Building content services
Clone this wiki locally
While all the software architecture is really nice and all that, it's all pointless without engaging, interesting, useful and fun content to be printed.
(If you haven't already looked at the general system architecture, please take a look; it will make some of this make more sense.)
The beauty of this software is that it's very simple to turn content into printouts; you just need to produce some HTML, and the printer system will take care of the rest. But even with that said, there are a few things to be aware of that will make your life easier.
Printing from a static page
The backend provides one such page, called sample.html
There are a few key features:
- including the print.css
previewclass on the
print.css and page width
Little receipt printers have a very small page width -- normally 384 pixels. The backend server tries as hard as it can to constrain the width of the content for printing to fit in this space, but at the moment it's still possible for a page to accidentally grow to a greater width, which will cause printing to fail.
The print.css stylesheet provides a few small styles to help constrain your content to 384px. All you need to do is wrap your content in an element with the
content class, and this will be set to the correct width.
I strongly recommend that you don't put any other content on your page outside of the
content element (with the
preview caveat I'll explain below.
Designing inside a plain white
div isn't very inspiring, and also doesn't communicate anything about the margins which will be present on the final printout.
To help give a more realistic preview, print.css also includes a style for a
paper element, which is intended to wrap around the
content element described above, like so:
<div class="paper"> <div class="content"> <h1>Your content</h1> </div> </div>
If you give the
body element of your page the
preview class, your content will then appear centered and with approximate margins, making it much easier to design. When the backend server performs its rasterisation, it removes this
preview class, reverting the page back to its plain, unadorned version.
You can also use this
preview is not present.
Printer.printPage -- which you can connect to links or buttons on your page.
(If you are running your own print backend, or a local one, you can also change the value of
Printer.backendUrl to point to your server. The default is
Printer.previewPage function simply posts the entire content of the current page to the backend server, and then redirects you to the preview page (which will reload until the preview is ready). This is a good way of checking how fonts will appear during the rasterisation process.
Printer.printPage expects a printer ID and a callback, which is passed through to jQuery's ajax mechanism. It also posts the page content to the server at
In this way, you can design, preview and test-print HTML without needing to deploy any content to publicly-accessible servers.
Building a simple application
Printing from a static HTML page is great, but it's not exactly interesting. Much better would be to have an application that other people could interact with to produce printouts!
The printer-mail application is a very simple example of such an application. It lets people send 'messages' to other people's printers.
The README on github gives a reasonable overview of how the software works, but in a nutshell there are two distingushing features from our simple page above:
- The application stores print URLs
- The application posts a url to the backend, rather than HTML content
Storing print URLs
In order to use the application, printer owners must "register", which in this case means finding out your print URL (if you have a printer connected to the
printer.exciting.io backend, you can find your URL by visiting http://printer.exciting.io/my-printer), and then using a form to store this along with a "nickname" in a small database. This nickname is used to retrieve the print URL when friends visit the application.
For example, if I people to send messages to "lazyatom", and my print URL was
http://printer.backend.server/print/abc123, then I'd use both those values in the registration.
Posting urls for printing
When the friend of a printer owner sends them a message, the content of that message is saved by the application, and associated with the nickname/print URL record. Immediately after saving this data, the application sends a request to the print URL in roughly the following form:
POST http://printer.backend.server/print/abc123 url=http://printer-mail.server/message/457345
url parameter corresponds to a page in the mail application which will display the sent message in a suitable manner (width, styling, as described above) to be printed.
The backend printer will then request that URL, download the content and get busy with preparing it for the printer connecting to it with the ID
That's pretty much the whole application, in a nutshell. The printer-paint application follows almost exactly the same pattern (much of it was entirely copied).
It's really a trivial demonstration, and if you were really interested in producing something similar you would probably want to add things like robust validation, checking for duplicate registrations, removing your printer, restricting who could send you a message, and so on.
Printing when someone presses a button is a bit more interesting than a static page, but it also doesn't quite reach the promise of waking up to a nice bundle of interesting and relevant content that's been automatically prepared for us.
Thankfully, it's only slightly more work to remove our friends from the printing procedure entirely and have the content be prepared and sent to the printer entirely automatically.
The printer-weather application is a very simple demonstration of exactly this. For every printer than is registered with it, a custom weather forecast is prepared and downloaded by the printer at 8am sharp, every day.
You can view the source to find out more about how it's put together, but there is only one significant difference between it and the mail and paint examples above:
- automatic scheduling of print URL posting
As with printer-mail, the application requires you to "register" your print URL (although no nickname is required), and this is stored in a database. In order to give you an accurate weather forecast, the application needs to know where in the world you are, and so the simplest possible way to do that is to use geocoding to estimate your location from your IP. This is also stored against the print URL, and the record is given a unique ID.
Nothing else happens until the scheduler (which could be "cron", but in this case is the Heroku scheduler addon) wakes up at 8am GMT.
... and at 8am...
When the scheduler wakes up, for every record in the database, it sends a request:
POST http://whatever.printer.backend/print/:printer-id url=http://weather.service.host/jobs/:job-id
When a backend server requests
http://weather.service.host/jobs/:job-id, the appropriate record is loaded from the database, and the IP is used by the (extremely hacky) weather code to ultimately produce some weather data, which is finally rendered in HTML (with icons drawn in HTML5 canvas tags -- fancy).
The backend then dutifully consumes the content and hands it off the appropriate printer as before.
Were this a more robust application, it would ask you for your location as part of the registration, validate it and store that against the print URL, rather than the IP. It could also store your name and use that in the printout to be friendly.
Beyond these toys
The point is simply that an application could store whatever data it wants with a print URL, and use that to produce interesting and useful content. A very similar service could as easily be loading todo lists by obtaining a Google data token on behalf of the user, or printing out the latest twitter mentions by storing a twitter OAuth token.
The only limit is your imagination and creativity, and your ability to turn that into HTML.
Now get to it!