Embedly was selected to present our APIs and offer support as an ambassador at the 2013 hackNY.  There was lots of energy in the room, with a focus on projects being awesome, rather than chasing hockey stick growth.  They even had a hardware hacking room with 3D printers. 




One of the projects, Edison Encryption, used the Embedly Extract API as one of the steps for an encryption algorithm.  The team consisted of Eric Schles, Dan Cohen, Chris Williams, and Danny Padawer.

Details of the algorithm are provided on Github

The algorithm currently adds padding to plaintext in such a way that makes cryptanalysis more difficult. This is because it pads based on a given corpus (chosen by the encrypter) and mimics that frequency. This makes discerning the true plaintext difficult. In order decrypt, you need a series of offsets, for each actual plaintext character. By combining both of these, we have an easy to decrypt and relatively cheap encryption algorithm.

When I saw the project presentation I was curious how Embedly was used in it.  Eric got back to us, mentioning that Embedly Extract was used specifically to parse an article and get the content. From Eric: 

We used embedly to get corpus’ of a specific kind.  We then did frequency analysis(similar to what is done in cryptanalysis) on the corpus in order to determine likely frequency patterns, making it difficult to tell which letters are part of the plaintext and which are part of the ciphertext.

According to Eric, the team doesn’t plan on stopping now, and has some pretty admirable ambitions.

We plan to expand this hack and turn it into a cryptographic standard that makes the internet a safer better place.

When we built Extract, we knew it would be used in natural language processing applications, but we never imagined it would be used for encryption.  Pretty cool seeing how people use the Extract API!

If you’d like to start using Extract, you can sign up free, and get started with some demos and tutorials

HackNY was a great time.  If you’re having a hackathon, let us know, we’d love to come by.

Update (04/18/13):  Danny got back to us on what it was like using the Extract API:

We only used the extraction API, but it was very nice, easy, simple to use. It returned everything we needed.

No complaints, and it worked quickly, which is always nice at a Hackathon - minimal time was needed to get it doing everything we needed.

Great to hear!

Posted 1 year ago by whichlight
Embed This

The third post in our series on Ember will continue to work from the development environment that we worked on in the first and second posts.

As promised last time, this post will dive into views and controllers. Here is where the magic happens. We’ll also touch on models, but we’ll save the bulk of the models work for our next post.


