Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Extending Gingko

If you’re willing to play around with the API, you can do some pretty amazing things with Gingko.

API

Gingko’s API can change on occasion, so if you’d like to be notified of any changes, get in touch with me.

GET

Action Method
Get user information GET /api/index
Get all of user’s cards GET /api/cards
Get all of user’s trees GET /api/trees
Get list of tree’s collabs GET /api/trees/:treeId/collaborators
Get all of tree’s cards GET /api/trees/:treeId/cards
Get tree export GET /api/export/:treeId.:format

Get user information

GET /api/index

curl -u you@email.com:password https://gingkoapp.com/api/index

Response

{
 "_id":"50abcdef12347c360b000001",
 "email":"you@email.com",
 "limit":-1,
 "hasStripeId":false,
 "createdAt":"2012-11-18T15:45:45.197Z",
 "treesCount":150,
 "cardsCount":12970,
 "favoriteTrees": ["42a08d2a519abcdefgh12345",
 "42a08d2a519abcdefgh12346","42a08d2a519abcdefgh12347"],
 "randomIndex":82,
 "userHash":"abcde12345",
 "offers":{},
 "csrf":""
}

List all trees

GET /api/trees

curl -u you@email.com:password https://gingkoapp.com/api/trees | python -mjson.tool

(python tool is optional, to format JSON response nicely).

Response

[
    {
        "__v": 0,
        "_id": "6e9bncfcvttpjealtkb2tfdw",
        "createdAt": "2012-11-19T02:22:41.530Z",
        "latex": true,
        "name": "Ideas",
        "owner": "50abcdef12347c360b000001",
        "updatedAt": "2014-08-05T21:46:15.333Z",
        "users": [
            "50abcdef12347c360b000001"
        ]
    },
    {
        "__v": 0,
        "_id": "yij7q888czecbermdwwn59gy",
        "createdAt": "2012-12-14T21:03:26.000Z",
        "name": "Archive Tree",
        "owner": "50abcdef12347c360b000001",
        "updatedAt": "2014-08-13T11:30:42.322Z",
        "users": [
            "50abcdef12347c360b000001"
        ]
    },
    {
        "__v": 0,
        "_id": "kilgsbxzg6e1pwyajcjd7dl7",
        "createdAt": "2012-11-28T21:11:19.029Z",
        "name": "Screenplay: Alien (1979)",
        "owner": "50abcdef12347c360b000001",
        "publicUrl": "alien-1979",
        "updatedAt": "2014-04-18T12:47:29.279Z",
        "users": [
            "50abcdef12347c360b000001",
            "50abcdef12347c360b000002"
        ]
    }
]

Get exports

You can use the API to get any of our supported export formats (txt, html, json, docx, impress). You can also use flags like column=3 or cardId=someCardId.

Simplest option is to export the view you want from within the app, and copy the URL & parameters.

PUT/POST/DELETE Cards

Action Method
Create new card POST /api/trees/:treeId/cards
Modify card by id PUT /api/trees/:treeId/cards/:cardId
Delete card by id DELETE /api/trees/:treeId/cards/:cardId
Import from JSON or Markdown POST /api/trees/:treeId/cards/seed

Create new card

POST JSON data to /api/trees/:treeId/cards

Schema:

var CardSchema = new Schema({
  content: { type: String, default: '' },
  position: { type: Number, required: true },
  treeId: { type: ObjectId, required: true },
  parentId: { type: ObjectId, default: null, validate: notId }
  // plus private fields
});

I’m aware that requiring position index is tricky (for instance, adding a card to the end of a list requires that you know the index of the last card). I’m working on a fix for this.

Modify card by id

PUT JSON data to /api/trees/:treeId/cards/:cardId

Can update content, position, and parentId.

Import from JSON or Markdown

POST JSON data to /api/trees/:treeId/cards/seed

Import Markdown:

{ "parentId": "someParentId" || null,
  "seed": "# Readme\nThis is some markdown document"
}

You can also import a JSON string in seed, using the format that Gingko exports JSON in.

Note that neither of these “import” functions will replace any part of your tree. The card someParentId will simply have a new subtree with this content (if null then the subtree will start in first column).

PUT/POST/DELETE Trees

Action Method
Create new tree POST /api/trees
Copy your private tree by id POST /api/trees/:treeId/clone
Copy a public tree by id POST /api/trees/:publicTreeId/clonePublic
Modify tree PUT /api/trees/:treeId
Delete tree DELETE /api/trees/:treeId

Client-side

Open up your browser’s console, and play with this. To prevent headaches, make a copy of your tree before messing with this.

app object

The Global app object is the main way to interact with your current tree. You can get a list of all cards, edit content, clear your trash, or do several other actions that don’t yet have a UI attached to them.

Sample methods of app object

Get currently active card’s id

app.get('cardId')

Get current tree model

app.get('currentTree')

Get children ids of current card

app.graph.children(app.get('cardId'))

Array of all cards (models & views)

To get an array of all cards:

app.get('cards')

This is an array of the card views. Use:

app.get('cards').models

to get the Backbone.js models for the cards.

Example: Find & Replace

For example, to do a “find and replace”, paste this code in your browser’s console:

function findAndReplace(find,replace){
  app.get('cards').models.map(function(c) {
    if(c.get('content').match(find)) {
      c.saveContent(c.get('content').replace(find, replace));
  }});
}

For the rest of the browser session, you can type:
findAndReplace("some text", "replacement text")
and press enter.

Events

You can trigger almost any event manually. Here are some examples:

Backbone.trigger("key:up");
Backbone.trigger("key:edit");
Backbone.trigger("key:save");
Backbone.trigger("key:bold");
Backbone.trigger("key:addDown");
Backbone.trigger("modal:show:new-tree");

To react to events, you can use Backbone.on:

Backbone.on("card:save", function(id){console.log(id, 'do something')})

Events:

  • card:edit
  • card:save
  • card:cancel
  • … (see Debug Mode for more events)

Custom Shortcuts

By binding to the Moustrap.js global object, and triggering Backbone events, you can create shortcuts for your own actions (or override the defaults).

Mousetrap.bind('mod+enter', function(e) {
  if (app.get('keyscope') === 'editCard') {
    Backbone.trigger("key:save", e);
  } else if (app.get('keyscope') === 'tree') {
    Backbone.trigger("key:edit", e);
  }
  return false;
});

Debug mode

In order to see all the events that are being triggered, you can paste the following into the console:

trigger = Backbone.trigger;
events = [];

Backbone.trigger = function() {
  var args, name, now, time;
  args = _.toArray(arguments);
  name = _.first(args);
  events.push(name);
  console.log(args);
  trigger.apply(Backbone, args);
  events.pop();
}

Examples

Send emails to a given card, automatically create a PDF from Gingko’s LaTeX output. If you use Gingko’s API for something, no matter how small or specific your use case, please share it with me, so I can add it here.

Add to Gingko via Alfred

If you use Alfred, you can quickly jot down a note in a designated Gingko tree:
https://github.com/fabianmu/alfred-add-to-gingko

Thanks to @fabianmu for this one.

Node - Gingko TeX to PDF

“And the other I fixed with a little post-production. Actually, I wrote a node server that mashes a header and footer around the LaTeX output from Gingko and spits out a nice PDF in about 3-5 seconds.” - A user

https://gist.github.com/AdrianoFerrari/653da1d745dcf8dd31b6

Further Ideas

As an exercise, try using http://zapier.com to:

  • Update an existing card with, say, your last tweet.
  • (harder) Copy the body of any Gmail message you label ‘gko’, to a new card.

Or how about getting raw Markdown from Github README’s, and displaying that as a gingko tree?