{"action":"created","comment":{"url":"https://api.github.com/repos/elo7/tech-blog/pulls/comments/80559571","id":80559571,"diff_hunk":"@@ -0,0 +1,229 @@\n+---\n+date: 2016-08-09\n+category: front-end\n+tags:\n+  - javascript\n+  - progressive webapps\n+  - pwa\n+  - service workers\n+author: luiz\n+layout: post\n+title: A tecnologia por trás de *progressive web apps*\n+description: Se você trabalha com web, provavelmente já deve ter ouvido falar no termo *progressive web app*. Essa é uma tendência que vem aparecendo muito forte, impulsionada principalmente pela Google. O objetivo deste post vai ser explorar um pouco mais o lado técnico dessa tendência: como a tecnologia evoluiu para chegarmos nesse ponto, o que temos de ferramentas e o que ainda está por vir.\n+---\n+\n+Se você trabalha com web, provavelmente já deve ter ouvido falar no termo *progressive web app*. Essa é uma tendência que vem aparecendo muito forte, impulsionada principalmente pela Google, que até já organizou [um evento especificamente sobre esse tema](https://events.withgoogle.com/progressive-web-app-dev-summit/).\n+\n+O [Fabricio Teixeira](http://fabricio.nu/) já escreveu [um post explicando bem o **conceito** de *progressive web apps*](http://arquiteturadeinformacao.com/mobile/o-que-sao-progressive-web-apps/). O objetivo aqui, então, vai ser explorar um pouco mais o lado técnico dessa tendência: como a tecnologia evoluiu para chegarmos nesse ponto, o que temos de ferramentas e o que ainda está por vir.\n+\n+## Tudo começou há um tempo atrás...\n+\n+A ideia de tentar transformar um site em algo mais próximo de um aplicativo não é tão nova quanto parece. A partir do momento em que os celulares começaram a ser capazes de ter aplicativos com boa usabilidade, os provedores de conteúdo e de serviços começaram a disponibilizar aplicativos para melhorar a experiência de seus usuários. A melhora da experiência vinha por conta de uma melhor **integração com o sistema nativo** e **performance**.\n+\n+Conforme os desenvolvedores foram percebendo a importância desses fatores para uma melhor experiência do usuário, começaram a surgir algumas especificações que procuram tornar os sites mais próximos do sistema operacional, com acesso a mais recursos do dispositivo e sem tanta dependência de conectividade para funcionar. Dentre elas, podemos citar:\n+\n+- APIs de acesso a sensores do dispositivo\n+    - Geolocalização (`navigator.geolocation`)\n+    - Câmera/microfone (`navigator.getUserMedia`)\n+    - Giroscópio/acelerômetro (eventos `deviceorientation` e `devicemotion`, respectivamente)\n+- LocalStorage/SessionStorage (`window.localStorage`/`window.sessionStorage`)\n+- Indexed Database (`window.indexedDB`)\n+- Manifesto para aplicações web (`link rel=\"manifest\"`)\n+- A falecida especificação de cache de aplicação (atributo `manifest` na tag `html`)\n+- A especificação de `CacheStorage`, que veio substituir o cache de aplicação (`window.caches`)\n+- Service workers (`navigator.serviceWorker`)\n+\n+Neste post, vamos focar nas APIs que permitem uma experiência \"app\" para qualquer tipo de site, que são as APIs de armazenamento (LocalStorage/SessionStorage, Indexed Database, Cache de aplicação e CacheStorage), o manifesto para aplicações web e os *service workers*.\n+\n+### LocalStorage e SessionStorage\n+\n+Armazenar informações sobre o usuário na máquina dele sempre foi um requisito técnico importante para conseguirmos fornecer uma experiência personalizada para quem usa nosso site ou aplicação. Por muito tempo, os *cookies* do navegador cumpriram esse papel, mas com algumas limitações.\n+\n+Os *cookies* foram projetados para facilitar o envio de informações relativas a um usuário para o servidor da aplicação; eles são enviados a cada requisição feita ao servidor e, portanto, não podem conter muita informação. Por isso, normalmente eles incluem apenas um código que identifica o usuário, e o resto das informações personalizadas, tais como nome de usuário, avatar, preferências etc. ficam todas no servidor.\n+\n+No entanto, com a possibilidade de criar aplicações cada vez mais ricas do lado do cliente, com navegadores mais poderosos e bibliotecas JavaScript mais sofisticadas, surgiu a necessidade de armazenar mais informações no navegador do cliente. Como os *cookies* precisam ser leves, era necessário surgir algo com esse propósito específico; surgiam então as especificações de LocalStorage e SessionStorage.\n+\n+Ambas são muito parecidas: especificam um objeto no escopo global do JavaScript que permite associar uma chave e um valor, ambos textuais. Esse objeto é único por domínio, ou seja, sua aplicação pode usá-lo tanto para armazenar informações específicas de uma página como informações mais genéricas.\n+\n+A diferença entre elas está no tempo de vida da informação armazenada nesses objetos. O objeto `window.localStorage` armazena as informações indefinidamente, até que o usuário apague-as explicitamente por meio das configurações do navegador. Já o objeto `window.sessionStorage` armazena as informações até que você feche a aba ou janela do navegador.\n+\n+Por serem objetos de armazenamento exclusivamente local, o LocalStorage e o SessionStorage têm capacidade de armazenamento de informações muito maior do que os *cookies*, sem afetar em nada a velocidade de comunicação com o servidor. A capacidade exata varia de acordo com o navegador, mas fica na faixa dos megabytes.\n+\n+### Indexed Database\n+\n+Ter um espaço de armazenamento no cliente já permite criar aplicações muito mais ricas no cliente. Porém, conforme a complexidade da aplicação cresce, cresce também a complexidade dos dados que ela precisa armazenar e consultar. Surge, então, a necessidade de algo mais sofisticado que o LocalStorage ou o SessionStorage, que permita o armazenamento e a consulta de dados mais estruturados.\n+\n+Nessa linha, surgiram duas especificações em paralelo: a especificação *Web SQL Database* e a especificação *Indexed Database*. A primeira, implementada experimentalmente nos navegadores baseados em WebKit (Chrome, Safari, Opera etc.), tenta trazer uma base de dados com suporte a SQL para o navegador. A segunda, que acabou se tornando a recomendação da W3C e que já é [bem suportada por todos os navegadores mais modernos](http://caniuse.com/#feat=indexeddb), segue uma abordagem diferenciada, com uma API de mais baixo nível de acesso aos dados armazenados.\n+\n+A especificação *Indexed Database* acabou tornando-se a escolha oficial para armazenamento de dados pela falta de um padrão claro na linguagem SQL e pelo poder que uma API de mais baixo nível fornece aos desenvolvedores ([você pode ler mais sobre esses pontos no blog de desenvolvedores da Mozilla](https://hacks.mozilla.org/2010/06/beyond-html5-database-apis-and-the-road-to-indexeddb/)). Com essa especificação, é possível implementar inúmeras bibliotecas de mais alto nível sobre ela, inclusive bibliotecas que dão suporte a algum tipo de SQL.\n+\n+Tendo uma base de dados sofisticada como uma *Indexed Database* disponível, já é possível criar aplicações muito sofisticadas no navegador apenas, sem a necessidade de acessar o servidor o tempo todo. No entanto, a experiência do usuário não se aproxima da experiência de uso de uma aplicação nativa apenas com poder de processamento. É necessário lidar ainda com a parte mais visual da experiência, além dos problemas de conectividade inerentes aos dispositivos móveis. Afinal, mesmo as aplicações mais sofisticadas precisam sincronizar os dados com um servidor de vez em quando. As próximas especificações lidam justamente com essas questões.\n+\n+### Manifesto para aplicações web\n+\n+Quando acessamos uma página da web, ela é aberta dentro de um navegador. O navegador adiciona, ao redor do conteúdo, barra de endereços, menu, ícones de extensões, barra de status etc. Tudo isso atrapalha a experiência do usuário quando queremos que ele realize tarefas na nossa aplicação, não é verdade? Compare com a experiência de acessar um aplicativo: toda a tela pode ser usada por ele, tornando a experiência mais imersiva e aproveitando melhor o espaço de tela, que é restrito.\n+\n+![Barra de endereços do navegador tomando parte do espaço disponível](../images/tecnologia-pwa-4.png)\n+![Usando todo o espaço da tela](../images/tecnologia-pwa-3.png)\n+\n+Fora isso, é comum que os usuários criem atalhos para seus aplicativos favoritos. No entanto, é difícil ver atalhos para sites. Por que? No Google Chrome, por exemplo, existe a opção de adicionar à tela inicial um atalho para o site que estamos visitando. Mas, quando fazemos isso num site simples, o atalho não é tão fácil de identificar quanto um atalho de aplicativo.\n+\n+![Atalho de um site comum versus atalho de um site com manifesto configurado](../images/tecnologia-pwa-5.png)\n+\n+Para melhorar esses pontos, surgiu a especificação do manifesto para aplicações web. Com ele, você consegue especificar se seu site deve ser visualizado com a barra de endereços ou em tela cheia; qual orientação de tela é mais adequada para seu site (retrato, paisagem ou indiferente); qual a cor principal do tema de cores do site (útil para customizar a cor da janela do navegador); e qual nome e ícone deve ter o atalho na área de trabalho.\n+\n+Usar essa especificação é simples: basta escrever um arquivo no formato JSON seguindo a especificação:\n+\n+```json\n+{\n+    \"name\": \"Elo7\",\n+    \"short_name\": \"Elo7\",\n+    \"icons\": [\n+        {\n+            \"src\": \"//images.elo7.com.br/marketplace/assets/web/common/png/favicon/32x32-negative.png\",\n+            \"sizes\": \"32x32\",\n+            \"type\": \"image/png\",\n+            \"density\": 0.75\n+        },\n+        {\n+            \"src\": \"//images.elo7.com.br/marketplace/assets/web/common/png/favicon/48x48-negative.png\",\n+            \"sizes\": \"48x48\",\n+            \"type\": \"image/png\",\n+            \"density\": 1.0\n+        },\n+        {\n+            \"src\": \"//images.elo7.com.br/marketplace/assets/web/common/png/favicon/64x64-negative.png\",\n+            \"sizes\": \"64x64\",\n+            \"type\": \"image/png\",\n+            \"density\": 1.5\n+        },\n+    ],\n+    \"start_url\": \"/?elo7_source=web_app_manifest\",\n+    \"display\": \"standalone\",\n+    \"orientation\": \"portrait\",\n+    \"theme_color\": \"#FDB933\",\n+    \"background_color\": \"#FDB933\"\n+}\n+```\n+\n+e referenciá-lo nas páginas de seu site com a tag `<link>`:\n+\n+```html\n+<link rel=\"manifest\" href=\"manifest.json\">\n+```\n+\n+Com isso, sua aplicação web já começa a ganhar uma aparência de aplicativo! Mas a experiência de navegação ainda é de um site: uma conexão ruim afeta diretamente a experiência.","path":"src/posts/a-tecnologia-por-tras-de-progressive-web-apps.html.md","position":115,"original_position":115,"commit_id":"bdaa6cdd061deeb37b1e48dbf898c5681f24622f","original_commit_id":"bdaa6cdd061deeb37b1e48dbf898c5681f24622f","user":{"login":"rapahaeru","id":3389749,"avatar_url":"https://avatars.githubusercontent.com/u/3389749?v=3","gravatar_id":"","url":"https://api.github.com/users/rapahaeru","html_url":"https://github.com/rapahaeru","followers_url":"https://api.github.com/users/rapahaeru/followers","following_url":"https://api.github.com/users/rapahaeru/following{/other_user}","gists_url":"https://api.github.com/users/rapahaeru/gists{/gist_id}","starred_url":"https://api.github.com/users/rapahaeru/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rapahaeru/subscriptions","organizations_url":"https://api.github.com/users/rapahaeru/orgs","repos_url":"https://api.github.com/users/rapahaeru/repos","events_url":"https://api.github.com/users/rapahaeru/events{/privacy}","received_events_url":"https://api.github.com/users/rapahaeru/received_events","type":"User","site_admin":false},"body":"Que tal explicar no parágrafo anterior, em que são enumeradas as possibilidades de configuração?","created_at":"2016-09-26T20:01:37Z","updated_at":"2016-09-26T20:01:37Z","html_url":"https://github.com/elo7/tech-blog/pull/21#discussion_r80559571","pull_request_url":"https://api.github.com/repos/elo7/tech-blog/pulls/21","_links":{"self":{"href":"https://api.github.com/repos/elo7/tech-blog/pulls/comments/80559571"},"html":{"href":"https://github.com/elo7/tech-blog/pull/21#discussion_r80559571"},"pull_request":{"href":"https://api.github.com/repos/elo7/tech-blog/pulls/21"}}},"pull_request":{"url":"https://api.github.com/repos/elo7/tech-blog/pulls/21","id":86780878,"html_url":"https://github.com/elo7/tech-blog/pull/21","diff_url":"https://github.com/elo7/tech-blog/pull/21.diff","patch_url":"https://github.com/elo7/tech-blog/pull/21.patch","issue_url":"https://api.github.com/repos/elo7/tech-blog/issues/21","number":21,"state":"open","locked":false,"title":"A tecnologia por trás das progressive web apps","user":{"login":"rapahaeru","id":3389749,"avatar_url":"https://avatars.githubusercontent.com/u/3389749?v=3","gravatar_id":"","url":"https://api.github.com/users/rapahaeru","html_url":"https://github.com/rapahaeru","followers_url":"https://api.github.com/users/rapahaeru/followers","following_url":"https://api.github.com/users/rapahaeru/following{/other_user}","gists_url":"https://api.github.com/users/rapahaeru/gists{/gist_id}","starred_url":"https://api.github.com/users/rapahaeru/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rapahaeru/subscriptions","organizations_url":"https://api.github.com/users/rapahaeru/orgs","repos_url":"https://api.github.com/users/rapahaeru/repos","events_url":"https://api.github.com/users/rapahaeru/events{/privacy}","received_events_url":"https://api.github.com/users/rapahaeru/received_events","type":"User","site_admin":false},"body":"✋  @tcelestino\r\n\r\n@luiz","created_at":"2016-09-26T17:03:57Z","updated_at":"2016-09-26T20:01:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"48f8e0627dfd3cefe9ef2ab9cffadb759aa49837","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/elo7/tech-blog/pulls/21/commits","review_comments_url":"https://api.github.com/repos/elo7/tech-blog/pulls/21/comments","review_comment_url":"https://api.github.com/repos/elo7/tech-blog/pulls/comments{/number}","comments_url":"https://api.github.com/repos/elo7/tech-blog/issues/21/comments","statuses_url":"https://api.github.com/repos/elo7/tech-blog/statuses/bdaa6cdd061deeb37b1e48dbf898c5681f24622f","head":{"label":"elo7:pwa","ref":"pwa","sha":"bdaa6cdd061deeb37b1e48dbf898c5681f24622f","user":{"login":"elo7","id":1469534,"avatar_url":"https://avatars.githubusercontent.com/u/1469534?v=3","gravatar_id":"","url":"https://api.github.com/users/elo7","html_url":"https://github.com/elo7","followers_url":"https://api.github.com/users/elo7/followers","following_url":"https://api.github.com/users/elo7/following{/other_user}","gists_url":"https://api.github.com/users/elo7/gists{/gist_id}","starred_url":"https://api.github.com/users/elo7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elo7/subscriptions","organizations_url":"https://api.github.com/users/elo7/orgs","repos_url":"https://api.github.com/users/elo7/repos","events_url":"https://api.github.com/users/elo7/events{/privacy}","received_events_url":"https://api.github.com/users/elo7/received_events","type":"Organization","site_admin":false},"repo":{"id":61552932,"name":"tech-blog","full_name":"elo7/tech-blog","owner":{"login":"elo7","id":1469534,"avatar_url":"https://avatars.githubusercontent.com/u/1469534?v=3","gravatar_id":"","url":"https://api.github.com/users/elo7","html_url":"https://github.com/elo7","followers_url":"https://api.github.com/users/elo7/followers","following_url":"https://api.github.com/users/elo7/following{/other_user}","gists_url":"https://api.github.com/users/elo7/gists{/gist_id}","starred_url":"https://api.github.com/users/elo7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elo7/subscriptions","organizations_url":"https://api.github.com/users/elo7/orgs","repos_url":"https://api.github.com/users/elo7/repos","events_url":"https://api.github.com/users/elo7/events{/privacy}","received_events_url":"https://api.github.com/users/elo7/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/elo7/tech-blog","description":"Blog técnico do Elo7","fork":false,"url":"https://api.github.com/repos/elo7/tech-blog","forks_url":"https://api.github.com/repos/elo7/tech-blog/forks","keys_url":"https://api.github.com/repos/elo7/tech-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/elo7/tech-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/elo7/tech-blog/teams","hooks_url":"https://api.github.com/repos/elo7/tech-blog/hooks","issue_events_url":"https://api.github.com/repos/elo7/tech-blog/issues/events{/number}","events_url":"https://api.github.com/repos/elo7/tech-blog/events","assignees_url":"https://api.github.com/repos/elo7/tech-blog/assignees{/user}","branches_url":"https://api.github.com/repos/elo7/tech-blog/branches{/branch}","tags_url":"https://api.github.com/repos/elo7/tech-blog/tags","blobs_url":"https://api.github.com/repos/elo7/tech-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/elo7/tech-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/elo7/tech-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/elo7/tech-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/elo7/tech-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/elo7/tech-blog/languages","stargazers_url":"https://api.github.com/repos/elo7/tech-blog/stargazers","contributors_url":"https://api.github.com/repos/elo7/tech-blog/contributors","subscribers_url":"https://api.github.com/repos/elo7/tech-blog/subscribers","subscription_url":"https://api.github.com/repos/elo7/tech-blog/subscription","commits_url":"https://api.github.com/repos/elo7/tech-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/elo7/tech-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/elo7/tech-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/elo7/tech-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/elo7/tech-blog/contents/{+path}","compare_url":"https://api.github.com/repos/elo7/tech-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/elo7/tech-blog/merges","archive_url":"https://api.github.com/repos/elo7/tech-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/elo7/tech-blog/downloads","issues_url":"https://api.github.com/repos/elo7/tech-blog/issues{/number}","pulls_url":"https://api.github.com/repos/elo7/tech-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/elo7/tech-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/elo7/tech-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/elo7/tech-blog/labels{/name}","releases_url":"https://api.github.com/repos/elo7/tech-blog/releases{/id}","deployments_url":"https://api.github.com/repos/elo7/tech-blog/deployments","created_at":"2016-06-20T14:14:12Z","updated_at":"2016-08-03T16:47:40Z","pushed_at":"2016-09-26T19:05:13Z","git_url":"git://github.com/elo7/tech-blog.git","ssh_url":"git@github.com:elo7/tech-blog.git","clone_url":"https://github.com/elo7/tech-blog.git","svn_url":"https://github.com/elo7/tech-blog","homepage":null,"size":4119,"stargazers_count":0,"watchers_count":0,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":9,"forks":0,"open_issues":9,"watchers":0,"default_branch":"master"}},"base":{"label":"elo7:master","ref":"master","sha":"d42621862316cdd880ab6ca7997d65248ea059e6","user":{"login":"elo7","id":1469534,"avatar_url":"https://avatars.githubusercontent.com/u/1469534?v=3","gravatar_id":"","url":"https://api.github.com/users/elo7","html_url":"https://github.com/elo7","followers_url":"https://api.github.com/users/elo7/followers","following_url":"https://api.github.com/users/elo7/following{/other_user}","gists_url":"https://api.github.com/users/elo7/gists{/gist_id}","starred_url":"https://api.github.com/users/elo7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elo7/subscriptions","organizations_url":"https://api.github.com/users/elo7/orgs","repos_url":"https://api.github.com/users/elo7/repos","events_url":"https://api.github.com/users/elo7/events{/privacy}","received_events_url":"https://api.github.com/users/elo7/received_events","type":"Organization","site_admin":false},"repo":{"id":61552932,"name":"tech-blog","full_name":"elo7/tech-blog","owner":{"login":"elo7","id":1469534,"avatar_url":"https://avatars.githubusercontent.com/u/1469534?v=3","gravatar_id":"","url":"https://api.github.com/users/elo7","html_url":"https://github.com/elo7","followers_url":"https://api.github.com/users/elo7/followers","following_url":"https://api.github.com/users/elo7/following{/other_user}","gists_url":"https://api.github.com/users/elo7/gists{/gist_id}","starred_url":"https://api.github.com/users/elo7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elo7/subscriptions","organizations_url":"https://api.github.com/users/elo7/orgs","repos_url":"https://api.github.com/users/elo7/repos","events_url":"https://api.github.com/users/elo7/events{/privacy}","received_events_url":"https://api.github.com/users/elo7/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/elo7/tech-blog","description":"Blog técnico do Elo7","fork":false,"url":"https://api.github.com/repos/elo7/tech-blog","forks_url":"https://api.github.com/repos/elo7/tech-blog/forks","keys_url":"https://api.github.com/repos/elo7/tech-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/elo7/tech-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/elo7/tech-blog/teams","hooks_url":"https://api.github.com/repos/elo7/tech-blog/hooks","issue_events_url":"https://api.github.com/repos/elo7/tech-blog/issues/events{/number}","events_url":"https://api.github.com/repos/elo7/tech-blog/events","assignees_url":"https://api.github.com/repos/elo7/tech-blog/assignees{/user}","branches_url":"https://api.github.com/repos/elo7/tech-blog/branches{/branch}","tags_url":"https://api.github.com/repos/elo7/tech-blog/tags","blobs_url":"https://api.github.com/repos/elo7/tech-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/elo7/tech-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/elo7/tech-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/elo7/tech-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/elo7/tech-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/elo7/tech-blog/languages","stargazers_url":"https://api.github.com/repos/elo7/tech-blog/stargazers","contributors_url":"https://api.github.com/repos/elo7/tech-blog/contributors","subscribers_url":"https://api.github.com/repos/elo7/tech-blog/subscribers","subscription_url":"https://api.github.com/repos/elo7/tech-blog/subscription","commits_url":"https://api.github.com/repos/elo7/tech-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/elo7/tech-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/elo7/tech-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/elo7/tech-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/elo7/tech-blog/contents/{+path}","compare_url":"https://api.github.com/repos/elo7/tech-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/elo7/tech-blog/merges","archive_url":"https://api.github.com/repos/elo7/tech-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/elo7/tech-blog/downloads","issues_url":"https://api.github.com/repos/elo7/tech-blog/issues{/number}","pulls_url":"https://api.github.com/repos/elo7/tech-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/elo7/tech-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/elo7/tech-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/elo7/tech-blog/labels{/name}","releases_url":"https://api.github.com/repos/elo7/tech-blog/releases{/id}","deployments_url":"https://api.github.com/repos/elo7/tech-blog/deployments","created_at":"2016-06-20T14:14:12Z","updated_at":"2016-08-03T16:47:40Z","pushed_at":"2016-09-26T19:05:13Z","git_url":"git://github.com/elo7/tech-blog.git","ssh_url":"git@github.com:elo7/tech-blog.git","clone_url":"https://github.com/elo7/tech-blog.git","svn_url":"https://github.com/elo7/tech-blog","homepage":null,"size":4119,"stargazers_count":0,"watchers_count":0,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":9,"forks":0,"open_issues":9,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/elo7/tech-blog/pulls/21"},"html":{"href":"https://github.com/elo7/tech-blog/pull/21"},"issue":{"href":"https://api.github.com/repos/elo7/tech-blog/issues/21"},"comments":{"href":"https://api.github.com/repos/elo7/tech-blog/issues/21/comments"},"review_comments":{"href":"https://api.github.com/repos/elo7/tech-blog/pulls/21/comments"},"review_comment":{"href":"https://api.github.com/repos/elo7/tech-blog/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/elo7/tech-blog/pulls/21/commits"},"statuses":{"href":"https://api.github.com/repos/elo7/tech-blog/statuses/bdaa6cdd061deeb37b1e48dbf898c5681f24622f"}}}}
{"actor":{"display_login":"rapahaeru"}}