Creating Your Own Theme

By on

Overview

You can create your own theme in AMSF, theme files are located in the following location (I use default theme Curtana here for better understanding):

├── _app/
|   ├── _data/
|   |   └── curtana.yml
|   ├── _includes/
|   |   └── themes/
|   |   |   └── curtana/
|   |   |   |   └── includes/
|   |   |   |   └── layouts/
|   ├── _pages/
|   |   └── themes/
|   |   |   └── curtana/
|   |   |   |   └── example-page.md
|   |   |   |   └── ...
|   ├── assets/
|   |   └── themes/
|   |   |   └── curtana/
|   |   |   |   └── _js/
|   |   |   |   └── _scss/
|   |   |   |   └── ...

The theme specific config curtana.yml should have the same filename as your theme name. It should contain theme-specific variables and can also override AMSF built-in settings.

More info about theme structure you can check out my default theme Curtana.

You can also have multiple themes in your project, as many as you like. For example if you also have themes Bootstrap and Ghost installed, the file structure should be:

├── _app/
|   ├── _data/
|   |   └── bootstrap.yml
|   |   └── curtana.yml
|   |   └── ghost.yml
|   ├── _includes/
|   |   └── themes/
|   |   |   └── bootstrap/
|   |   |   |   └── includes/
|   |   |   |   └── layouts/
|   |   |   └── curtana/
|   |   |   |   └── includes/
|   |   |   |   └── layouts/
|   |   |   └── ghost/
|   |   |   |   └── includes/
|   |   |   |   └── layouts/
|   ├── _pages/
|   |   └── themes/
|   |   |   └── bootstrap/
|   |   |   |   └── example-about.md
|   |   |   |   └── example-blog.md
|   |   |   |   └── example-fluid-container.md
|   |   |   |   └── ...
|   |   |   └── curtana/
|   |   |   |   └── example-about.md
|   |   |   |   └── example-news.md
|   |   |   |   └── ...
|   |   |   └── ghost/
|   |   |   |   └── example-archive.md
|   |   |   |   └── example-page.md
|   |   |   |   └── example-tagcloud.md
|   |   |   |   └── ...
|   ├── assets/
|   |   └── themes/
|   |   |   └── bootstrap/
|   |   |   |   └── _coffee/
|   |   |   |   └── _scss/
|   |   |   |   └── images/
|   |   |   └── curtana/
|   |   |   |   └── _js/
|   |   |   |   └── _scss/
|   |   |   |   └── svg/
|   |   |   └── ghost/
|   |   |   |   └── _js/
|   |   |   |   └── _less/
|   |   |   |   └── fonts/
...

AMSF Options

There’re several built-in options you can use in your theme. These options can also be overridden in theme-specific config.

site.name

Template:

<footer class="footer">
  <ul>
    <li><a href="/">{{ site.name }}</a></li>
    <li><a href="/atom.xml">Atom</a></li>
  </ul>
</footer>

Output:

<footer class="footer">
  <ul>
    <li><a href="/">Almace Scaffolding</a></li>
    <li><a href="/atom.xml">Atom</a></li>
  </ul>
</footer>

site.description

Site description will appear in the document meta and Atom feed subtitle.

Template:

<meta property="og:description" content="{{ site.description }}">

Output:

<meta property="og:description" content="A super-fast Jekyll framework fighting against the website obesity.">

site.file

Media assets URL used in posts, without trailing slash. In most cases this URL should be powered by a CDN provider.

Config:

file: //d349cztnlupsuf.cloudfront.net

Template:

<img src="{{ site.file }}/post-thumbnail.jpg">

Output:

<img src="//d349cztnlupsuf.cloudfront.net/post-thumbnail.jpg">

site.twitter

Site Twitter account handle.

Template:

<a href="https://twitter.com/{{ site.twitter }}">Follow @{{ site.twitter }} on Twitter</a>

Output:

<a href="https://twitter.com/sparanoid">Follow @sparanoid on Twitter</a>

site.force_utf_8

Force UTF-8 encoding, enable this will simply add <meta charset="utf-8"> to the head of your pages.

Template:

{% if site.force_utf_8 %}
  <meta charset="utf-8">
{% endif %}

site.robots

You can define your own records in robots.txt.

Config:

robots:
  - "User-agent: *"
  - "Disallow: /ajax/"
  - "Disallow: /@async"
  - "Disallow: /log/"

Theme Features

There’re some features can be integrated into your theme.

(Basic) Multi-Language Support

You can define post/page language in your front-matter field:

lang:
  - zh-tw

An additional lang HTML attribute will be added to your final rendering:

<article lang="zh-tw">
  ...
</article>

If your post/page content is multilingual, you can also define multiple languages in array:

lang:
  - zh-tw
  - en-us

Please note that only the first item defined in lang array will be used in final lang output, the additional languages will be available in JSON feed output:

{
  "languages": ["zh-tw", "en-us"],
  "categories": ["note"],
  "tags": ["miscellaneous"]
}

Smooshing Assets

For better performance, Almace Scaffolding will find all the CSS, script links and images in compiled HTML, and outputs a version with all the CSS, scripts and images (Base64) written inline. Sounds cool? but it needs theme support. Here’s how:

You can simply add the query string ?assets-inline at the end of the file you’d like to be inlined in production site:

<!-- This CSS will be inlined into HTML -->
<link rel="stylesheet" href="{{ '/css/app.css?assets-inline' | prepend: amsf_theme_assets }}">

<!-- This script will be inlined into HTML -->
<script src="{{ '/js/app.js?assets-inline' | prepend: amsf_theme_assets }}"></script>

User Custom Styles Support

Define the following code snippet into your theme styles (Sass) will allow users to custom your theme without touching the theme files:

// Import user custom styles
@import "../../../_scss/custom";

User Custom Scripts Support

Define the following code snippet into your theme template (it’s recommended to put it in footer) will allow users to add custom scripts without touching the theme files:

<!-- User custom scripts -->
<script src="{{ '/js/user.js?assets-inline' | prepend: amsf_user_assets }}"></script>

Page / Post Specific CSS Block Support

This allows your user to define page / post specific CSS blocks in front-matter data:

<!-- Page-wide custom CSS -->
{{ amsf_page_css }}

Google Analytics Support

This allows your user to be able to use Google Analytics for their site, tracking ID can be changed in the config file:

<!-- Google Analytics tracking code -->
{{ amsf_google_analytics }}

Post Published Time

This allows you to get the published time of the current post.

Template:

<meta property="article:published_time" content="{{ amsf_page_pubdate | date_to_xmlschema }}">

Output:

<meta property="article:published_time" content="2014-01-01T00:00:00+08:00">

Post Modified Time

This allows you to get the modified time of the current post.

Template:

<meta property="article:modified_time" content="{{ amsf_page_update | date_to_xmlschema }}">

Output:

<meta property="article:modified_time" content="2014-01-03T03:17:49+08:00">

Post Reading Time

This allows you to show the average reading time of current post.

Template:

Reading time: {{ amsf_page_reading_time }}

Output:

# Less than 200 words
Reading time: Less than 1 min

# Around 200 words
Reading time: 1 min

# More than 200 words
Reading time: 34 mins

# More than 1 hour
Reading time: 1 hr
Reading time: 1 hr 1 min
Reading time: 3 hrs 20 mins

Publishing Themes

You really like your custom design and wanna show it off to the world? Cool, you can create (pack) you own theme by the following command:

$ grunt theme-save

The activated theme will be saved to AMSF cache (.amsf-cache/) with correct file and directory structure, then you can upload your theme to GitHub.

Still confusing? see my default theme Curtana for reference.