{"action":"created","comment":{"url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/comments/43891608","id":43891608,"diff_hunk":"@@ -1,80 +1,190 @@\n # Tweeteor\n-### meteor-workshop\n+Welcome to this Meteor workshop made for BEKK. This is the second part of the workshop, so if you haven't completed the [first part](https://github.com/EirikV/meteor-workshop/tree/chat-solution) yet, we strongly recommend that you do.\n \n-This is a workshop for JS-Platform at Bekk Consulting.\n+In this part you are jumping into some existing code for a social microblog application called Tweeteor. Tweeteor revolutionizes the way social microblogs work by fetching random images from Instagram that matches your hashtags. Wonder how it looks like? Go [check it out](http://therealtweeteor.meteor.com/). Feel free to create an account and write some tweets.\n \n-The objective is to learn about Meteor (not to be confused with meteorites or comets) by building Tweeteor.\n-Tweeteor is a fun new micro-blog that combines your hashtags with instagram pictures.\n+## Some resources to help you along\n+* **[The full Meteor documentation](http://docs.meteor.com/#/full/quickstart)**\n+* **[Atmospherejs.com - meteor packages](https://atmospherejs.com/)**\n+* **[The iron router guide](http://iron-meteor.github.io/iron-router/)**\n+* **[Collection FS github page (used for image upload)](https://github.com/CollectionFS/Meteor-CollectionFS)**\n \n-[Meteor documentation](http://docs.meteor.com/#/full/)\n+### Tasks\n \n-## Tasks:\n+####1. Structure\n+This application is quite a lot bigger than the [chat application](https://github.com/EirikV/meteor-workshop/tree/chat-solution), so we have chosen to structure it into smaller files and folders. Structuring a larger Meteor app can be achieved using packages, but that falls outside the scope of this workshop. \n \n-### 1. First of all\n+You should familiarize yourself with how the application is built. Poke a little around in the code, and don't hesitate to ask if some things are unclear!. \n \n-Head over to [instagram](https://instagram.com/developer/) and create an account if you don't have one already.\n-Next, click \"Register Your Application\" and then \"Register a New Client\", to register a new client.\n-Pop your `CLIENT ID` and `CLIENT SECRET` into **settings.json** (found in the root of the project).\n+The application is built using the following structure:\n \n-We do this because instagram has a 5000-requests an hour per application limit for applications where the user is not authenticated.\n+* client (main folder for client side only code).\n+    * common (holds common code such as global helpers)\n+    * less\n+    * modules (each logical piece of the application is treated like a module)\n+        * some module\n+            * some_root_level.html or .js\n+            * some submodule folder\n+                * some submodule .html or .js\n+* lib (main folder for code shared between client and server).\n+    * It may seem a little strange that the 'lib' folder doesn't actually contain any external libraries. We have named this folder lib as per Meteor's own [recommendations](http://docs.meteor.com/#/full/structuringyourapp) for structuring an app.\n+* public (assets).\n+* server (main folder for server side only code).\n+    * modules (some of the client side modules also have server side counter parts. Others exist only on the server).\n+        * some submodule\n+            * some submodule .js\n+#### 2. Routing\n+Meteor applications mostly use one package for routing: the [iron:router](https://atmospherejs.com/iron/router). Using a router is essential for a larger application. With Meteor, using a router changes some of the basic mechanics of the framework. For example: In the chat application, you simply published a collection and then subscribed to it from the client. With a router, this needs to be handled for each route to make sure that a subscription is ready once a route function is executed. In the next series of subtasks, you will learn the parts of iron:router that are needed for Tweeteor.\n+\n+##### Registering a route\n+Tweeteor requires two routes. One root route that shows posts and one route for the profile page. Open up *router.js* and add these two routes. The profile route should use a parameter that is unique for each user, the username for instance.\n+\n+Create a data function for both routes that for now just return a predefined set of data so that you can verify that your routes work.\n+\n+*Tip: Iron router looks for templates named the same as you routes*\n+\n+*Tip: Look at the templates provided for posts and profile. Add some temporary code here to display the dummy data you put in the data function of your routes*\n+\n+##### Layout\n+Right now, your app probably doesn't look to good. Let's fix this by using the layout we have provided. If you open *layout.html* you can see that this file has some default markup. \n+\n+To use this layout in your router, open *router.js* and create a *Router.configure* function that takes in an object. Add a *layoutTemplate* property on this object with a string that matches the name of the layout template in *layout.html*. \n+\n+To wrap it all up you need to tell the router where to *yield* the template rendered in the route function. Adding the special template function {{> yield}} does the trick.\n+\n+##### Handling data from subscriptions\n+In later tasks you will add some collections to the application that you will publish from the server. The client will need to subscribe to these. But, since Tweeteor uses a router, this has to be handled a little differently than in the [chat application](https://github.com/EirikV/meteor-workshop/tree/chat-solution).\n+\n+Both the *route* function and the global *Router.configure* function supports an object property called *waitOn*. This is a function that can be used to set up route specific subscriptions (when used in a *route* call) and global subscriptions (when used in the *Router.configure* function). Either return a single *Meteor.subscribe* or an array of multiple subscriptions. If you want, you can add a loadingTemplate that will be displayed until the subscription is ready. Subscriptions aren't needed right now, but we will remind you when the time comes.\n+\n+##### 404 - header not found\n+Iron router can of course show a custom 404 page for unknown routes. All you need to do is to use your *Router.configure* function to tell it where to find the *notFoundTemplate*. You can also show a custom *dataNotFound* page through the use of a *plugin*. Make your app a little more friendly by adding both of these.\n+\n+#### 3. Accounts\n+A true social microblog needs to have authenticated users. Luckily, you don't have to build this functionality yourself. Meteor has a series of packages with the prefix *accounts* that handle user registration and authentication for you. With just a few keystrokes you can get authentication through Facebook, Twitter, Github and others.\n+\n+Tweeteor will use simple authentication where users signs up with Tweeteor directly (but feel free to try out the accounts packages for Facebook etc.). So open up a command line and type `meteor add accounts-password` and `meteor add accounts-ui`. The first package is the actual authentication and user handler. The other gives you a simple UI for a sign in and registration form.\n+\n+The *accounts-ui* package comes with a predefined template called *loginButtons*. This is basically all you need to get a fully functional accounts system in the app. By default, you will get login by email and no username. To change this, create a .js file somewhere in your client code (maybe in the profile module?) and ùse `Accounts.ui.config` to use a username and (optional) email instead.","path":"README.md","position":79,"original_position":79,"commit_id":"505e05e8a5288e864f738439a077fca62631e947","original_commit_id":"505e05e8a5288e864f738439a077fca62631e947","user":{"login":"kjohann","id":3235249,"avatar_url":"https://avatars.githubusercontent.com/u/3235249?v=3","gravatar_id":"","url":"https://api.github.com/users/kjohann","html_url":"https://github.com/kjohann","followers_url":"https://api.github.com/users/kjohann/followers","following_url":"https://api.github.com/users/kjohann/following{/other_user}","gists_url":"https://api.github.com/users/kjohann/gists{/gist_id}","starred_url":"https://api.github.com/users/kjohann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kjohann/subscriptions","organizations_url":"https://api.github.com/users/kjohann/orgs","repos_url":"https://api.github.com/users/kjohann/repos","events_url":"https://api.github.com/users/kjohann/events{/privacy}","received_events_url":"https://api.github.com/users/kjohann/received_events","type":"User","site_admin":false},"body":"email (optional) - Done!","created_at":"2015-11-04T15:12:41Z","updated_at":"2015-11-04T15:12:41Z","html_url":"https://github.com/EirikV/meteor-workshop/pull/8#discussion_r43891608","pull_request_url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8","_links":{"self":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/comments/43891608"},"html":{"href":"https://github.com/EirikV/meteor-workshop/pull/8#discussion_r43891608"},"pull_request":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8"}}},"pull_request":{"url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8","id":49605929,"html_url":"https://github.com/EirikV/meteor-workshop/pull/8","diff_url":"https://github.com/EirikV/meteor-workshop/pull/8.diff","patch_url":"https://github.com/EirikV/meteor-workshop/pull/8.patch","issue_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues/8","number":8,"state":"open","locked":false,"title":"New tasks","user":{"login":"kjohann","id":3235249,"avatar_url":"https://avatars.githubusercontent.com/u/3235249?v=3","gravatar_id":"","url":"https://api.github.com/users/kjohann","html_url":"https://github.com/kjohann","followers_url":"https://api.github.com/users/kjohann/followers","following_url":"https://api.github.com/users/kjohann/following{/other_user}","gists_url":"https://api.github.com/users/kjohann/gists{/gist_id}","starred_url":"https://api.github.com/users/kjohann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kjohann/subscriptions","organizations_url":"https://api.github.com/users/kjohann/orgs","repos_url":"https://api.github.com/users/kjohann/repos","events_url":"https://api.github.com/users/kjohann/events{/privacy}","received_events_url":"https://api.github.com/users/kjohann/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-11-03T20:16:57Z","updated_at":"2015-11-04T15:12:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2bf3b833616e0f7ba31c8bb5c535d3d6df2deea1","assignee":{"login":"EirikV","id":4076243,"avatar_url":"https://avatars.githubusercontent.com/u/4076243?v=3","gravatar_id":"","url":"https://api.github.com/users/EirikV","html_url":"https://github.com/EirikV","followers_url":"https://api.github.com/users/EirikV/followers","following_url":"https://api.github.com/users/EirikV/following{/other_user}","gists_url":"https://api.github.com/users/EirikV/gists{/gist_id}","starred_url":"https://api.github.com/users/EirikV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EirikV/subscriptions","organizations_url":"https://api.github.com/users/EirikV/orgs","repos_url":"https://api.github.com/users/EirikV/repos","events_url":"https://api.github.com/users/EirikV/events{/privacy}","received_events_url":"https://api.github.com/users/EirikV/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8/commits","review_comments_url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8/comments","review_comment_url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/comments{/number}","comments_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues/8/comments","statuses_url":"https://api.github.com/repos/EirikV/meteor-workshop/statuses/505e05e8a5288e864f738439a077fca62631e947","head":{"label":"EirikV:newTasks","ref":"newTasks","sha":"505e05e8a5288e864f738439a077fca62631e947","user":{"login":"EirikV","id":4076243,"avatar_url":"https://avatars.githubusercontent.com/u/4076243?v=3","gravatar_id":"","url":"https://api.github.com/users/EirikV","html_url":"https://github.com/EirikV","followers_url":"https://api.github.com/users/EirikV/followers","following_url":"https://api.github.com/users/EirikV/following{/other_user}","gists_url":"https://api.github.com/users/EirikV/gists{/gist_id}","starred_url":"https://api.github.com/users/EirikV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EirikV/subscriptions","organizations_url":"https://api.github.com/users/EirikV/orgs","repos_url":"https://api.github.com/users/EirikV/repos","events_url":"https://api.github.com/users/EirikV/events{/privacy}","received_events_url":"https://api.github.com/users/EirikV/received_events","type":"User","site_admin":false},"repo":{"id":34062323,"name":"meteor-workshop","full_name":"EirikV/meteor-workshop","owner":{"login":"EirikV","id":4076243,"avatar_url":"https://avatars.githubusercontent.com/u/4076243?v=3","gravatar_id":"","url":"https://api.github.com/users/EirikV","html_url":"https://github.com/EirikV","followers_url":"https://api.github.com/users/EirikV/followers","following_url":"https://api.github.com/users/EirikV/following{/other_user}","gists_url":"https://api.github.com/users/EirikV/gists{/gist_id}","starred_url":"https://api.github.com/users/EirikV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EirikV/subscriptions","organizations_url":"https://api.github.com/users/EirikV/orgs","repos_url":"https://api.github.com/users/EirikV/repos","events_url":"https://api.github.com/users/EirikV/events{/privacy}","received_events_url":"https://api.github.com/users/EirikV/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/EirikV/meteor-workshop","description":"","fork":false,"url":"https://api.github.com/repos/EirikV/meteor-workshop","forks_url":"https://api.github.com/repos/EirikV/meteor-workshop/forks","keys_url":"https://api.github.com/repos/EirikV/meteor-workshop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/EirikV/meteor-workshop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/EirikV/meteor-workshop/teams","hooks_url":"https://api.github.com/repos/EirikV/meteor-workshop/hooks","issue_events_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues/events{/number}","events_url":"https://api.github.com/repos/EirikV/meteor-workshop/events","assignees_url":"https://api.github.com/repos/EirikV/meteor-workshop/assignees{/user}","branches_url":"https://api.github.com/repos/EirikV/meteor-workshop/branches{/branch}","tags_url":"https://api.github.com/repos/EirikV/meteor-workshop/tags","blobs_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/refs{/sha}","trees_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/EirikV/meteor-workshop/statuses/{sha}","languages_url":"https://api.github.com/repos/EirikV/meteor-workshop/languages","stargazers_url":"https://api.github.com/repos/EirikV/meteor-workshop/stargazers","contributors_url":"https://api.github.com/repos/EirikV/meteor-workshop/contributors","subscribers_url":"https://api.github.com/repos/EirikV/meteor-workshop/subscribers","subscription_url":"https://api.github.com/repos/EirikV/meteor-workshop/subscription","commits_url":"https://api.github.com/repos/EirikV/meteor-workshop/commits{/sha}","git_commits_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/commits{/sha}","comments_url":"https://api.github.com/repos/EirikV/meteor-workshop/comments{/number}","issue_comment_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues/comments{/number}","contents_url":"https://api.github.com/repos/EirikV/meteor-workshop/contents/{+path}","compare_url":"https://api.github.com/repos/EirikV/meteor-workshop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/EirikV/meteor-workshop/merges","archive_url":"https://api.github.com/repos/EirikV/meteor-workshop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/EirikV/meteor-workshop/downloads","issues_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues{/number}","pulls_url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls{/number}","milestones_url":"https://api.github.com/repos/EirikV/meteor-workshop/milestones{/number}","notifications_url":"https://api.github.com/repos/EirikV/meteor-workshop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/EirikV/meteor-workshop/labels{/name}","releases_url":"https://api.github.com/repos/EirikV/meteor-workshop/releases{/id}","created_at":"2015-04-16T14:58:03Z","updated_at":"2015-10-25T13:24:17Z","pushed_at":"2015-11-04T14:59:55Z","git_url":"git://github.com/EirikV/meteor-workshop.git","ssh_url":"git@github.com:EirikV/meteor-workshop.git","clone_url":"https://github.com/EirikV/meteor-workshop.git","svn_url":"https://github.com/EirikV/meteor-workshop","homepage":null,"size":1056,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"EirikV:tweeteor-solution","ref":"tweeteor-solution","sha":"b3d26c29b284276418a22a36bb22ac744c54e1f5","user":{"login":"EirikV","id":4076243,"avatar_url":"https://avatars.githubusercontent.com/u/4076243?v=3","gravatar_id":"","url":"https://api.github.com/users/EirikV","html_url":"https://github.com/EirikV","followers_url":"https://api.github.com/users/EirikV/followers","following_url":"https://api.github.com/users/EirikV/following{/other_user}","gists_url":"https://api.github.com/users/EirikV/gists{/gist_id}","starred_url":"https://api.github.com/users/EirikV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EirikV/subscriptions","organizations_url":"https://api.github.com/users/EirikV/orgs","repos_url":"https://api.github.com/users/EirikV/repos","events_url":"https://api.github.com/users/EirikV/events{/privacy}","received_events_url":"https://api.github.com/users/EirikV/received_events","type":"User","site_admin":false},"repo":{"id":34062323,"name":"meteor-workshop","full_name":"EirikV/meteor-workshop","owner":{"login":"EirikV","id":4076243,"avatar_url":"https://avatars.githubusercontent.com/u/4076243?v=3","gravatar_id":"","url":"https://api.github.com/users/EirikV","html_url":"https://github.com/EirikV","followers_url":"https://api.github.com/users/EirikV/followers","following_url":"https://api.github.com/users/EirikV/following{/other_user}","gists_url":"https://api.github.com/users/EirikV/gists{/gist_id}","starred_url":"https://api.github.com/users/EirikV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EirikV/subscriptions","organizations_url":"https://api.github.com/users/EirikV/orgs","repos_url":"https://api.github.com/users/EirikV/repos","events_url":"https://api.github.com/users/EirikV/events{/privacy}","received_events_url":"https://api.github.com/users/EirikV/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/EirikV/meteor-workshop","description":"","fork":false,"url":"https://api.github.com/repos/EirikV/meteor-workshop","forks_url":"https://api.github.com/repos/EirikV/meteor-workshop/forks","keys_url":"https://api.github.com/repos/EirikV/meteor-workshop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/EirikV/meteor-workshop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/EirikV/meteor-workshop/teams","hooks_url":"https://api.github.com/repos/EirikV/meteor-workshop/hooks","issue_events_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues/events{/number}","events_url":"https://api.github.com/repos/EirikV/meteor-workshop/events","assignees_url":"https://api.github.com/repos/EirikV/meteor-workshop/assignees{/user}","branches_url":"https://api.github.com/repos/EirikV/meteor-workshop/branches{/branch}","tags_url":"https://api.github.com/repos/EirikV/meteor-workshop/tags","blobs_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/refs{/sha}","trees_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/EirikV/meteor-workshop/statuses/{sha}","languages_url":"https://api.github.com/repos/EirikV/meteor-workshop/languages","stargazers_url":"https://api.github.com/repos/EirikV/meteor-workshop/stargazers","contributors_url":"https://api.github.com/repos/EirikV/meteor-workshop/contributors","subscribers_url":"https://api.github.com/repos/EirikV/meteor-workshop/subscribers","subscription_url":"https://api.github.com/repos/EirikV/meteor-workshop/subscription","commits_url":"https://api.github.com/repos/EirikV/meteor-workshop/commits{/sha}","git_commits_url":"https://api.github.com/repos/EirikV/meteor-workshop/git/commits{/sha}","comments_url":"https://api.github.com/repos/EirikV/meteor-workshop/comments{/number}","issue_comment_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues/comments{/number}","contents_url":"https://api.github.com/repos/EirikV/meteor-workshop/contents/{+path}","compare_url":"https://api.github.com/repos/EirikV/meteor-workshop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/EirikV/meteor-workshop/merges","archive_url":"https://api.github.com/repos/EirikV/meteor-workshop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/EirikV/meteor-workshop/downloads","issues_url":"https://api.github.com/repos/EirikV/meteor-workshop/issues{/number}","pulls_url":"https://api.github.com/repos/EirikV/meteor-workshop/pulls{/number}","milestones_url":"https://api.github.com/repos/EirikV/meteor-workshop/milestones{/number}","notifications_url":"https://api.github.com/repos/EirikV/meteor-workshop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/EirikV/meteor-workshop/labels{/name}","releases_url":"https://api.github.com/repos/EirikV/meteor-workshop/releases{/id}","created_at":"2015-04-16T14:58:03Z","updated_at":"2015-10-25T13:24:17Z","pushed_at":"2015-11-04T14:59:55Z","git_url":"git://github.com/EirikV/meteor-workshop.git","ssh_url":"git@github.com:EirikV/meteor-workshop.git","clone_url":"https://github.com/EirikV/meteor-workshop.git","svn_url":"https://github.com/EirikV/meteor-workshop","homepage":null,"size":1056,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8"},"html":{"href":"https://github.com/EirikV/meteor-workshop/pull/8"},"issue":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/issues/8"},"comments":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/issues/8/comments"},"review_comments":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8/comments"},"review_comment":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/pulls/8/commits"},"statuses":{"href":"https://api.github.com/repos/EirikV/meteor-workshop/statuses/505e05e8a5288e864f738439a077fca62631e947"}}}}