This time let’s try and fill in some details on the about page. Since it needs to be about something, let’s create a fictitious organization called Jubarian. We’ll create a simple controller to display information about the organization and add it to index.html.

    // app/scripts/modules/about.js
    App.AboutController = Em.Controller.extend({
      name: 'jubarian.org',
      description: 'A non-profit organization of peopled dedicating to spreading joy.'

    // app/index.html
    <script src="scripts/modules/about.js"></script>

    // app/templates/about.handlebars
    <h1>About {{name}}</h1>

This works, but it’s not very MVC. We shouldn’t be adding our data directly to our controller. Our controller should only contain data directly relevant to display concerns.

Controllers in Ember are a little different then what you may be used to in more traditional MVC frameworks. Usually, they are implemented as proxies to a model and passed to the view using an ObjectController or ArrayController. The view will never interact with the model directly, only through the controller proxy. This allows us to have a clean separation of data concerns and display concerns. The controller decorates the model with display logic. Let’s implement something to make things more clear.


There are two main types of controllers that are most common in Ember applications, the ObjectController and the ArrayController. In this case, we’ll use an ObjectController, since there is only a single organization being displayed. We’ll create a naively simple model to hold our data and connect it to the controller in the router.

     // app/scripts/modules/about.js
     App.Fixtures = App.Fixtures || {};

     // our model
     App.Fixtures.Org = {
       name: 'jubarian.org',
       description: 'A non-profit organization of peopled dedicating to spreading joy.'

     App.AboutController = Em.ObjectController.extend({})

     App.AboutRoute = Em.Route.extend({
       model: function() {
         return App.Fixtures.Org;

Properties of Ember objects aren’t set directly. We always use set(name) and get(name) functions to allow Ember to notify the objects observers of property changes. This is what allows Ember to automatically update views when properties change. Since our Org object is not an Ember object, Ember won’t be able to detect changes to it. We’ll cover a more robust way of doing thing in the next post, when we cover models and ember-data.

We’ll need to wire up our Org to the AboutController. We do this by defining a method function property on our AboutRoute object. ObjectControllers are different then a regular controller because they proxy all of their undefined properties to the object defined as their content property. Ember will automatically call the model function and set the result to the content property of the controller.

Our controller, as it stands, doesn’t do anything. Before we created it we were using an auto-generated controller of type Controller. Since it wasn’t an ObjectController, it didn’t proxy to the content property. Now that we’ve defined it as an ObjectController, all undefined properties pass through to the content property, our org fixture.

Let’s add some state to the display so the controller has something to do. We’ll add a list of team members with a toggle for displaying or hiding it. This will also give us a chance to setup an ArrayController and see how that works. But first let’s just create a static view. And modify the AboutController to handle the team display logic.

      // app/templates/team.handlebars

      // app/templates/about.handlebars
        <a href="#" {{action toggleTeam}}>{{toggleTeamLabel}}</a>

      {{view App.TeamView isVisibleBinding="teamVisible"}}

      // app/scripts/modules/about.js
      App.AboutController = Em.ObjectController.extend({
        teamVisible: false,
        toggleTeam: function() {
          this.set('teamVisible', !this.get('teamVisible'));
        toggleTeamLabel: function() {
          var vis = this.get('teamVisible');
          return vis ? 'hide team' : 'show team';

      App.TeamView = Em.View.extend({
        templateName: 'team'

You’ll notice that we had to explicitly create the TeamView object. That is because it wasn’t generated through the router so the template name isn’t automatically discovered.


toggleTeamLabel is a good example of a dynamic property. When controller.get('toggleTeamLabel') is called, the function will be used to generate toggleTeamLabel’s value. To denote this, the property function is called on the function. The property function takes a list of arguments that define it’s dependencies. This is important for observers of the property, and to allow Ember to cache the property result. Ember knows that when teamVisible changes, so does toggleTeamLabel.

In our about template, we have created an anchor tag that fires toggleTeam on AboutController whenever it is clicked using the action helper. We are using the toggleTeamLabel as the display name of the tag. We use the view helper to insert the TeamView into our template. isVisibleBinding="teamVisible" is a special attribute that binds the isVisible attribute of TeamView to the teamVisible property of the current scope, which happens to be AboutController. Now, whenever teamVisible changes, so will isVisible. isVisible is a builtin property of every View that controls whether or not it is visible.


Now let’s convert the static template, team, into a proper ArrayController. Since we want the view to have it’s own controller, and not share a controller with AboutView, we’ll change it from a {{view}} to a {{render}}. This will allow us to wire up the array of team members to an ArrayController and associate it with the view.

    // app/modules/about.js
    App.Fixtures.Team = [
      { name: 'Bob' },
      { name: 'Andy' },
      { name: 'John' },
      { name: 'Kawan' },
      { name: 'Nina' },
      { name: 'Sean' },
      { name: 'Art' },

    App.Team Controller = Em.ArrayController.extend({
      needs: 'about',
      about Binding: 'controllers.about'

    App.TeamView = Em.View.extend({
      isVisibleBinding: 'controller.about.teamVisible'

    // app/template/about.handlebars

    {{render "team" App.Fixtures.Team}}


    // app/templates/team.handlebars
      {{#each controller}}

The render helper will automatically find the correct view and controller based on the first parameter, the template name. The second parameter will be used as the model.

The way we are binding AboutController’s teamVisible property to TeamView is a bit contrived, but it shows how controllers can be bound together. We declare that TeamController needs AboutController and that the about property of TeamController is bound the AboutController. We then bind TeamView’s isVisible property to AboutController’s teamVisible property.

Since TeamController is now an ArrayController, we can iterate over it’s content with the each helper. each will iterate over the collection putting it in scope for the contained template, in this case <li>{{name}}</li>.


With a few lines of code we’ve made a dynamic, data driven about page and demonstrated the power of Ember views and controllers. You can find the source for the project on github  This wraps up our brief intro to views and controllers. Our next blog in the series will give an introduction to ember-data, a web ORM for ember. See you next time!

Posted 1 year ago by dokipen
Embed This

Our users are what keeps us going so we’ve decided to start a weekly user spotlight series to showcase your projects and creations.

First up is Fetchnotes. An app that’s core mission is to make productivity as simple as a tweet. When using Fetchnotes, your tasks are grouped by hashtags, as in #todo, #email, #groceries, and #buy. As you place hashtags on each task, they are grouped by the hashtag and you can access them more clearly via your phone or dashboard. Pretty slick.

So, how do they use Embedly? Fetchnotes founder and CEO, Alex Schiff filled us in,

"Embedly makes it easy for our users to act on the notes they take, so it directly supports that goal of helping people execute. When they save a YouTube link, Embedly allows them to watch it from directly within our app - no extra steps. When they save an article to read later, it previews it and gives them relevant context. It cuts down on the steps from "I want to…" to "done."

The original feature of Embed being put to use, to help you finish that growing to do list that’s probably making you sick.

Last thing we’d like to add is what Fetchnotes is hoping to see from us in the near future. We build for you, so when you ask us to create something we always try our best to deliver. What is Fetchnotes hoping for?

"One thing I’d love to see from Embedly is to pull in similar results without needing the link itself. So rather than needing the link to a song on Rdio to pull in the preview, it would be awesome if it could find it based off of having the artist name or song in the text."

We’ll be sure to add that to our to do list (cleverly placed statements are my speciality, look out). Awesome to see such a dynamic app using our API and we hope to see more. Make sure to take a look at Fetchnotes to kickstart your productivity. And if you’re using Embedly, let me know, I’ll be diligently writing posts for as long as you contribute! Feel free to email me directly at nina@embed.ly.

Interested in what you could create with Embed? Check it out here, mosey on over to the sign up and start using Embedly for free.

Posted 1 year ago by ninerr
Embed This

As you may know, we co-sponsored a hackday with Traackr and Elasticsearch at Hack/Reduce.  A one-day event centered around Machine Learning and Natural Language Processing that turned out to be a hit.

The event host, George Stathis of Traackr had a few favorites but one stood out to us: Alex Lambert from Spindle. He processed articles from the Economist from the past 5 years and rated them on 3 different mood scales from the Affective Norms for English Words (ANEW) word scores to see if indeed the world is coming to an end, no joke. Thankfully, he came to the conclusion that the world is not ending, so we are all safe…for now.

Embedly’s own Andy and Art created their own “NFL coach”. This one hit close to home as many of the guys in the office, including my lady self, are pretty big NFL fans. They took 10 years worth of very detailed NFL play data and used it to train an ML algorithm to predict what play should be called. Once it was trained, they tested to see how often it made the same call as a professional coach would. The results? Out of 44 thousand plays a year in the NFL, their algorithm would give 1 out of 11 options, out of all of those options, they would get around 22 thousand right. So 50% for a bot acting like a pro football coach? Not bad.

John and Kawan gave a talk at the beginning to get the ideas going. They went in depth on how we use machine learning and NLP in-house to build some of Embedly’s features, including parts of our new product, Extract.


The winner of the Best Use of the Embedly API was Sands Fish. I had the pleasure of interviewing him about his project.

Sand’s idea was to use a large amount of data that he had in the form of 15,000+ tweets from this year’s SXSW conference and “write a service to aggregate all of the tweets containing #SXSWi and #SXSWedu”. He said, “my main goal was to enrich the data as much as possible so I could paint a more complete picture of what happened [at the conference] and get some insight into what ideas, people, and companies were being talked about the most”. Pretty nifty.

"The embedly API was a great fit…while I was only able to enrich tweets that contained links, there were more than 5,000 in this category, and for each of them, the API provided me with a wealth of data about the resources linked to in the tweet". Sands created an image-wall with the data, keeping time in mind, this was the most he felt comfortable creating. Sands mentioned that he had "many ambitions for the data-set" and you better believe we’re excited to see what he comes up with given the luxury of time, post hackday.

Posted 1 year ago by ninerr
Embed This

As reported by Pingdom, Embedly’s uptime for the month of April has been 100%. We pay Pingdom to manage these checks and have configured them to properly monitor the API’s health.

We were pretty surprised when Verelo started reporting on Twitter that we were down. If you have never heard of Verelo (neither had I), they monitor uptime like Pingdom and were recently acquired by Dyn.

Apparently they are also into public shaming to try to drum up business, so we are going to return the favor.

Verelo runs a site called whatsdowntoday.com where they hook up their services to a bunch of sites without notifying them first. They ping them and tweet out at @verelostatus when one fails to pass it’s status check.

They nicely have Tweet and Facebook buttons to share downtime, but no links to the service they are actually checking.

Embedly’s API is one of these services, however, their check is not configured correctly. Verelo does not include an API key in the URL, so when they hit our usage limit for unauthenticated requests we throw errors. If you rely on Verlo we have been down for most of the last 2 days.

Funny enough, this is their API call:


That t.co url redirects to a reddit post for their own press release: https://t.co/04SmeCDl. Zero comments, whomp whomp.

I’m all for trying to to acquire new business, but by publicly shaming people via whatsdowntoday.com is down right dirty.

Attracting customers starts with building relationships, not alienating your target market. Your viral growth hack has turned into spam, time to go back to the drawing board.

If you would like to see Embedly’s actual status, you can check out Pingdom: http://stats.pingdom.com/q1pr2ct042w3

Posted 1 year ago by screeley
Embed This

This is the second post in our series on Ember. We will be building off the development environment we set up in the first post.

In practice, everything is based off the router and templates. Ember handles the dynamic creation of views and controllers. You really don’t need them until you start dealing with data and events.

By default Ember sets up two routes for you: application and index. application is the container for your entire application while index is the route for the root of your site ‘/’. You can create the two templates for these routes in the templates directory.

$ touch app/templates/application.handlebars
$ touch app/templates/index.handlebars

And for good measure we will create a global nav.

$ touch app/templates/nav.handlebars

The application template is a good place to create scaffolding; things that need to be on every page and also inside the scope of the application. Here is our simple application.handlebars:

{{ render "nav" }}
<div class="row">
 <div class="large-12 columns">

We just introduced two handlebars helpers that Ember uses: render and outletHandlebars helpers are a part of the Handlebars template language that is included with Ember. The render and outlet helpers are added by Ember.

About render from the docs:

Renders the named template in the current context using the singleton instance of the same-named controller.

render allows you to include one template into another. It’s much like the template helper, but also allows you to pass data along. In this case you could use either.

outlet is a placeholder that allows you to specify where the child node’s content will be rendered. They are much like {% block %} tags in Django or <%= yield ==%> in ERB.

Since application.handlebars is the base route the content from index.handlebars will be rendered where this outlet is. We can create a simple index.handlebars to prove this.

$ echo "<h1>Welcome To My App</h1>" > app/templates/index.handlebars


Routes are URL paths. To add a new page, you need to add a new route. So to add our about page, we need to add a route to our router.


Ember is creating AboutRoute, AboutView, and AboutController. We don’t really need those for this exercise, but we do need a template with some content.

$ echo "<h1>About To My App</h1>" > app/templates/about.handlebars

If you visit ‘/#/about’ you will see the content.


When you want to start grouping routes, i.e. “/company/contact” and “/company/team” resources come in to play. The benefit here is that they share common templates. While you could so something like this:

  this.route('contact', {path:'/company/contact'});
  this.route('team', {path:'/company/team'});

It becomes a mess really quickly. Instead you should use a resource.

  this.resource('company', function(){

It is however a little more confusing when it comes to templates. Like the application route, we need to create a base container for all the leaf routes. This could be as simple as:

$ echo "{{outlet}}" > app/templates/company.handlebars

In this case, everything will just be added to the outlet in the application.handlebars. If you want every company page to have common display attributes, you can change the template:

<div class="row">
  <div class="large-9 columns">
  <div id="sidebar" class="large-3 columns">
    {{outlet sidebar}}

You’ll notice here that we added a named outlet. By default all content from the leaf routes will go into the {{outlet}} unless we tell it to go somewhere else instead.

We can then create the leaf templates.

$ mkdir app/templates/company
$ touch app/templates/company/index.html
$ touch app/templates/company/contact.html
$ touch app/templates/company/team.html

This is one of the nice things about having ember_templates set up and compiling templates for you. Ember expects the templates to be put into EM.TEMPLATES hash as ‘resource/route’ or you need to declare the templateName on the view. The former is less code.

Custom Routes

We set up that outlet earlier, it’s time that we use it. In order to use named outlets we need to modify the Routes behavior. Here we will change that Company Team Route to add a sidebar. In the main.js file we are going to add:

App.CompanyTeamRoute = Em.Route.extend({
  renderTemplate: function(controller, model){
    // Render the base template
    this._super(controller, model);
    // Render the bios template into the sidebar
    this.render('bios', {outlet: 'sidebar'});

And then add the bios template:

$ echo "<h2>Bios</h2>" > app/templates/bios.handlebars

When you visit /#/company/team you will see the bios section in the template.

Alright, that was a quick primer into the Router and Templates, you can see the final code here: https://github.com/screeley/ember-demo-environment/tree/router. Next week, we’ll go into using View and Controllers.

Posted 1 year ago by screeley
Embed This

Hello there embedders! You might have noticed that we have recently released a couple new products — today we’re going to talk about a couple features of the new /1/extract endpoint. Extract is great when you want to not only embed a URL but get a deeper understanding of its contents.

Let’s write up a quick application that scrapes the front page of any given subreddit and uses the extract endpoint to see what people are talking about by totaling all keywords and entities. Keywords are probably what you expect them to be, while entities are essentially just proper nouns. Note that you’ll need an Embedly API key to run this demo — you can get one for free if you don’t already have one!

First thing’s first: let’s grab the frontpage of a subreddit using reddit’s awesome JSON API. This is just a simple HTTP request to the subreddit frontpage with .json appended to the URL.  We also define a function to extract all of the URLs from this blob:

import sys
import json
import urllib

import requests

def reddit(sub):
    Retrieve the json representation of the given subreddit
    url = 'http://reddit.com/r/%s.json' % sub
    resp = requests.get(url)
    return json.loads(resp.text)

def reddit_urls(js):
    Return all the URLs in the given json blob of reddit data
    return [x['data']['url'] for x in js['data']['children']]

The above code depends on one external package: the excellent requests package, which makes performing HTTP requests very simple.

Now that we have a list of URLs, let’s call embedly’s extract endpoint. For URLs that have any significant amount of text this response will include keywords and entites that summarize the text (take a look at an example response if you’d like to see what else is returned).

def embedly(url, key):
    Call the embedly API and return the json blob. Returns None if there
    is an error processing the URL (e.g., HTTP 404)
    quoted = urllib.quote(url)
    api = 'http://api.embed.ly/1/extract?url=%s&key=%s' % (quoted, key)
    resp = requests.get(api)
    if resp.status_code != 200:
        sys.stderr.write('Failed to process URL %s :(\n' % url)
        return None
    return json.loads(resp.text)

Okay, now we can just loop over all of the responses and sum together all of the counts and take the, say, ten highest counts. The code below operates on entities, but by changing ‘entities’ to ‘keywords’ in the line above sum_counts you can have it look at keywords instead!

def sum_counts(item_lists):
    Takes a list of lists of items and mashes them all together into a dict
    mapping item_name -> item_score. The input items are either entity or
    keyword lists, which look like {'name': 'Dennis', 'count': 10} or
    {'name': 'sports', 'score': 33}, respectively.
    ret = {}
    for item_list in item_lists:
        for item in item_list:
            # get either score or count so we can work with both
            # keywords and entities
            name, count = item['name'], item.get('count', item.get('score', 0))
            ret[name] = ret.get(name, 0) + count
    return ret

def top_n(item_dict, n):
    by_count = sorted(item_dict.iteritems(), key=lambda x: x[1],
    return by_count[:n]

def main(subreddit, key):
    urls = reddit_urls(reddit(subreddit))
    embeds = [embedly(url, key) for url in urls]
    # change 'entities' to 'keywords' to check out the keyword extraction!
    items = [x['entities'] for x in embeds if x]
    all_counts = sum_counts(items)

    top = top_n(all_counts, 10)
    print '\n'.join('%s %s' % (x[0], x[1]) for x in top)

if __name__ == '__main__':
    if len(sys.argv) < 3:
        sys.stderr.write('Usage: demo.py <subreddit> <your-embedly-key>\n')
        main(sys.argv[1], sys.argv[2])

Let’s try it out on /r/sports!

$ python demo.py sports <your-embedly-key>
Ware 3
Sharks 2
Daily Caller 2
Kevin Ware 2
Louisville 2
Cal 2
Taylor Branch 1
San Jose Sharks 1
National Collegiate Players Association 1

Here we can see that the NCAA is by far the most popular entity mentioned, which should be no surprise considering we’re in the height of the March Madness tournament. Kevin Ware also makes an appearance, no doubt due to his unfortunate injury in Sunday’s game.

How about /r/worldnews?

$ python demo.py worldnews <your-embedly-key>
North Korea 66
India 30
Pakistan 27
U.S. 21
China 19
UN 17
Bolkovac 16
United States 14
EU 13
Novartis 13

Looks like North Korea is big right now, which isn’t too surprising considering what’s been going on over there.

Go grab the source if you’d like to play around. There are all sorts of ways to extend this — extract also pulls image metadata, so maybe you could make an image wall sorted by keyword or entity of what’s going on right now. Or use the related article feature to curate content on the current hottest topic. Speaking of related articles, we’ll be showcasing that feature in an upcoming post!

Sign up for a free account to start using Extract and run this example, or check out the other features and demos available for Extract.  Other thoughts? Continue the conversation on Twitter

Posted 1 year ago by thejohnnest
Embed This

This is John.


John works at Embedly and he seems like a normal guy. He likes ultimate Frisbee, a good joke and time with friends. He has 10 fingers and 10 toes, but John was born with a great affliction. From the second he was put on this earth he had to endure overwhelming odds against him. 

You see when John was delivered the doctor held him up, as Rafiki did to Simba, and proclaimed “April Fools.” Yes, John was born on the 1st of April.

Gasp, I know. Let that sink in for a second.

Like millions of “Foolies”, as they call themselves, he was subjected to a childhood of bad jokes. “Your parents must of thought you were a joke…” “Here little Johnnie, I got you the TMNT action figure you wanted. Nope, Ha, April Fools.” “John, we got you a car for your Birthday. Ha, April Fools, here’s a Frisbee.” “John, you were adopted… April Fools!” The courage that it takes, I can’t imagine.

The Foolies are a fellowship. Once a year, while everyone is out pranking they meet at a bar. They drink raspberry beer and not a single giggle is heard. They sit in peace as the world burns around them.

We at Embedly support the Foolies. We will not be participating in what tech has deemed a day of bad jokes thought up by insensitive marketing people to show their company has a “fun side.” It hurts real people like John and we cannot condone such actions.

There will be no scratch and sniff embeds and you will not be hearing Rick Astley.

Instead we will be silent in solemn solace with those less fortunate than us. John, we will not be pranking anyone today, we love you, stay strong.

- Sean

Posted 1 year ago by screeley
Embed This

Every time I see Ember on Hacker News it’s being trashed, like MongoDB trashed. It sucks for an open source project when the herd mentality kicks in and it becomes cool to hate. Sadly, I’m not one of the cool kids.

Ember is excellent. We use it extensively here at Embedly for our developer dashboard. While none of us here are JavaScript experts, Ember has made us incredibly productive.

We are going to do a series of posts on Ember at Embedly. Mostly tips and tricks that have made us successful. These are not aimed at the pro, but the amateur.

A lot goes in to baking a production-quality website, and Ember adds to that. As a result, there is a lot of boilerplate when it comes to setting up the development environment. Rest assured that once you fight through the boilerplate, you’ll be able to iterate at an impressive rate.

Okay, so you have a new awesome idea of what you are going to build, how do you get started?


Grunt is the Javascript Task Runner. It makes the set up of common tools like jshint, compass, uglify and development servers dead simple. We use it in almost every project now and it has made development a whole lot easier.

Yeoman is a thin wrapper around Grunt that really just builds out a directory structure and a few files. One member of your team will use it once and never think about it again.

So, let’s get started.

$ mkdir demo
$ cd demo
$ npm install -g yo grunt-cli bower

At the time of writing, the ember generator for yeoman is hosed, so you can do what you wish with that information. We can just use the default webapp generator.

$ yo webapp
$ npm install & bower install

This will build a pretty simple directory structure.

  app /
  test /

Yeoman sets up the project so it can immediately be used. Run grunt’s server to launch your new web app.

$ grunt server

Tada, a browser will open to http://localhost:9000/ and show a nice little Allo message.

Getting Ember

Bower is Twitter’s package management tool for the Web. Let’s get Ember installed using bower.

$ bower install ember

Bower will handle getting all the right dependencies and install them in a components directory. You will then need to add Ember and Handlebars to your index.html file.

$ vim app/index.html

You can put the following lines near the bottom but above main.js:

<script src="components/handlebars/handlebars.js"></script>
<script src="components/ember/ember.js"></script>

Grunt will live reload your browser. You now have all the dependencies for a simple Ember app. You can prove it by opening up the console and running Em.

To recap, that was about 5 commands to get Ember completely ready to go:

$ npm install -g yo grunt-cli bower
$ yo webapp
$ npm install && bower install
$ bower install ember
$ vim app/index.html

If you complain about how hard Ember is to set up you are using the wrong tools.


Here on out is optional, but will probably save you some headaches later down the road. We will set up grunt-ember-templates, an Application and the Router.

The grunt-ember-templates module pre-compiles all your templates on the fly and adds them to Em.Templates, which is where Ember keeps your templates so it can match them to your views, based on naming convention. More on this later.

$ npm install grunt-ember-templates --save-dev
# Create the templates directory.
$ mkdir app/templates
$ touch app/templates/index.handlebars

We are going to have to update the Gruntfile to run ember_templates

Grunt is configured by a Gruntfile.js, which uses JSON to define a bunch of different actions that Grunt can perform for you. This is where we’ll hook up grunt-ember-templates to Grunt.

$ vim Gruntfile.js

In the Gruntfile, you are going to load the task before, I generally put it before the grunt.initConfig


Inside the grunt.initConfig you will need to set up the compile task to point at all the templates.

ember_templates: {
  compile: {
    options: {
      templateName: function(sourceFile) {
        return sourceFile.replace(/app\/templates\//, '');
    files: {
      "<%= yeoman.app %>/scripts/templates.js": ["<%= yeoman.app %>/templates/**/*.handlebars"]

Next tell the watch command to look for changes in the templates directory to make the live reload work correctly:

watch {
  ember_templates: {
      files: '<%= yeoman.app %>/templates/**/*.handlebars',
      tasks: ['ember_templates']

Lastly, add ember_templates to the server task, you are looking for this line:

grunt.registerTask('server', function (target) {
        'ember_templates', // Add this line.

Once you restart grunt server, you can take a gander at the app/scripts/templates.js file in scripts. It should look something like this:

Ember.TEMPLATES["index"] = Ember.Handlebars.template

Add that script to the index.html file to make sure the browser loads it.

<script src="scripts/templates.js"></script>

That was kind of a detour, you don’t really need to set up ember_templates, you can use inline script tags or Em.Handlebars.compile, but this method offers a nice separation of HTML and javascript. For a quick reference you can see the completed Gruntfile here.


The last step here will be to set up a simple App and Router to take advantage of our setup.

You can add the main.js to the end of index.html and delete whatever is in that file.

<script src="scripts/main.js"></script>

Next set up a rootElement for Ember to use, this will make sure that Ember puts the html where you want it to. Replace the div with the class container with:

<div id="app"></div>

Next add a simple Application to main.js:

App = Em.Application.create({
  rootElement: $('#app'),

You can then edit index.handlebars with a simple h1

$ echo "<h1>My App</h1>" > app/templates/index.handlebars

When grunt reloads the server, your browser will have My App as the header. There is a little magic going on here. Ember is creating a Router for you and by default creates and Application Route and an Index Route. This is why just adding an index.handlebars works.

The Router is dead simple to set up as well. In main.js add


And then create the about template

$ echo "<h1>About</h1>" > app/templates/about.handlebars

If you navigate to /#/about, boom, you are now in the About route. You can also link to the about page from index by adding:

{{#linkTo "about"}}About{{/linkTo}}

This all works based on naming conventions. You can create an AboutController, AboutRoute and AboutView, but Ember will take care of that for these simple routes. More on that later.


Setting up Ember is a lot of boiler plate code, and there are some really good tools out there that do it for you. Nothing I have described above is earth shattering, but it should get you set up for your next Ember project.

I put the complete demo on Github for reference you can find it at github.com/screeley/ember-demo-environment.

For our next post in the Ember series, we will go into Ember basics; Views, Routing and Outlets. Stay tuned.

- Sean

Discuss on Hacker News

Posted 1 year ago by screeley
Embed This

We launched a redesign of our website and developer dashboard yesterday to showcase the three new products that we’ve been working on: Embed, Extract, and Display.


After countless bug fixes and beta testing for ages, we created the three products with your feedback in mind. Today Embedly graduates from embedding content on the web to providing you with tools to build a better user experience. Developers have made us the largest embedding platform on the web. We’re serving half a billion API requests per month to over 15,000 developers who have signed up for our service.

The classic embedding you all know and love is Embed. Digging deeper into articles to reveal the important information is Extract. And Display helps make your images appear beautifully within your website. A short blurb on what each product is made of that doesn’t do them justice, but we’ll do it anyway:

  • Embed: Get the world’s most powerful tool for embedding videos, photos, and rich media into websites.
  • Extract: Use the elements-colors, text, keywords, and entities-that you want from articles. Discard the rest automatically.
  • Display Make the images you use look great-and display quickly-on any screen, every time.

These products are only the beginning of a new chapter for Embedly. We want to provide the tools that developers need to build richer, more engaging sites. The products are separated because we think it makes sense for you to pay for what you use, not what you don’t. Moving forward, we’ll continue looking out to see what is possible, and hearing what our customers need. We’ll build what you’re looking for and what developers are scouring the web for in frontend development. We won’t stop until it’s all here, for you to use.

Posted 1 year ago by ninerr
Embed This