{"action":"created","comment":{"url":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/comments/37671077","id":37671077,"diff_hunk":"@@ -0,0 +1,107 @@\n+---\n+layout: post\n+\n+title: \"Dreamforce Session Explorer - Story behind the app\"\n+tags: [Templating, UnderscoreJS]\n+\n+author:\n+  name: Vincent Séguin\n+  bio: Team Lead - Cloud\n+  twitter: VincentSeguin\n+  image: vseguin.jpg\n+---\n+\n+As some of you guys may know, Dreamforce is one of the biggest event in the enterprise software industry. For the #DF15 edition, we wanted to do a little something different than what we had done previously.\n+\n+<!-- more -->\n+\n+We wanted to create something by combining marketing and R&D efforts. There were a few simple rules to follow :\n+* Be able to create something in about 1.5 months or less.\n+* Do not replicate/copy Salesforce’s Dreamforce app - complement it\n+* Try some new technology or frameworks\n+* Showcase Coveo’s capabilities but be distant enough of Coveo for Salesforce\n+* Be awesome\n+* Have fun\n+\n+The project was also intended to be a huge hackathon on evenings and weekends… it ended up being a lot more.\n+\n+## The Design\n+\n+Our timeframe was quite restricted! We had to think of how to build something awesome really quickly. Numerous ideas were thrown on the table of what the app could be : should we leverage the Dreamforce agenda? Be more social-oriented? Make a party app?  At some point, we even thought about creating a real-time social media aggregator on top of Dreamforce… Let’s say the discussions were flowing!\n+\n+Leveraging the agenda would have been really cool, but it would have implied authentication to Salesforce which we just didn’t have time to build. We also explored the Dreamforce website to see what was available at that point. We then decided to do what Coveo has the capability to do: create relationships between data you wouldn’t even think they exist. By leveraging Dreamforce’s sessions, themes and speakers, we could associate them with external content such as Twitter, LinkedIn, SlideShare etc. The idea was born!\n+\n+Quickly, our power UX team came with an original idea : everything would be hexagonal-oriented. (Nothing to make a developer life easy…)  We had to make quite a lot of iterations on mockups to have something that would satisfy everyone. You can see that from the first iteration from the actual result… it quite changed.\n+\n+![image]({{ site.baseurl }}/images/20150821/dreamforce-iterations-dashboard-01.png)\n+![image]({{ site.baseurl }}/images/20150821/dreamforce-iterations-fiche-02.png)\n+![image]({{ site.baseurl }}/images/20150821/dreamforce-iterations-fiche-04.png)\n+![image]({{ site.baseurl }}/images/20150821/actualapp.png)\n+\n+## Techno techno techno\n+\n+Lots of questions to ask here : Is it client-side only or do we want a back-end as well? Which language? Should it be a native app for mobiles? Which framework?\n+\n+At Coveo, we have our own Javascript UI Framework (JS UI to make it short) that enables people to easily create custom search pages. Problem is, that it comes with a whole lot of functionalities that we did not need in our app, the app concept is really different from what we usually do. Quickly enough, we stripped out what we call the Search Endpoint (module responsible to build and executes queries on the Coveo Cloud platform) from the JS UI to make our app the lightest possible. Obviously, we were not going to write everything in pure JavaScript without any external help… so came the fatidic time to choose a JS framework to build on top of it. We explored a few things here and there (and also invoked the possibility to do it in TypeScript just like our actual Coveo frameworks)... and decided to use the most trending, buzzwordy, a la mode javascript framework of the week, that is React.\n+\n+React comes with a really different architecture traditional developers are not used to. We also added the classic tools to make the development easier such as gulp and webpack… and quickly added react-router in the project to manage our URLs. Some parts of the app were really suiting well for React, such as session details (including related/external content)... but others such as the complete honeycomb view were more… let’s say tricky.\n+\n+We tried to respect the React architecture and split into most component possibles. For instance, in the Hexagon Details page, you can find components for :\n+* Whole page\n+* Hexagonal header\n+* Session/Keynote excerpts\n+* Result list and result list items\n+* A variety of templates for each different kind of content\n+and so on. It would have been really fun to do it in TypeScript instead of JavaScript, but with our early experiences, it felt like the React/Typescript integration was not mature enough to build something without doing some hacks on Typescript itself (this [github issue](https://github.com/Microsoft/TypeScript/issues/3203) covers the discussion of it). ","path":"_posts/2015-08-21-dreamforce-session-explorer.md","position":55,"original_position":55,"commit_id":"821ffcbd376786c38c5cc5a3a2b1b2d5df9228a5","original_commit_id":"821ffcbd376786c38c5cc5a3a2b1b2d5df9228a5","user":{"login":"GuiSim","id":2000390,"avatar_url":"https://avatars.githubusercontent.com/u/2000390?v=3","gravatar_id":"","url":"https://api.github.com/users/GuiSim","html_url":"https://github.com/GuiSim","followers_url":"https://api.github.com/users/GuiSim/followers","following_url":"https://api.github.com/users/GuiSim/following{/other_user}","gists_url":"https://api.github.com/users/GuiSim/gists{/gist_id}","starred_url":"https://api.github.com/users/GuiSim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GuiSim/subscriptions","organizations_url":"https://api.github.com/users/GuiSim/orgs","repos_url":"https://api.github.com/users/GuiSim/repos","events_url":"https://api.github.com/users/GuiSim/events{/privacy}","received_events_url":"https://api.github.com/users/GuiSim/received_events","type":"User","site_admin":false},"body":"\"covers most of it\" ?","created_at":"2015-08-21T19:46:41Z","updated_at":"2015-08-21T19:46:41Z","html_url":"https://github.com/Coveo/source.coveo.com/pull/56#discussion_r37671077","pull_request_url":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56","_links":{"self":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/comments/37671077"},"html":{"href":"https://github.com/Coveo/source.coveo.com/pull/56#discussion_r37671077"},"pull_request":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56"}}},"pull_request":{"url":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56","id":43072329,"html_url":"https://github.com/Coveo/source.coveo.com/pull/56","diff_url":"https://github.com/Coveo/source.coveo.com/pull/56.diff","patch_url":"https://github.com/Coveo/source.coveo.com/pull/56.patch","issue_url":"https://api.github.com/repos/Coveo/source.coveo.com/issues/56","number":56,"state":"open","locked":false,"title":"Add DF post","user":{"login":"vseguin","id":1884896,"avatar_url":"https://avatars.githubusercontent.com/u/1884896?v=3","gravatar_id":"","url":"https://api.github.com/users/vseguin","html_url":"https://github.com/vseguin","followers_url":"https://api.github.com/users/vseguin/followers","following_url":"https://api.github.com/users/vseguin/following{/other_user}","gists_url":"https://api.github.com/users/vseguin/gists{/gist_id}","starred_url":"https://api.github.com/users/vseguin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vseguin/subscriptions","organizations_url":"https://api.github.com/users/vseguin/orgs","repos_url":"https://api.github.com/users/vseguin/repos","events_url":"https://api.github.com/users/vseguin/events{/privacy}","received_events_url":"https://api.github.com/users/vseguin/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-08-21T19:26:23Z","updated_at":"2015-08-21T19:46:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b18a2a507162bb9e2414bdbb651ca6fcedfa0acd","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56/commits","review_comments_url":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56/comments","review_comment_url":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Coveo/source.coveo.com/issues/56/comments","statuses_url":"https://api.github.com/repos/Coveo/source.coveo.com/statuses/821ffcbd376786c38c5cc5a3a2b1b2d5df9228a5","head":{"label":"vseguin:gh-pages","ref":"gh-pages","sha":"821ffcbd376786c38c5cc5a3a2b1b2d5df9228a5","user":{"login":"vseguin","id":1884896,"avatar_url":"https://avatars.githubusercontent.com/u/1884896?v=3","gravatar_id":"","url":"https://api.github.com/users/vseguin","html_url":"https://github.com/vseguin","followers_url":"https://api.github.com/users/vseguin/followers","following_url":"https://api.github.com/users/vseguin/following{/other_user}","gists_url":"https://api.github.com/users/vseguin/gists{/gist_id}","starred_url":"https://api.github.com/users/vseguin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vseguin/subscriptions","organizations_url":"https://api.github.com/users/vseguin/orgs","repos_url":"https://api.github.com/users/vseguin/repos","events_url":"https://api.github.com/users/vseguin/events{/privacy}","received_events_url":"https://api.github.com/users/vseguin/received_events","type":"User","site_admin":false},"repo":{"id":41173015,"name":"source.coveo.com","full_name":"vseguin/source.coveo.com","owner":{"login":"vseguin","id":1884896,"avatar_url":"https://avatars.githubusercontent.com/u/1884896?v=3","gravatar_id":"","url":"https://api.github.com/users/vseguin","html_url":"https://github.com/vseguin","followers_url":"https://api.github.com/users/vseguin/followers","following_url":"https://api.github.com/users/vseguin/following{/other_user}","gists_url":"https://api.github.com/users/vseguin/gists{/gist_id}","starred_url":"https://api.github.com/users/vseguin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vseguin/subscriptions","organizations_url":"https://api.github.com/users/vseguin/orgs","repos_url":"https://api.github.com/users/vseguin/repos","events_url":"https://api.github.com/users/vseguin/events{/privacy}","received_events_url":"https://api.github.com/users/vseguin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/vseguin/source.coveo.com","description":"Our technical blog.","fork":true,"url":"https://api.github.com/repos/vseguin/source.coveo.com","forks_url":"https://api.github.com/repos/vseguin/source.coveo.com/forks","keys_url":"https://api.github.com/repos/vseguin/source.coveo.com/keys{/key_id}","collaborators_url":"https://api.github.com/repos/vseguin/source.coveo.com/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/vseguin/source.coveo.com/teams","hooks_url":"https://api.github.com/repos/vseguin/source.coveo.com/hooks","issue_events_url":"https://api.github.com/repos/vseguin/source.coveo.com/issues/events{/number}","events_url":"https://api.github.com/repos/vseguin/source.coveo.com/events","assignees_url":"https://api.github.com/repos/vseguin/source.coveo.com/assignees{/user}","branches_url":"https://api.github.com/repos/vseguin/source.coveo.com/branches{/branch}","tags_url":"https://api.github.com/repos/vseguin/source.coveo.com/tags","blobs_url":"https://api.github.com/repos/vseguin/source.coveo.com/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/vseguin/source.coveo.com/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/vseguin/source.coveo.com/git/refs{/sha}","trees_url":"https://api.github.com/repos/vseguin/source.coveo.com/git/trees{/sha}","statuses_url":"https://api.github.com/repos/vseguin/source.coveo.com/statuses/{sha}","languages_url":"https://api.github.com/repos/vseguin/source.coveo.com/languages","stargazers_url":"https://api.github.com/repos/vseguin/source.coveo.com/stargazers","contributors_url":"https://api.github.com/repos/vseguin/source.coveo.com/contributors","subscribers_url":"https://api.github.com/repos/vseguin/source.coveo.com/subscribers","subscription_url":"https://api.github.com/repos/vseguin/source.coveo.com/subscription","commits_url":"https://api.github.com/repos/vseguin/source.coveo.com/commits{/sha}","git_commits_url":"https://api.github.com/repos/vseguin/source.coveo.com/git/commits{/sha}","comments_url":"https://api.github.com/repos/vseguin/source.coveo.com/comments{/number}","issue_comment_url":"https://api.github.com/repos/vseguin/source.coveo.com/issues/comments{/number}","contents_url":"https://api.github.com/repos/vseguin/source.coveo.com/contents/{+path}","compare_url":"https://api.github.com/repos/vseguin/source.coveo.com/compare/{base}...{head}","merges_url":"https://api.github.com/repos/vseguin/source.coveo.com/merges","archive_url":"https://api.github.com/repos/vseguin/source.coveo.com/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/vseguin/source.coveo.com/downloads","issues_url":"https://api.github.com/repos/vseguin/source.coveo.com/issues{/number}","pulls_url":"https://api.github.com/repos/vseguin/source.coveo.com/pulls{/number}","milestones_url":"https://api.github.com/repos/vseguin/source.coveo.com/milestones{/number}","notifications_url":"https://api.github.com/repos/vseguin/source.coveo.com/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/vseguin/source.coveo.com/labels{/name}","releases_url":"https://api.github.com/repos/vseguin/source.coveo.com/releases{/id}","created_at":"2015-08-21T19:13:54Z","updated_at":"2015-08-21T19:13:54Z","pushed_at":"2015-08-21T19:25:26Z","git_url":"git://github.com/vseguin/source.coveo.com.git","ssh_url":"git@github.com:vseguin/source.coveo.com.git","clone_url":"https://github.com/vseguin/source.coveo.com.git","svn_url":"https://github.com/vseguin/source.coveo.com","homepage":"source.coveo.com","size":18004,"stargazers_count":0,"watchers_count":0,"language":"CSS","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"gh-pages"}},"base":{"label":"Coveo:gh-pages","ref":"gh-pages","sha":"aa2eacc2b28736d3315926e5b827c5182f7835f8","user":{"login":"Coveo","id":8632328,"avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=3","gravatar_id":"","url":"https://api.github.com/users/Coveo","html_url":"https://github.com/Coveo","followers_url":"https://api.github.com/users/Coveo/followers","following_url":"https://api.github.com/users/Coveo/following{/other_user}","gists_url":"https://api.github.com/users/Coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/Coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Coveo/subscriptions","organizations_url":"https://api.github.com/users/Coveo/orgs","repos_url":"https://api.github.com/users/Coveo/repos","events_url":"https://api.github.com/users/Coveo/events{/privacy}","received_events_url":"https://api.github.com/users/Coveo/received_events","type":"Organization","site_admin":false},"repo":{"id":23815317,"name":"source.coveo.com","full_name":"Coveo/source.coveo.com","owner":{"login":"Coveo","id":8632328,"avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=3","gravatar_id":"","url":"https://api.github.com/users/Coveo","html_url":"https://github.com/Coveo","followers_url":"https://api.github.com/users/Coveo/followers","following_url":"https://api.github.com/users/Coveo/following{/other_user}","gists_url":"https://api.github.com/users/Coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/Coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Coveo/subscriptions","organizations_url":"https://api.github.com/users/Coveo/orgs","repos_url":"https://api.github.com/users/Coveo/repos","events_url":"https://api.github.com/users/Coveo/events{/privacy}","received_events_url":"https://api.github.com/users/Coveo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Coveo/source.coveo.com","description":"Our technical blog.","fork":false,"url":"https://api.github.com/repos/Coveo/source.coveo.com","forks_url":"https://api.github.com/repos/Coveo/source.coveo.com/forks","keys_url":"https://api.github.com/repos/Coveo/source.coveo.com/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Coveo/source.coveo.com/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Coveo/source.coveo.com/teams","hooks_url":"https://api.github.com/repos/Coveo/source.coveo.com/hooks","issue_events_url":"https://api.github.com/repos/Coveo/source.coveo.com/issues/events{/number}","events_url":"https://api.github.com/repos/Coveo/source.coveo.com/events","assignees_url":"https://api.github.com/repos/Coveo/source.coveo.com/assignees{/user}","branches_url":"https://api.github.com/repos/Coveo/source.coveo.com/branches{/branch}","tags_url":"https://api.github.com/repos/Coveo/source.coveo.com/tags","blobs_url":"https://api.github.com/repos/Coveo/source.coveo.com/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Coveo/source.coveo.com/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Coveo/source.coveo.com/git/refs{/sha}","trees_url":"https://api.github.com/repos/Coveo/source.coveo.com/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Coveo/source.coveo.com/statuses/{sha}","languages_url":"https://api.github.com/repos/Coveo/source.coveo.com/languages","stargazers_url":"https://api.github.com/repos/Coveo/source.coveo.com/stargazers","contributors_url":"https://api.github.com/repos/Coveo/source.coveo.com/contributors","subscribers_url":"https://api.github.com/repos/Coveo/source.coveo.com/subscribers","subscription_url":"https://api.github.com/repos/Coveo/source.coveo.com/subscription","commits_url":"https://api.github.com/repos/Coveo/source.coveo.com/commits{/sha}","git_commits_url":"https://api.github.com/repos/Coveo/source.coveo.com/git/commits{/sha}","comments_url":"https://api.github.com/repos/Coveo/source.coveo.com/comments{/number}","issue_comment_url":"https://api.github.com/repos/Coveo/source.coveo.com/issues/comments{/number}","contents_url":"https://api.github.com/repos/Coveo/source.coveo.com/contents/{+path}","compare_url":"https://api.github.com/repos/Coveo/source.coveo.com/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Coveo/source.coveo.com/merges","archive_url":"https://api.github.com/repos/Coveo/source.coveo.com/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Coveo/source.coveo.com/downloads","issues_url":"https://api.github.com/repos/Coveo/source.coveo.com/issues{/number}","pulls_url":"https://api.github.com/repos/Coveo/source.coveo.com/pulls{/number}","milestones_url":"https://api.github.com/repos/Coveo/source.coveo.com/milestones{/number}","notifications_url":"https://api.github.com/repos/Coveo/source.coveo.com/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Coveo/source.coveo.com/labels{/name}","releases_url":"https://api.github.com/repos/Coveo/source.coveo.com/releases{/id}","created_at":"2014-09-09T01:43:19Z","updated_at":"2015-04-27T14:55:22Z","pushed_at":"2015-08-21T19:26:23Z","git_url":"git://github.com/Coveo/source.coveo.com.git","ssh_url":"git@github.com:Coveo/source.coveo.com.git","clone_url":"https://github.com/Coveo/source.coveo.com.git","svn_url":"https://github.com/Coveo/source.coveo.com","homepage":"source.coveo.com","size":18004,"stargazers_count":3,"watchers_count":3,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":25,"mirror_url":null,"open_issues_count":3,"forks":25,"open_issues":3,"watchers":3,"default_branch":"gh-pages"}},"_links":{"self":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56"},"html":{"href":"https://github.com/Coveo/source.coveo.com/pull/56"},"issue":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/issues/56"},"comments":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/issues/56/comments"},"review_comments":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56/comments"},"review_comment":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/pulls/56/commits"},"statuses":{"href":"https://api.github.com/repos/Coveo/source.coveo.com/statuses/821ffcbd376786c38c5cc5a3a2b1b2d5df9228a5"}}}}