Big tables mess no more. Inker provide all the mechanics for creating sane email templates & keeping a clean workflow.
Documentation http://posabsolute.github.io/inker/
Inker is:
- Built on top of Zurb Ink
- Sane CSS components structure with sass
- Sane HTML components structure with nunjuck
- Auto generate template to HTML documents with inlined CSS
- Auto deployment on litmus for testing
- Auto deployment to any email address for testing
- Basic REST mail sender server.
Inker require npm & grunt to be already installed.
git clone https://github.com/posabsolute/inker.git
cd inker && npm install
You have now everything you need to use inker. Your first stop would be the example in src/templates to help you get started.
- grunt watch - Watch source folder for changes & generate dist files
- grunt css - Build CSS
- grunt html - Build HTML templates
- grunt build - Build css & html
- grunt connect *- test emails in your browser from the root folder (http://0.0.0.0:8555/)
- grunt email - Send a test email to any email inbox
- grunt litmus - Send a test email to litmus
Inker use Zurb Ink responsive css framework, everything in Ink is available in inker, please refer to their documentation. Inker also use the meta framework ITCSS for the files & folders structure. Better explained by this image. The css can be found in src/css
base.scss is your base CSS file importing all needed files for inker, if you add a css component you must import it in base.scss.
It is important to note that since we inline style to html nodes it make no sense to pick & choose components you want to use as it will make no difference on the file size in the end
Responsive rules are in the folder 8_trumps, please note that these rules are added to the document head instead of inlined using data-ignore="ignore" in the html templates.
<!-- external styles -->
<link rel="stylesheet" data-ignore="ignore" href="../css/style.css" />
<!-- embedded styles -->
<style data-ignore="ignore">
/* styles here will not be inlined */
</style>
Open 7_themes, you will see there is already a folder called sidebarhero used for the sidebar hero template. Add a new folder in 7_themes for your template, your main css file will be automatically generated in dist/css/[your folder].
Them in your html use:
{% block theme_css %}<link href="../../css/sidebarhero/sidebarhero.css" media="all" rel="stylesheet" type="text/css" />{% endblock %}
Inker use Mozilla Nunjucks to build html templates, please see nunjucks documentation for more information on how you can take inker even farther.
Inker as an html components stucture that use nunjucks macros. Example of component:
{% macro button(label='default', link='#', class='', align='left') %}
<table class="button {{class}}" align="{{align}}">
<tr>
<td>
<a href="{{link}}">{{label}}</a>
</td>
</tr>
</table>
{% endmacro %}
// Import the component in the base.html file in html-components folder.
{% from "/html-components/component.button.html" import button %}
Usage in html template:
{{ button('Go to google', 'http://www.google.com', 'button-green', 'left'); }}
When creating new components remember to add them to the base.html file situates in src/html-components
Open the templates folder, you should see a folder sidebar_hero, add your own folder here. Please refer to sidebar_hero for a complete example.
{% extends "/html-components/base.html" %}
{% block main_css %}<link href="../../css/main.css" media="all" rel="stylesheet" type="text/css" />{% endblock %}
{% block theme_css %}<link href="../../css/sidebarhero/sidebarhero.css" media="all" rel="stylesheet" type="text/css" />{% endblock %}
{% block responsive_css %}<link href="../../css/responsive.css" media="all" data-ignore="ignore" rel="stylesheet" type="text/css" />{% endblock %}
{% block meta_title %}Email title in document head{% endblock %}
{% block mainContent %}
{% block header %} {% include "/templates/sidebar_hero/header.html" %} {% endblock %}
{% block content %} {% include "/templates/sidebar_hero/content.html" %} {% endblock %}
{% endblock %}
There is a bit of a duality with Inker, it use a templating engine to generate template but must not use it with personalized data so that it can be generated by another templating engine.
Inker enable you to use a custom syntax so to not interfer with your templating engine of choice. If you do use a custom syntax you will have to replace the current implementation with the new syntax, but that should be pretty easy.
nunjucks: {
options: {
data: grunt.file.readJSON('data.json')
}
}
Inker can use json files as a source of dynamic data, example wout want to test a product loop.
This is a built-in feature of grunt-nunjucks-2-html.
nunjucks: {
options: {
data: grunt.file.readJSON('data.json')
}
}
Current list of implemented component. (I am always looking to add more components to inker.)
Options:
- Label
- Link
- Class to add
- Alignement
Usage:
button('Go to google', 'http://www.google.com', 'button-green', 'left');
Render:
<table class="button button-green" align="left">
<tr>
<td>
<a href="http://www.google.com">Go to google</a>
</td>
</tr>
</table>
Options:
- width of bars
- progress
- label
- Class to add
Usage:
progressbar('100%', 70, 'Your progress so far', 'progressbar-green');
Render:
<table class='progressbar progressbar-green' cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class='foreground' style='' width="70%">
Your progress so far
</td>
<td class="background" width="30%">
</td>
</tr>
</table>
Please refer to campaign monitor chart to see what email client support video, fall back to an image.
Options:
- width
- height
- video_src
- video_link
- video_image_placeholder
- class
Usage:
video(320, 176, 'http://www.google.com', 'http://www.google.com', 'http://www.google.com', 'video-big');
Render:
<div class="video_holder video-big">
<video width="320" height="176" controls>
<source src="{{video_src}}.mp4" type="video/mp4">
<source src="{{video_src}}.ogg" type="video/ogg">
<a href="{{video_link}}" ><img height="176"
src="{{video_image_placeholder}}" width="320" /></a>
</video>
</div>
Options:
- Label
- Width
- Class
- Align
Usage:
caption('This is a cat', '320px', 'caption-red', 'left');
Render:
<table class="caption caption-red" cellpadding="0" cellspacing="0" width="320px" border="0", align='left'>
<tr>
<td align="center">
<img src="http://placekitten.com/g/300/300" alt="" />
<div>This is a cat</div>
</td>
</tr>
</table>
Options:
- Label
- size (default: twelve)
- Class
Usage:
panel('This is a panel', 'twelve', 'panel-red');
Render:
<table class="twelve panel-red columns">
<tr>
<td class="panel">
This is a panel
</td>
<td class="expander"></td>
</tr>
</table>
Inker use grunt-nodemailer to send test. By default it send a test for all files that are in the output folders, you can easily change that in gruntfile.js.
However a better way to use it would be to change the path directly from the grunt command. This make it possible to send tests really fast with different templates.
// Override default src provided in gruntfile
grunt email --fileSrc=dist/output/example.html
Config example:
nodemailer: {
options: {
transport: {
type: 'SMTP',
options: {
service: 'Gmail',
auth: {
user: '[email protected]',
pass: 'BLAH'
}
}
},
recipients: [
{
email: '[email protected]',
name: 'Jane Doe'
}
]
},
src: ['dist/output/*.html']
},
Grunt litmus documentation.
grunt litmus:dist/output/sidebar_hero/index.html
The most used email clients are already set in the config file.
litmus: {
test: {
src: ['email.html'],
options: {
username: 'username',
password: 'password',
url: 'https://yourcompany.litmus.com',
clients: [
//gmail
'gmailnew', 'ffgmailnew', 'chromegmailnew',
// outlook
'ol2002', 'ol2003', 'ol2007', 'ol2010', 'ol2011', 'ol2013',
// hotmail
'outlookcom', 'ffoutlookcom', 'chromeoutlookcom',
//Yahoo
'chromeyahoo',
//applemail
'appmail6',
//mobile
'iphone6plus', 'iphone6', 'iphone5s', 'androidgmailapp', 'android4', 'ipad',
// spam check
'messagelabs'
]
}
}
},
Inker comes with a basic nodejs rest api that can handle outputting templates with custom variables & sending emails throught SMTP to any email provider. In it's current state I would recommend keeping it internal & not opening it completely to the web.
Their is a public Postman collection for your convenience for testing the api. https://www.getpostman.com/collections/5e0cbbb46d8e9fff3c8d
Install all dependencies
npm install
Start the server
node src/server/server.js
The server has a basic auth system. It expect a token for each request. This token is set in /src/server/config.js
Default:
X-Authorization-Token : asd98a7s9898asdaSDA(asd987asda*(&*&%))
The API also use nunjucks to render custom variables, but since it is a 2 step process (grunt build & then applying personalized data), the syntax has been changed to avoid conflicts. This is configurable in /src/server/config.js.
"POST /templates/[path & name to template]"
Base path is dist/output
Example:
"POST /templates/sunday/index"
// Post data
{
"name":"Cedric",
"loop": ["1","2","3"]
}
The api can send email to a variety of smtp service, notably MailGun, Mandrill, SendGrig, Gmail, etc. You can see the full list in /src/server/serviceAuth.js
Example:
"POST /email/send"
// Post data
{
"template" : {
"src":"data_example/index.html",
"data": {
"name":"Cedric",
"loop": ["1","2","3"]
}
},
"options" : {
"from": "sender@address",
"to": "[email protected]",
"subject": "hello",
"text": "hello world!"
},
"service" : {
"name":"MailGun"
}
}
You must add your credentials in /src/server/serviceAuth.js
Thanks to Litmus for providing free email client testing for this project.
I'm always happy to accept contributions, i'm currently looking for more components & example, but please follow ITCSS guidelines & please test your new components in the most used email clients.
The MIT License (MIT)
Copyright (c) 2014 Cedric Dugas http://www.position-absolute.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.