{"id":6717,"date":"2015-09-02T12:15:08","date_gmt":"2015-09-02T09:15:08","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=6717"},"modified":"2015-12-16T11:23:56","modified_gmt":"2015-12-16T09:23:56","slug":"improving-shipscope-performance-websockets","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/","title":{"rendered":"Improving Shipscope Performance with WebSockets"},"content":{"rendered":"<p>Nearly a year ago, we released <a href=\"https:\/\/chrome.google.com\/webstore\/detail\/shipscope\/jdedmgopefelimgjceagffkeeiknclhh?hl=en\">Shipscope<\/a>, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our users, and I want to share some of that insight in this post.<\/p>\n<p>In order to provide frequent status updates, Shipscope requested project status from our API server every 10 seconds. Multiply this by a rapidly growing userbase, and it really amounted to something.<\/p>\n<p>There were two consequences of Shipscope\u2019s frequent polling:<\/p>\n<ol>\n<li>As Shipscope became more popular, the load on our API server grew. This was not a critical problem, but if we can reduce the number of requests to our API server while providing timely updates to users, then we should really try to do that.<\/li>\n<li>Shipscope stayed pretty busy in the user\u2019s browser, frequently requesting updates which most often would report no change to any build status. This is just wasteful use of CPU.<\/li>\n<\/ol>\n<p>In our web-based UI, we have been using <a href=\"https:\/\/pusher.com\/\">Pusher<\/a> for a while to provide build progress updates to the browser via WebSockets. Using Pusher, our web client never needs to poll the server for build progress updates. The server sends a message on the socket when progress occurs in the build. The client then requests build info from the server and updates the UI. This provides immediate updates without any unnecessary polling.<\/p>\n<p>For security reasons, we don\u2019t send full build information across the WebSocket. We don\u2019t want to send customer build info over a connection that could be unencrypted. Pusher allows payloads to be encrypted between the server and Pusher and then from Pusher to the client over the WebSocket.<\/p>\n<p>However, that transfer between the HTTP port and the WebSocket port is not encrypted. Rather than trying to encrypt the build info before we send it, we choose to limit the data that we send over the WebSocket. So, the client is notified of an update, and the full update info is fetched securely over an HTTPS connection.<\/p>\n<p>This approach has worked very well for us with our web client, so we decided we should give it a try with Shipscope. The first step is to get a Pusher app key, which is easy enough once you signup at <a href=\"https:\/\/pusher.com\/\">Pusher\u2019s website<\/a>.<\/p>\n<p>After installing Pusher\u2019s JavaScript client, Shipscope initializes a Pusher instance like so:<\/p>\n<pre class=\" brush:php\">pusher = new Pusher(PUSHER_APP_KEY, {\r\n    authEndpoint: 'https:\/\/codeship.com\/pusher\/auth',\r\n    auth: {\r\n      params: {\r\n        api_key: options.api_key\r\n      }\r\n    },\r\n    encrypted: true\r\n})<\/pre>\n<p>The <code>authEndpoint<\/code> and <code>auth<\/code> properties allows us to verify that Shipscope can only subscribe to updates for which the <code>api_key<\/code> authorizes it. <code>encrypted<\/code> ensures that messages to and from Pusher are not in plain text.<\/p>\n<p>Once we have a Pusher instance, we only need to subscribe to a channel. Each project has its own channel for publishing updates. So, if we are monitoring a project with id, 9876, then we\u2019ll subscribe like this:<\/p>\n<pre class=\" brush:php\">var channel = pusher.subscribe(\"private-project-9876\")<\/pre>\n<p>and finally,<\/p>\n<pre class=\" brush:php\">channel.bind(UPDATE_EVENT, onUpdate.bind(projectInfo))<\/pre>\n<p>will call <code>onUpdate()<\/code> with <code>projectInfo<\/code> bound to <code>this<\/code> every time a build starts or finishes in our project.<\/p>\n<p>That saves a lot of effort for both Shipscope running in your browser and our API server, which now only gets requests when something interesting has happened.<\/p>\n<p>One more thing that we get from Pusher is offline notification. If you somehow find yourself away from a wifi connection, the Pusher client fires a <code>state_change<\/code> event to let Shipscope know. We use this currently to change the Shipscope icon to red to let you know that Shipscope is offline.<\/p>\n<p>Setting this up is as simple as:<\/p>\n<pre class=\" brush:php\">pusher.connection.bind('state_change', function() {\r\n  if (pusher.connection.state == 'connected') {\r\n    chrome.browserAction.setIcon({path: 'img\/shipscope_icon_19.png'})\r\n    getShipscopeSummary()\r\n  } else {\r\n    chrome.browserAction.setIcon({path: 'img\/shipscope_icon_19_error.png'})\r\n    chrome.browserAction.setBadgeText({text: ''})\r\n  }\r\n})<\/pre>\n<p>WebSockets have made a big difference to both our server and the Shipscope Chrome extension. Pusher made WebSockets easy. You can install Shipscope from the <a href=\"https:\/\/chrome.google.com\/webstore\/detail\/shipscope\/jdedmgopefelimgjceagffkeeiknclhh?hl=en\">Chrome Web Store<\/a>. Shipscope is open source, so feel free to review the code at <a href=\"https:\/\/github.com\/codeship\/shipscope\">https:\/\/github.com\/codeship\/shipscope<\/a>.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/blog.codeship.com\/improving-shipscope-performance-websockets\/\">Improving Shipscope Performance with WebSockets<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/wcg\/\">WCG partner<\/a> Florian Motlik at the <a href=\"http:\/\/blog.codeship.com\/\">Codeship Blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Nearly a year ago, we released Shipscope, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our users, and I want to share some of that insight in this post. In order to provide frequent status updates, Shipscope requested project status from our API server every 10 seconds. &hellip;<\/p>\n","protected":false},"author":123,"featured_media":927,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[180],"class_list":["post-6717","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-development","tag-websockets"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Improving Shipscope Performance with WebSockets - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Nearly a year ago, we released Shipscope, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Improving Shipscope Performance with WebSockets - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Nearly a year ago, we released Shipscope, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-02T09:15:08+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2015-12-16T09:23:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"David McGaffin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@davidmcgaffin\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"David McGaffin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/\"},\"author\":{\"name\":\"David McGaffin\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/08140ec4254f9dbbd7b130f758086891\"},\"headline\":\"Improving Shipscope Performance with WebSockets\",\"datePublished\":\"2015-09-02T09:15:08+00:00\",\"dateModified\":\"2015-12-16T09:23:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/\"},\"wordCount\":626,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"keywords\":[\"WebSockets\"],\"articleSection\":[\"Web Dev\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/\",\"name\":\"Improving Shipscope Performance with WebSockets - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"datePublished\":\"2015-09-02T09:15:08+00:00\",\"dateModified\":\"2015-12-16T09:23:56+00:00\",\"description\":\"Nearly a year ago, we released Shipscope, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Web Dev\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/web-development\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Improving Shipscope Performance with WebSockets\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/08140ec4254f9dbbd7b130f758086891\",\"name\":\"David McGaffin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/1b6734eb8a1c1765a813f9bfd6700bdc7743a3914e8dca54fc3885186ea9a3b8?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/1b6734eb8a1c1765a813f9bfd6700bdc7743a3914e8dca54fc3885186ea9a3b8?s=96&d=mm&r=g\",\"caption\":\"David McGaffin\"},\"description\":\"David McGaffin is a senior engineer at Codeship. He likes coming up with new project ideas... and finishing some of them. He also likes learning new songs on his ukulele.\",\"sameAs\":[\"https:\/\/x.com\/davidmcgaffin\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/david-mcgaffin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Improving Shipscope Performance with WebSockets - Web Code Geeks - 2026","description":"Nearly a year ago, we released Shipscope, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/","og_locale":"en_US","og_type":"article","og_title":"Improving Shipscope Performance with WebSockets - Web Code Geeks - 2026","og_description":"Nearly a year ago, we released Shipscope, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our","og_url":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2015-09-02T09:15:08+00:00","article_modified_time":"2015-12-16T09:23:56+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","type":"image\/jpeg"}],"author":"David McGaffin","twitter_card":"summary_large_image","twitter_creator":"@davidmcgaffin","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"David McGaffin","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/"},"author":{"name":"David McGaffin","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/08140ec4254f9dbbd7b130f758086891"},"headline":"Improving Shipscope Performance with WebSockets","datePublished":"2015-09-02T09:15:08+00:00","dateModified":"2015-12-16T09:23:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/"},"wordCount":626,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","keywords":["WebSockets"],"articleSection":["Web Dev"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/","url":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/","name":"Improving Shipscope Performance with WebSockets - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","datePublished":"2015-09-02T09:15:08+00:00","dateModified":"2015-12-16T09:23:56+00:00","description":"Nearly a year ago, we released Shipscope, a Chrome extension for monitoring your projects on Codeship. We\u2019ve received some really good feedback from our","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/web-development\/improving-shipscope-performance-websockets\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Web Dev","item":"https:\/\/www.webcodegeeks.com\/category\/web-development\/"},{"@type":"ListItem","position":3,"name":"Improving Shipscope Performance with WebSockets"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/08140ec4254f9dbbd7b130f758086891","name":"David McGaffin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/1b6734eb8a1c1765a813f9bfd6700bdc7743a3914e8dca54fc3885186ea9a3b8?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b6734eb8a1c1765a813f9bfd6700bdc7743a3914e8dca54fc3885186ea9a3b8?s=96&d=mm&r=g","caption":"David McGaffin"},"description":"David McGaffin is a senior engineer at Codeship. He likes coming up with new project ideas... and finishing some of them. He also likes learning new songs on his ukulele.","sameAs":["https:\/\/x.com\/davidmcgaffin"],"url":"https:\/\/www.webcodegeeks.com\/author\/david-mcgaffin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/6717","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/123"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=6717"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/6717\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/927"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=6717"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=6717"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=6717"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}