{"id":14954637,"url":"https://github.com/meteor/telephone-pictionary","last_synced_at":"2026-02-13T05:01:55.489Z","repository":{"id":9160451,"uuid":"10956346","full_name":"meteor/telephone-pictionary","owner":"meteor","description":"Telephone-Pictionary crash course for Meteor","archived":false,"fork":false,"pushed_at":"2014-04-16T19:36:27.000Z","size":392,"stargazers_count":16,"open_issues_count":3,"forks_count":14,"subscribers_count":18,"default_branch":"master","last_synced_at":"2026-01-26T10:45:40.641Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meteor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-06-26T02:37:26.000Z","updated_at":"2021-12-24T15:21:01.000Z","dependencies_parsed_at":"2022-09-10T05:40:43.762Z","dependency_job_id":null,"html_url":"https://github.com/meteor/telephone-pictionary","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/meteor/telephone-pictionary","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Ftelephone-pictionary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Ftelephone-pictionary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Ftelephone-pictionary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Ftelephone-pictionary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meteor","download_url":"https://codeload.github.com/meteor/telephone-pictionary/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Ftelephone-pictionary/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29396847,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T04:26:15.637Z","status":"ssl_error","status_checked_at":"2026-02-13T04:16:29.732Z","response_time":78,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T13:04:36.750Z","updated_at":"2026-02-13T05:01:55.466Z","avatar_url":"https://github.com/meteor.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Telephone-Pictionary Meteor Crash Course\n\nTelephone-Pictionary is a game where you alternately draw phrases and describe\ndrawings.\n\nThis is meant to be a crash course in the Meteor Javascript web framework.  The\n`master` branch of this repository is not fully implemented; finishing the\nimplementation is left as an exercise to the reader.  The `solution` branch of\nthis repository is a working game.\n\n# Test Drive Telephone Pictionary\n\nClick this button to start hacking on Telephone Pictionary on [Nitrous.IO](https://www.nitrous.io/?utm_source=github.com\u0026utm_campaign=meteor-telephone-pictionary\u0026utm_medium=hackonnitrous) in a matter of seconds:\n\n[![Hack meteor/telephone-pictionary on Nitrous.IO](https://d3o0mnbgv6k92a.cloudfront.net/assets/hack-l-v1-3cc067e71372f6045e1949af9d96095b.png)](https://www.nitrous.io/hack_button?source=embed\u0026runtime=nodejs\u0026repo=meteor%2Ftelephone-pictionary\u0026file_to_open=README.nitrous.md)\n\n# Walkthrough\n\nThroughout this course, you can use `git grep 'PHASE N'` to find spots in the code\nrelevant to the phase you're working on, if you're working on phase `N`.  For\nexample, to find spots in the code relevant to phase 1, type `git grep 'PHASE 1'`.\n\nTo start playing:\n\n* Install Meteor.  At your terminal, type:\n\n        curl https://install.meteor.com | /bin/sh\n\n* Check out this git repository\n* Navigate to your checkout, and type `meteor` at your terminal.\n\nYou should now be able to go to `localhost:3000` in your browser, and have\naccess to a basic drawing program.  Spend a little time poking around the code,\nin advance of getting down and dirty with it very soon.\n\n## Phase 1\n\nHere you'll be getting used to Meteor's reactive templating system.  That sounds\nfancy and complicated, but what it really means is that Meteor does its best to\ntell when the information substituted into your HTML templates changes, and\nautomatically re-renders the templates for you on the page.\n\nThe templating system Meteor uses is a variant of Handlebars.  The basics: You\ninvoke a template like so: `{{\u003e templateName}}`. You enclose variable names in\ndouble braces `{{likeThis}}`, and Meteor fills in the string contents of those\nvariables.\n\nMeteor searches two places for filling in Handlebars variables:\n\n* *Template helpers*, which are functions in your Javascript code that return\n  the values to substitute.  To provide a template helper that will substitute\n  `{{foo}}` in the template called `sillyWords`, assign a function to the\n  variable `Template.sillyWords.foo` For example:\n\n        Template.sillyWords.foo = function () {\n          return Random.choice([\"pabst\", \"furblig\", \"blick\"]);\n        }\n\n* The *data context* of your template.  You can create a data context by writing\n  `{{#with helper}}` or `{{#each helper}}` (closed by `{{/with}}` and\n  `{{/each}}` respectively) in your html.\n\n  A `{{#with foo}}` block evaluates `foo` (in the same way as any other\n  handlebars variable), and sets the data context for everything in the block to\n  be that value.\n\n  An `{{#each foo}}` block does the same thing, but expects the value of `foo`\n  to be an array or database cursor, and repeats its contents once with the data\n  context set to every element of `foo`.\n\n  Within template helpers and event handlers on templates, the value of `this`\n  is the data context.\n\nIf the data context is itself a string, `{{this}}`, will substitute in the whole\ndata context.\n\nMeteor supplies certain information sources that will inform template helpers\nthey need to rerender when the data source is changed.  The simplest of these is\n`Session`.  To get a `Session` variable, use `Session.get(\"variableName\")`, and\nto set one, use `Session.set(\"variableName\", value)`.\n\nThe task for phase 1 is to add color support to our drawing program.  You'll be\nworking in `client/draw.js` and `client/draw.html`.  Replace each of the PHASE 1\ncomments with the appropriate Handlebars and Javascript code.\n\nNote: In Meteor, you rarely want to supply `href` attributes to links, because\nclicking them reloads your page.  You want to directly process click events on\nthose links instead.\n\n## Phase 2\n\nPhase 2 is about interacting with Meteor's package system, to add the ability to\nlog in to our application.\n\nAt the command prompt in your application directory, type\n\n    meteor add accounts-ui\n    meteor add accounts-password\n\n(you can instead add `accounts-facebook`, or `accounts-google` if you like).\n\nAt this point, you can add login support just by adding `{{loginButtons}}` to\nthe `telephone-pictionary.html` file.\n\nWe'd also like to hide most of the application's UI if the user is not logged\nin, so you can add a template helper in `main.js` to return `Meteor.userId()`\n(which will be null if we're not logged in), and add `{{#if\nloggedIn}}`...`{{/if}}` blocks to `telephone-pictionary.html` in the spots\nindicated for phase 2.\n\n\n## Phase 3\n\nThe way Meteor stores data that's shared between the client and the server is in\nMongoDB.  On the server, this is a direct interface to MongoDB.  On the client,\nwe're dealing with a pure-Javascript reimplementation of Mongo that shares a\nmirror of (a subset of) the data on the server.\n\nMongo is a non-SQL object database with a Javascript object based query\nlanguage.  For example, for a collection `Coll`, `Coll.find({a: 3, b: \"foo\"})`\nfinds every object in the collection for which `a` is `3` and `b` is\n`\"foo\"`. You can also use a variety of selector operations, such as\n`Coll.find({a: {$lt: 3}})`, for all objects with `a` less than `3`.  Every object\nin the database has an `_id` field that uniquely specifies it.\n\nThe Mongo operations of note are:\n\n * `Coll.find(selector)` -- finds a cursor over all objects that match the given selector object\n * `Coll.findOne(selector)` -- finds the first object that matches the given selector, if any.\n * `Coll.insert(object)` -- inserts the given object into the database\n * `Coll.update(_id, updater)` -- updates the object with the given `_id` with\n   the given updater.  For example, the updater `{$set: {a: 6}}` sets the `a`\n   field to `6`.\n * `Coll.remove(_id)` -- removes the specified object from the collection.\n\nIn phase 3, we'll be doing some database interaction to figure out what our user\nshould draw or describe, and use Meteor's remote procedure call api to inform\nthe client of this assignment.  In `assignments.js`, fill in the part of the\n`getAssignment` RPC as indicated.  Then, in `main.js`, fill in the parts\nnecessary to actually make the RPC to get an assignment when needed, and to\ndisplay the assignment in the main template.\n\n## Phase 4\n\nNow that we have an assignment in the `\"assignment\"` Session variable, we can\ndisplay the assignment, not just the drawing interface all the time.  In\n`telephone-pictionary.html`, change the main template to decide which of the\n`draw`, `describe`, or `start` templates to use based on what fields of the\nassignment are set: `picture` is set when you should describe something,\n`description` is set when you should draw something, and `start` is set when you\nshould start something.  If there is no assignment or if we're in game-viewing\nmode, display none of these.\n\nNote: Look at `start.html`, `describe.html`, `start.js`, and `describe.js` for\nthe code for these other templates.  You've seen the code for the `draw`\ntemplate before.\n\n## Phase 5\n\nWe have assignments displaying.  Now let's provide the answers to them.  In\n`start.js`, `describe.js`, and `draw.js`, provide an event handler that will\ngather the answer (use the `find` method on the template object to get a\nparticular html element in the template) and send it to the server.  Don't\nforget the `submitAnswer` helper function that already exists for you in\n`main.js`.\n\n## Phase 6\n\nAt this point your game should be mostly working.  The rest is window dressing.\nBut kind of important window dressing... right now people never run out of time\nto make their moves.  Let's implement expiry on moves, and a timer for the user\nto look at while they're working.\n\nThe subtle stuff here has to do with Meteor's `Deps` package, which is the\nlower-level interface to reactivity. In `timer.js`, you have a template helper\nthat should return the time left on the current assignment -- but it needs to\nknow that it should re-render regularly.  We do this by calling `depend()` on a\n`Dependency` object (which will tell this function to re-run every time the\ndependency is changed), and regularly calling `changed()` on the dependency\nobject (which will tell the dependency it has changed).\n\nYou will also have to implement some server-side assignment expiry logic with\nMongoDB at the bottom of `assignments.js`.\n\n## Phase 7\n\nSo now our app is feature-complete.  The one problem: All the clients still get\nall the information in the database.  To keep this from happening, we need to\nstop relying on Meteor's introductory `autopublish` package, which sends your\nwhole database to every client.  Instead, we'll publish only the information we\nwant each client to see.\n\nTo remove `autopublish`:\n    meteor remove autopublish\n\nWhile you're at it, also remove the `insecure` package, which allows clients\nunfettered access to modify your database.\n    meteor remove insecure\n\nThe simplest way to use `Meteor.publish('name', func)` is to have the function\nreturn a Mongo cursor, possibly using the arguments of the function or\n`this.userId` to determine what should be in the cursor.  You can then call\n`Meteor.subscribe('name', arguments)` on the client to subscribe to the publish\nfunction of the same name.\n\nFind the places in `model.js` and `main.js` to implement publishes and\nsubscriptions, respectively.\n\n## Appendix: How did we get here?\n\nThis walkthrough dumps you in to the middle of a Meteor project.  How did we get\nfrom a blank filesystem to the state of the repository you checked out?\n\nFirst, we created a blank application with\n    meteor create telephone-pictionary\n\nWe proceeded to create `client` and `server` directories there, so that we could\neasily have code execute just on the client, or just on the server, and we moved\nsome of the default files to the `client` directory.\n\nNext, we added the Twitter Bootstrap package, to make styling things easier.\n\n    meteor add bootstrap\n\nSince we didn't want to write a whole canvas drawing program ourselves, we went\nto [http://fabricjs.com/build/](http://fabricjs.com/build/) and downloaded a\nbuild of Fabric with Interaction, Serialization, Parser, and Free Drawing\nselected.  We dropped it in `client/compatibility/fabric.js` in our\nproject. (`client/compatibility` is a directory for third-party libraries that\nexpect to be able to declare global variables with the `var` keyword).\n\nFinally, we wrote some code.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeteor%2Ftelephone-pictionary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeteor%2Ftelephone-pictionary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeteor%2Ftelephone-pictionary/lists"}