package module
Version: v0.6.0 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2021 License: GPL-2.0 Imports: 12 Imported by: 0


GoDoc Go Report Card license Release


ephemeris is a golang CLI-application which will generate a blog from a collection of static text-files, complete with:

  • An archive-view.
    • Showing posts by year, and month.
  • Comment support.
    • See COMMENTS.md for more details on the setup required.
  • A tag-cloud.
    • Containing all tags, and a list of posts using a specified tag.
  • An RSS feed.
    • Containing the most recent ten posts.
    • Full text is included in the feed.

The project was primarily written to generate my own blog, which was previously generated with the perl-based chronicle blog compiler - if you've used chronicle you may consult the brief notes on migration.


You can install from source, by cloning the repository and running:

$ cd ephemeris/cmd/ephemeris
$ go build .
$ go install .

Or if you just wish to install the binary:

$ go install github.com/skx/ephemeris/cmd/ephemeris@latest

Alternatively you may find precompiled binaries available for many systems upon the release page.

Blog Generation

A blog is generated from two things:

  • A series of blog-posts, stored beneath a given directory.
  • An optional set of comments, which are plaintext files associated with a given blog-post.

To build/generate/create your blog you need to create a configuration file that contains the appropriate directories. The configuration file is assumed to be named ephemeris.json in the current-directory, and a sample configuration file would look like this:

      "CommentsPath":  "./comments/",
      "OutputPath":    "./output/",
      "PostsPath":     "./posts/",
      "Prefix":        "http://blog.steve.fi/"

Once you have a configuration file simply run the command to compile and generate your blog:

$ ephemeris

As expected the generated output will be placed beneath the output/ directory. The possible configuration-keys in the JSON file are:

  • PostsPath - Mandatory
    • This is the path to the directory containing your blog-posts.
    • This directory will be searched recursively for content.
  • CommentAPI
    • The URL of the CGI script to receive comments, this is used in the add-comment form.
  • CommentsPath
    • This is the path to the directory containing your comments.
    • If this is empty then no comments will be read/inserted into your output
    • See COMMENTS.md for a discussion of comments.
  • OutputPath
    • The path beneath which all output content should be written.
    • This defaults to output/ if not specified.
  • Prefix - Mandatory
    • This is the URL-prefix used to generate all links.
  • ThemePath
    • This is the path to a local theme you're using, if you don't wish to use the default theme embedded within the binary.
    • See the theming section in this document for more details.

There is a command-line flag which lets you specify an alternative configuration-file, if you do not wish to use the default. Run ephemeris -help to see details.

Blog Format

The input to this program is a directory tree containing a series of blog-posts. Each post will be stored in a single file, with the entry being prefixed by a simple header containing meta-data.

A sample post would look like this:

Tags: compilers, assembly, golang, brainfuck
Date: 14/06/2020 19:00
Subject: Writing a brainfuck compiler.
Format: markdown

So last night I had the idea..

There are a few things to note here:

  • The header and the content are separated by a single blank line.
  • The date MUST be in the specified format.
  • If there is no format: markdown header then the body will be assumed to be HTML.
    • All my early posts were written in HTML.
    • Later I switched to markdown.

As noted the input directory will be processed recursively, which allows you to group posts by topic, year, or in any other way you might prefer. I personally file my entries by year, like so:

  ├── 2005
  | ├── 1.txt
  | └── 2.txt
  ├── 2006
  | ├── 3.txt
  | └── 4.txt
  ├── 2018
  | ├── 5.txt
  | └── 6.txt
  ├── 2019
  | ├── 7.txt
  | └── 8.txt
  └── 2020
    ├── 9.txt
    ├── 10.txt
    └── 11.txt

Demo Blog

There is a demo-blog contained within this repository, along with a lightly-modified theme. To compile the blog into a set of HTML output-pages simple change into the appropriate directory and run the command:

$ cd _demo
$ ephemeris

This will generate ./output/. As you can see from the configuration file the blog will have an URL-prefix of http://localhost:8000 so you can try serving it with a local webserver on that port to view it in your browser:

cd output/
python -m SimpleHTTPServer 8000

Once the simple HTTP-server is running open http://localhost:8000/ with your browser to see the compiled/generated result.


The main binary contains an embedded set of text/template resources which are used to generate the output blog. If you wished to update those static-resources you'd need to edit the application-source and rebuild it which is a bit cumbersome, and future releases would almost certainly overwrite your changes.

Instead of having to rebuild the application to change the generated output you can use a local directory of templates instead of the embedded resources.

To get started you should export the default templates to a local directory:

