A blog generator for github hosted markdown + metadata files
Last updated a year ago by newfivefour .
ISC · Repository · Bugs · Original npm · Tarball · package.json
$ cnpm install paper-fish 
SYNC missed versions from official npm registry.




Create a static blog from markdown (or other markup languages) files (+ metadata) hosted on Github.

It currently runs:


  • Can deal with other markdown languages - not just markdown
  • Tags and tag categories
  • Pagination
  • An atom/RSS feed
  • A sitemap
  • Automatic date creation from git modification times
  • Ability to add metadata to posts to use in your blog
  • Complete control over the HTML output

paper-fish comes with a very basic HTML default. You'll immdiately want to change this by modifying the javascript files.

Example of a blog post hosted on github

The files are markdown with some metadata headers. Each file is like this:

title: The title
tags: misc,hello
someothermetadata: hello
date: Mar 11 2001

Here's some *normal* markdown

Note the date metadata is optional. If it's not there we'll get it from github.

All your metadata will be available in the output posts. And you can aggregate all the metadata too.


Create a Github repository like this:

Go to and create an access token with repo access.

Create a blogconf.json file like this:

  "githubAccessToken": "YOUR_ACCESS_TOKEN",
  "websiteUrlForFeeds": "",
  "feedTitle": "This will appear in atom.xml",
  "outputDir": "output/",
  "paginationValue": 3

(Note: the url and the output dir must end with a /)

  • Run npm -g install paper-fish
  • Make the output directory in your filesystem
  • Run paper-fish

Your blog will now exist in the output/ directory, with the sitemap and atom feed.

Structure of the blog

The blog will have an index.html page and will have five posts on it, if your pagination value is five. index.2.html will have the next five posts on, and so on.

For each tag, a category page will be built. If you have a tag sometag then category_sometag.html will be created with five posts on it, if your pagination value is five. category_sometag.2.html will contain the next five posts.

A single page file will be created for each file. If you have a file, then a somepost.html file will be created.

The posts are ordered by date. This comes from either the date metadata field in the post (pased by javascript's Date function) or from the lastest git commit date for that file.

A atom.xml RSS feed and a sitemap.xml sitemap is also created.

Understanding how to modify the HTML output

Your blog will be created with the default styling. You'll want to change that.

The current file that controls that is in your npm global directory. It relates to

export const singlePost = (post, allPosts) => `

export const taggedPaginatedPosts = (tag, index, indexEnd, pagePosts, allPosts) => `

export const mainPaginatedPosts = (index, indexEnd, pagePosts, allPosts) => `

The first method controls a single post html file, the second method controls the "category_tagname.html" pages, and the third controls the "index.html" pages.

The parameters:

  • index - this starts from 1, and is the pagination value of the page
  • indexEnd - if you have 8 pages, this value will be 8
  • post - this is a post object { path: "" content : { headers: { title: "Title", tags: ["a", "b"], date: "Mar 1 2001" }, text: "markdown text" } }
  • pagePosts - array of posts object for this pagination page, e.g. if you have a pagination value of 3, they'll be three posts
  • tag - if you have a post tagged hello, then the value will be hello.
  • tags - given to the mainPaginatedPosts method as a convienence: a list of all the tag in frequency order, { tag: "name", freq: 7 } for example
  • allPosts - this is a list of all the post objects that exist in your github repo sorted by date - can be used to extra custom metadata from all the posts

Specifying a markup language other than markdown

In the custom HTML output javascript file, we specify the markup language parser to use.

The default style uses markdown, but you're free to use whatever.

In the HTML output javascript file we do something like this:

import * as markdown from 'markdown' 
const parseText = markdown.default.parse




Customising the output

Let's say you've decided to make your output file, personal_output.mjs - below is very basic.

import * as markdown from 'markdown' 
const parseText = markdown.default.parse

export const singlePost = (post, allPosts) => `
  ${ => t).join(" | ")}

export const taggedPaginatedPosts = (tag, index, indexEnd, pagePosts, allPosts) => `
  ${ => `<h3>${p.content.headers.title}</h3> ${parseText(p.content.text)}`).join("<hr>")}
  Page ${index} of ${indexEnd}

export const mainPaginatedPosts = (index, indexEnd, pagePosts, allPosts) => `
  <h1>Your blog</h1>
  ${ => `<h3>${p.content.headers.title}</h3> ${parseText(p.content.text)}`).join("<hr>")}
  Page ${index} of ${indexEnd}

Then you can specify it in your blogconf.json file as outputMJSFile. The path must be absolute:

  "outputMJSFile": "/the/full/path/personal_output.mjs"

Now run paper-fish in the directory and you will have a blog with custom output.


npm test for the unit tests.

npm run ui-test for the UI tests -- but you'll need to supply a blogconf.json etc for them to work and have firefox in /usr/bin/firefox

TODO later

  • Talk about github api and api call interval
  • Make it so you don't need .md for the github files
  • What if output filename is wrong?
  • Specify config file from command line
  • Use output html files on github
  • Use latest packages on live

Current Tags

  • 0.5.23                                ...           latest (a year ago)

21 Versions

  • 0.5.23                                ...           a year ago
  • 0.5.22                                ...           a year ago
  • 0.5.21                                ...           a year ago
  • 0.5.20                                ...           a year ago
  • 0.5.19                                ...           a year ago
  • 0.5.18                                ...           a year ago
  • 0.5.17                                ...           a year ago
  • 0.5.16                                ...           a year ago
  • 0.5.15                                ...           a year ago
  • 0.5.14                                ...           a year ago
  • 0.5.13                                ...           a year ago
  • 0.5.12                                ...           a year ago
  • 0.5.8                                ...           a year ago
  • 0.5.7                                ...           a year ago
  • 0.5.6                                ...           a year ago
  • 0.5.5                                ...           a year ago
  • 0.5.4                                ...           a year ago
  • 0.5.3                                ...           a year ago
  • 0.5.2                                ...           a year ago
  • 0.5.1                                ...           a year ago
  • 0.5.0                                ...           a year ago
Maintainers (1)
Today 0
This Week 0
This Month 0
Last Day 0
Last Week 0
Last Month 1
Dependencies (2)
Dev Dependencies (3)
Dependents (0)

Copyright 2014 - 2016 © |