photo

New York City FC Launch

We are excited to introduce the new New York City FC site! The new site is built by the MLS Digital team on our next generation content publishing platform, which is built with Drupal on Amazon Web Services. It is designed from the ground up to deliver a consistent, seamless experience across desktop, tablet and mobile devices. Start following NYC FC now as they get ready to join MLS next year.

Hans Gutknecht - @hansyg
Justin Slattery - @jdslatts
Louis Jimenez - @LouisAJimenez
Chris Bettin - @chrisbettin
Amer Shalan - @pterodactylitis

 photo

The MLS Digital Dev team has been working on some new features for our Golazo MatchCenter and we wanted to give our fans a chance to check them out and give us some feedback before we include them as standard features. Feel free to post feedback on Reddit or to post it on our User Voice Page. We will be running the trial features for the next week before we make decisions about what will go into production.

Moderated Stats

Golazo moderators now have the ability to generate a snapshot of a stat (along with some commentary) any time during the game for inclusion in the game timeline. You can filter out this content using the timeline filters if you prefer not to see the stats.

Stats in feed

Stats Sharing

You are now able to a click a share icon by each stat graphic on the stats page and capture a snapshot of that graphic for the current minute of the game. You will then be prompted to share the stat on Twitter, Facebook, G+, or via email. Golazo will automatically generate a rich piece of shareable content on the chosen social network with a link back to the match.

This feature is hidden behind a flag. To access it, add ?share=true to the stats page URL.

Example: http://matchcenter.mlssoccer.com/matchcenter/2014-07-27-montreal-impact-vs-portland-timbers/stats?share=true

Share Button

Choose Network

Photo Expansion

We are currently testing two alternative views of the timeline. Currently, photos are collapsed to a short preview image and must be expanded to be fully viewed. This experience works well on a mobile device but feels wrong on the desktop. We have created two new modes to try and address this.

Expand mode - Photos will all be automatically fully expanded on the desktop. To access this mode, add ?timeline-photo=expand to the feed URL.

Example: http://matchcenter.mlssoccer.com/matchcenter/2014-07-27-montreal-impact-vs-portland-timbers/feed?timeline-photo=expand

Collapse mode - Only the most recent photo will be fully expanded on the desktop. Photos lower in the feed will automatically collapse. To access this mode add ?timeline-photo=collapse to the feed URL.

Example: http://matchcenter.mlssoccer.com/matchcenter/2014-07-27-montreal-impact-vs-portland-timbers/feed?timeline-photo=collapse Choose Network

We encourage you to check out the Sounders/Galaxy game tonight using the new features. The links are below.

Have fun and let us know what you think!

Justin

 photo

Re-Sign iOS App

If you ever work with 3rd party developers, you know that getting the final project into production can take two different routes. You can either let the developer push the code/project into production or they hand it over to your internal team to release. There are pros and cons for each, but I always prefer to publish things ourselves since it reduces security concerns and gives us more control. The Apple App Store is no different, and it is actually really simple to take a developer app and turn it into an App Store version for submission.

Note: You can use this exact same process to resign the app to your developer certificate and profile, so you can install it on your own registered developer devices.

Get a developer build

Get your developer to give you the .IPA file that is signed using their normal “iPhone Developer” key. They do this all the time to test the app on physical devices they own.

Get your tools in order

You will need the following:

  1. A “Mobile Provisioning Profile”
  2. An “Entitlements.plist”
  3. An “iOS Distribution Certificate”
  4. iReSign OS X app (or you could use command line)

1. Mobile Provisioning Profile

Download (or create then download) this from the “iOS Provisioning Profiles” inside of Apple Developer Members Center.

iOS Provisioning Profile

2. Entitlements Plist

You will actually need to make this yourself. You will need two values to make the strings required. You need the App ID Prefix and the Bundle ID. You can find them in Members Center “Certificates, Identifiers & Profiles” under Identifiers > App IDs.

iOS App IDs

Open your favorite text/code editor and drop this in. Then update the two values for “PREFIX.yourappBundleID” in the following code and save it as “entitlements.plist”.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>application-identifier</key>
    <string>PREFIX.yourappBundleID</string>
    <key>aps-environment</key>
    <string>production</string>
    <key>get-task-allow</key>
    <false/>
    <key>keychain-access-groups</key>
    <array>
        <string>PREFIX.yourappBundleID</string>
    </array>
</dict>
</plist>

If you are NOT using Push Notifications, you need to remove the two lines:

<key>aps-environment</key>
    <string>production</string>

3. iOS Distribution Certificate

You should have this installed already. If not, you can get it installed via Xcode or Member Center.

  • Xcode > Preferences > Accounts

  • Find or add your Apple ID and click “View Details…”

  • ”+” “iOS Distribution” (or iOS Development) and then Refresh (bottom left)

Re-sign the .IPA

Download the iReSign app.

Fill in all the values required.

iReSign and Views Configuration

Press the “ReSign!” button and you get yourappname-resigned.ipa. You can now submit it for App Store review via the Application Loader.

 photo

Part 3 - Documentation

Welcome to the third and final installment of our three part series about the MLS API. Check out the first and second posts in case you missed them.

User documentation is important. Especially if you expect anyone outside your organization (or anyone other than the original developer, really) to actually use your API. The docs need to show how to use the API and cover all the available routes, the parameters they accept, and so on. Most developers consider writing docs a huge pain. We certainly do.

Manually writing documentation is, at best, a tedious and error prone process. Like any tedious, error prone process, we wanted to figure out a way to automate it. In this post, we will show you how we did just that. Using our Respectify module and a handful of templates, we are able to generate documentation directly from the API code, thus guaranteeing that it will always stays up-to-date and greatly reducing the surface area for documentation errors.

In the last Respectify post, we went over how we define specifications and the type of information a Respectify specification can return. Now, in order to make these specifications into something more palatable to humans, we create markdown templates to transform the specifications to markdown documents which can be rendered to HTML by a variety of tools.

Example markdown template:

## Table of Contents

* [Routes](#routes)
<% specs.forEach(function(spec) { %>
  * [<%= spec.route %>](#<%= spec.route.replace(/:|\//g, '').toLowerCase() %>)
<% }) %>

## Routes

<% specs.forEach(function(spec) { %>
#### [<%= spec.route %>](#<%= spec.route.replace(/:|\//g, '').toLowerCase() %>)
<% if (spec.description) { %>
<%= spec.description %>
<% } %>
Method: `<%= spec.method %>`<br />
Versions: `<%= spec.versions.join('`, `') %>`
<% if (spec.parameters && spec.parameters.length) { %>
##### Parameters

<% (spec.parameters || []).forEach(function(param) { %>* `<%= param.name %>` -<% if (param.description) { %> <%= param.description %><% } %> (`<%= param.dataTypes.join('`, `') %>`)<% if (!param.required) { %> (optional<% if (param.default) { %>, default `<%= param.default %>`<% } %>)<% } %><% if (param.dataValues && param.dataValues.length) { %>
  - Valid values are: `<%= param.dataValues.join('`, `') %>`<% } %><% if (param.hasOwnProperty('min')) { %>
  - Minimum: `<%= param.min %>`<% } %><% if (param.hasOwnProperty('max')) { %>
  - Maximum: `<%= param.max %>`<% } %><% (param.notes || []).forEach(function(note) { %>
  - ***Note:*** <%= note %><% }) %>
<% }) %><% } %>

<% }) %>

Route documentation generated during the build process can easily be incorporated into existing documentation. The code below output’s the template into our API project’s documentation.md file. We then use Github’s markdown rendering engine to display it. This can easily be done by using an HTML template instead of markdown.

var _ = require('underscore')
  , fs = require('fs')
  , restify = require('restify')
  , Respectify = require('respectify')
  , server = restify.createServer()
  , respect = new Respectify(server)
  , template = '...assume above template...'

server.use(respect.middleware)

// add some routes...

var specs = respect.loadSpecs()

var output = _.template(template, {
  specs: specs
})
fs.writeFileSync('path/to/docs.md', output)

Here is what the output will look like:

This gives us a readable markdown file that contains the documentation for our API, but let’s take this one step further and convert the markdown into HTML to create a static documentation site. We use the marked library to render the markdown files during our build process. As this can be done many ways (or skipped altogether) we won’t go into the details.

We were able to use some of the time we saved not hand editing files to create some fancier layouts and styles. Here is what our finished documentation pages come out as:

The main benefit in this strategy is that we automatically generate and deploy our external documentation whenever we build and deploy changes to the API. This ensures that our clients always have access to current, accurate, documentation (assuming there are no bugs).

The Respectify module has enabled us to ensure our API has consistent parameter validation, programmatically readable route information, and automated documentation. But, from a busy developer’s point of view, the best part of all is that we never have to manually update markdown or HTML files. We can just hit the deploy button, sit back, and drink our morning coffee.