ephemeris -export-theme=./blog-theme/

This will give you the following contents:

├── archive_page.tmpl
├── archive.tmpl
├── entry.tmpl
├── inc
│   ├── add_comment_form.tmpl
│   ├── blog_post.tmpl
│   ├── comments_on_blog_post.tmpl
│   ├── css.tmpl
│   ├── recent_posts.tmpl
│   └── rss.tmpl
├── index.rss
├── index.tmpl
├── tag_page.tmpl
└── tags.tmpl

1 directory, 13 files

Now that you have the local templates available you can edit them, changing the text and layout as you wish, and specify that local directory as the ThemePath in your ephemeris.json configuration file.


This project is not documented to my usual and preferred standard, no doubt it will improve over time.

However there are many blog packages out there, so I expect this project will only be of interest to those wishing to switch from chronicle.




Package ephemeris holds some minimal code to create a blog.

A blog is largely made up of blog-posts, which are parsed from a series of text-files.

Each post will have a small header to include tags, date, title, and will be transformed into a simple site.



This section is empty.


This section is empty.


This section is empty.


type BlogComment

type BlogComment struct {

	// Author holds the name of the comment-submitter.
	Author string

	// Body holds the body of the comment.
	Body string

	// Icon is generated from the email-address of the submitter.
	// This will be a gravitar link.
	Icon string

	// Link holds any user-submitted URL.
	Link string

	// Date is when the comment was created - this is extracted
	// from the filename of the comment file.
	// The filenames of our comments are "${title}.html.${epoch-seconds}"
	Date time.Time

BlogComment is the structure to describe a comment associated with a blog post.

func NewBlogComment

func NewBlogComment(path string) (BlogComment, error)

NewBlogComment reads a comment from the named file, and returns that in a structured form.

type BlogEntry

type BlogEntry struct {
	// Title holds the blog-title.
	Title string

	// Path holds the path to the source-file, on-disk.
	Path string

	// Tags contains a list of tags for the given post.
	Tags []string

	// Content contains the post-body.
	Content string

	// The link to the post.
	Link string

	// Date is when the post was created.
	Date time.Time

	// CommentData contains any comments left upon this entry.
	CommentData []BlogComment

BlogEntry holds a single blog-post.

A post has a series of attributes associated with it, as you would expect, such as a title a set of tags, and an associated set of comments.

func NewBlogEntry

func NewBlogEntry(path string, site *Ephemeris) (BlogEntry, error)

NewBlogEntry creates a new blog object from the contents of the given file.

If the file is formatted in Markdown it will be expanded to HTML as part of the creation-process.

func (BlogEntry) MonthName added in v0.2.0

func (b BlogEntry) MonthName() string

MonthName returns the value of a post's month, as a string, for example "January", "March", etc.

func (BlogEntry) MonthNumber added in v0.2.0

func (b BlogEntry) MonthNumber() string

MonthNumber returns the value of a post's month, as a two-digit string. For example "01", "11", or "12".

Having a string return value is useful for template interpolation.

func (BlogEntry) Year added in v0.2.0

func (b BlogEntry) Year() string

Year returns the year of a blog-post, as a string.

Having a string return value is useful for template interpolation.

type Ephemeris

type Ephemeris struct {
	// Root is the source of our posts.
	Root string

	// BlogEntries holds the entries we've found
	BlogEntries []BlogEntry

	// CommentFiles holds the filenames of comments we've found.
	CommentFiles []string

	// Prefix is the absolute URL prefix for the blog
	Prefix string

Ephemeris holds our site structure.

There are only a few settings for the blog, which are the obvious ones - a path pointing to the blog-posts, a URL-prefix for use in generation of the output files, and a list of comment files.

func New

func New(directory string, commentPath string, prefix string) (*Ephemeris, error)

New creates a new site object.

func (*Ephemeris) Entries

func (e *Ephemeris) Entries() []BlogEntry

Entries returns the blog-entries contained within a site. Note that the input directory is searched recursively for files matching the pattern "*.txt" - this allows you to create entries in sub-directories if you wish.

The entries are returned in a random-order, and contain a complete copy of all the text in the entries. This means that there is a reasonable amount of memory overhead here.

func (*Ephemeris) Recent added in v0.5.0

func (e *Ephemeris) Recent(count int) []BlogEntry

Recent returns the data about the most recent N entries from the site


Path Synopsis
This is the driver for our blog-compiler, which will generate a static-blog from a series of text-files.
This is the driver for our blog-compiler, which will generate a static-blog from a series of text-files.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL