-
Notifications
You must be signed in to change notification settings - Fork 35
Design
In this document I'll go through a possible design/features for Antwar based on my personal needs. My goal is to port my blog (~200 posts) to run on top of Antwar. The plan is to host it on top of gh-pages
. I'll want to reach feature parity with the current solution and then improve on that.
The current blog is quite simple. There's an index listing some of the recent posts (about five) in their entirety. In addition it is possible to navigate to a page of a specific post or tag.
The url structure goes like this:
- post -
<year>/<double zero padded month>/<slug based on post title fixed to 29 characters>
- tag -
search/label/<name>
, examplesearch/label/software%20development
. Navigation goes like this?updated-max=2013-12-31T20:18:00%2B02:00&max-results=20&start=9&by-date=false
That's actually it. There are just three types of pages in the blog currently.
The blog has been complemented with a couple of widgets. These include:
- Popular posts - visible at footer, lists just about ten of the most popular ones
- Tags - visible at footer, lists tags of the blog (links to that specific tag) and amount of pages per each
- Comments - visible at footer, lists recent comments (based on Disqus). In addition each post page has a Disqus widget in it.
- RSS - visible at footer, based on Feedburner
At one point I had a listing per year/month but ended up dropping it. In addition the layout has changed a lot over the years. I've settled for a simple header - content - footer kind of thing.
Currently posts are authored using HTML with Blogger editor (ugh). Besides text the posts contain often an image or two and some source code. Often I have embedded just a Gist. I know this isn't a good idea, though, given the gists won't be visible in RSS.
That's the blog in its entirety. There are a couple of problems with the current design. It can be difficult to find content (it's buried below tags). If you want to find something, you'll need to navigate through tag specific page. I doubt many do that.
In order to port the blog over Antwar, at least the following features should exist:
- Front page - List recent posts
- Footer - Popular posts, tags, comments, RSS widgets
- Routing for posts - Former should retain current scheme and provide reroutes for possible new one
- Tags - It should be possible to attach tags to each post. This is also needed for tags widget. Tags require some routing of their own (index per tag + pagination)
- Posts - A way to author posts (Markdown is ok), attach code (with highlighting!) and images to them
A lot of this is very basic functionality for a blog. I'll cover what this means for Antwar architecture next.
As discussed earlier we should aim for a pluggable architecture and keep the core of Antwar as simple as possible. The question here is where to draw the line. Conceptually the architecture can be split up like this:
- core - API needed for generating a build, running development server. The core encapsulates webpack and in addition generates needed directories and files.
- cli - Wraps core and provides convenience utilities. This is the user facing part.
- themes - The core uses a theme when building the project. The used theme is provided through site configuration. It represents the basic outlook of a project.
- site - A site may be generated using the cli. It contains configuration required to build it (
antwar.config.js
,package.json
) and artifacts such as posts.
As said earlier, the core just wraps Webpack and deals with the generation. The API can be as simple as:
antwar.build(config).then(...).catch(...)
antwar.develop(config).then(...).catch(...)
We'll leave it up to consumer to deal with possible errors. Ideally the consumer would have power over logging (console
can be a part of config).
The cli just wraps core and provides a couple of utilities beyond it. These include parsing antwar.config.js
and joining it with defaults. Extra utilities include --init
, --serve
and deployment related tooling.
antwar.config.js
is a module which returns an object structure like this:
'use strict';
module.exports = {
theme: 'antwar-default-theme', // points at theme based on NPM package name
output: 'build', // where to output the build
plugins: { // plugins deal with structure
// the tag plugin would operate based on posts tags metadata + provide a data source that can be used for routing
// ie. it would shape ['foo', 'bar'] into [{name: 'foo', url: '...', posts: [...]}, {name: 'bar', url: '...', posts: [...]}]
// you can see url shaping function below
'antwar-tags': {
route: function(meta) {
// return path to tag
}
},
// there could be an image plugin to deal with thumbnail generation
'antwar-images': {}, // is this actually needed here? push to higher level?
'antwar-popular-posts': { // https://www.npmjs.com/package/ga-server
id: '...',
clientEmail: '...',
privateKey: '...'
}, // adds popularity field for each post
},
// meta - it should be possible to attach data here that's available per template
title: 'My demo blog',
// routing - a theme may define something but it makes sense to be able to override it
routes: {
post: function(meta) {...}, // examples below
}
};
It should be possible to shape routes. Below you can see examples of post routes. Each post route is derived based on post metadata. This includes antwar.config.js
overlayed with post headmatter.
function basicUrlify(meta) {
return meta.category + '/' + slugify(meta.title);
}
// multiple urls per post
function multipleUrlify(post) {
return [
meta.category + '/' + slugify(meta.title),
dateify(meta.date) + '/' + slugify(meta.title)
];
}
// redirect
function redirectUrlify(meta) {
var to = dateify(meta.date) + '/' + slugify(meta.title);
return [
{
from: meta.category + '/' + slugify(meta.title),
to: to,
},
to,
];
}
Each post is just a Markdown file suplemented with a YAML headmatter. Example:
---
title: "Demo post"
date: 2013-12-15
---
Content goes here
It should be possible to extend base themes. Ie. in my case I would have to define a custom footer that uses the widgets (just React components). In addition I would need to define a custom file for tag index.
Each theme should be able to declare its Webpack dependencies and configuration. This allows you to use custom technology (ie. SCSS, whatever) for defining those.
Plugins take some input and provide some output. As based on above it would make sense if they could hook into metadata, routing and images. The last case would parse image urls from post content and then generate thumbnails based on set convention on build. Possibly some Webpack loader can be used here.
A site looks roughly like this:
-
antwar.config.js
- Site configuration as described above -
package.json
- Site dependencies (ie. React components, plugins, theme, ...) -
/drafts
- Possible post drafts. These are visible only in a dev build -
/posts
- Posts in Markdown format. The structure could be arbitrary if we match against**/*.md
. This would allow people to structure their posts however they want. The path tot he post could be passed to some metadata transformation function that could do something useful with it (ie. extract category, date etc.). -
/build
- Output of the project. Just a static site that can be hosted somewhere. -
/assets
- Site assets (images etc.)