stele

package module
v1.0.0-beta.2 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2024 License: GPL-3.0 Imports: 20 Imported by: 0

README

stele

TODO: Logo

A no frills blogging platform for people with analysis paralysis.


Go Reference Build Status

Overview

stele is a static-site generator focused on simplicity over configurability. The goal of this project is to create a fast, purpose-built SSG to meet my needs when spinning up a new blog. If you're hoping for a more featureful, I highly recommend you check out the alternatives below as well as the broader world of SSG tooling. There's definitely something out there that does what you want.

As for this project, here's what you do get:

  • A CLI
  • Markdown posts
  • Static pages
  • Automatic web manifest
  • Automatic RSS feed
  • (Pretty) responsive design

and, perhaps most critically:

  • No decisions

If that sounds good enough for your use-case, then do please try it out!

Install from source

To install from source you will need Go >= 1.22 installed:

go install github.com/haleyrc/stele

Usage

Assuming stele is already installed and in your path, using the CLI is pretty straightforward. Running stele dev will start up a local development server. This does a full build of the static assets and makes them available at http://localhost:8081. At the moment, the site will not automatically rebuild on changes, but you can visit http://localhost:8081/refresh to force a rebuild.

Once you are satisfied with your post/page/whatever, you can do a full build by running stele build. This will create a dist/ folder with all of the static assets for the site. These assets should be deployable as-is to something like an S3 bucket or you can have your favorite host (e.g. Cloudflare Pages, Netlify, etc.) build and deploy them for you. How to set that up is outside of the scope of this guide, but shouldn't be too difficult for someone with experience on these platforms.

For either of these commands to work correctly, you will need to make sure that your source directory is laid out in the standard stele format.

File structure

The stele CLI relies on a specific file structure to work correctly:

.
├── config.yml
├── pages
└── posts
config.yml

At the root of your project you will need a YAML file containing the configuration for your blog. The available configuration values are:

  • title - The name of your blog
    title: My First Blog
    
  • description - A short description of your blog's content/purpose
    description: A personal blog about fish
    
  • author - Probably your name
    author: Grace Hopper
    
  • baseURL - The FQDN and protocol for your blog
    baseURL: https://myblog.example.com
    
  • categories - A list of categories that describe the content of the blog
    categories:
      - blog
      - programming
    

    This can also be written in short-form: categories: [blog, programming].

  • menu - A list of links to include in the top-level site navigation
    menu:
      - label: about
        path: /about
    

    The path should correspond to a static page e.g. pages/about.html or the link will be dead when the site is generated.

pages/

"Pages" are static content written in HTML that require no additional parsing. These are primarily useful for things like "About Me" and "Contact" pages that are generally authored once and only infrequently updated.

stele will look for any files in the pages/ subdirectory with an .html extension and render them into the default layout. The resulting file will have the same name as the original but will be in the root of the rendered static assets. For example, the file /pages/about.html will be available at {{ BASE_URL }}/about.html. For this reason, make sure that your file names are URL-safe.

posts/

Posts in stele, as with most SSGs, are written in markdown with some minimal frontmatter.

stele will load and parse any files in the posts/ subdirectory with a .md extension. As with pages, the post name should be URL-safe as it will be converted in to a slug for the post in the final assets.

The post content should follow the format:

---
title: Your Title Here
description: Your description here.
tags: [tag1, tag2]
draft: false
date: YYYY-MM-DD
---

Your content here.

The title and description fields are required. If tags is not present, the post will simply not have any tags assigned. The draft field determines whether the post should be published. If true, the post will be rendered in the local development server but will not be present in the production build. Posts must also have a date with one exception: drafts must not have a date assigned. When running the development server, drafts are automatically assigned today's date so that they remain at the top of the rendered list of posts. Once a post is no longer a draft (by setting draft: false or removing the field entirely), they will need to have a publish date assigned.


That's really all you need to get started. Everything else is handled by the framework!

Alternatives

Documentation

Overview

Package stele contains the top-level types and functions for the stele blog framework.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Build

func Build(ctx context.Context, srcDir, dstDir string, opts ...BuildOpt) error

Build compiles a deployable blog. Source files are read from srcDir and the resulting assets are written to dstDir. The contents of the destination directory, if any, will be deleted when running this function.

func RenderManifest

func RenderManifest(ctx context.Context, w io.Writer, cfg *Config) error

RenderManifest renders a web manifest to w based on the configuration provided.

func RenderRSSFeed

func RenderRSSFeed(ctx context.Context, w io.Writer, cfg *Config, posts Posts) error

RenderRSSFeed renders an RSS feed to w based on the configuration and list of posts provided.

func WithDrafts

func WithDrafts(cfg *buildConfig)

Types

type BuildOpt

type BuildOpt func(*buildConfig)

type Config

type Config struct {
	// The author of the blog.
	Author string `yaml:"author"`

	// The URL where the blog will be hosted. This is used to construct links
	// to resources e.g. in the RSS feed and must be an absolute URL including
	// protocol.
	BaseURL string `yaml:"baseURL"`

	// A list of categories that describe the content of the blog. This is used in
	// the web manifest and RSS feed and should be descriptive without being
	// overloaded.
	Categories []string `yaml:"categories"`

	// A description of the blog's content and/or purpose.
	Description string `yaml:"description"`

	// A list of links to include in the top-level site navigation. This is useful
	// for including links to raw pages e.g. an "about me" page.
	Menu []MenuLink `yaml:"menu"`

	// The title/name of the blog.
	Title string `yaml:"title"`
}

Config represents the supported configuration for the stele framework.

func NewConfig

func NewConfig(path string) (*Config, error)

NewConfig loads the file at path and returns the parsed configuration.

type Frontmatter

type Frontmatter struct {
	// A short description of the post.
	Description string `yaml:"description"`

	// Drafts are visible when running the local server, but are not included in
	// production builds.
	Draft bool `yaml:"draft"`

	// A list of tags to associate with the post.
	Tags []string `yaml:"tags"`

	// The "authored date" for the post.
	Timestamp time.Time `yaml:"date"`

	// The title of the post.
	Title string `yaml:"title"`
}

Frontmatter represents all of the supported frontmatter fields for posts.

type MenuLink struct {
	// The text to show the user.
	Label string `yaml:"label"`

	// The path for the link.
	Path string `yaml:"path"`
}

MenuLink represents a link that will appear in the main page navigation.

type Page

type Page struct {
	// The path to the page on disk.
	Path string

	// A URL-safe identifier for the page.
	Slug string
}

Page represents a page with static HTML content.

func NewPage

func NewPage(path string) (*Page, error)

NewPage creates a Page object representing the page at the given path.

func NewPages

func NewPages(dir string) ([]Page, error)

NewPages returns a slice of Pages by parsing the contents of the provided directory.

func (Page) Content

func (p Page) Content() string

Content returns the content of the page. This is loaded lazily and this method will panic if the file is unavailable or can't be read.

type Post

type Post struct {
	Frontmatter

	// The path to the file on disk.
	Path string

	// A URL-safe identifier for the post.
	Slug string
}

Post represents a single markdown post.

func NewPost

func NewPost(path string) (*Post, error)

NewPost returns a Post object by parsing the file at path.

func (*Post) Content

func (p *Post) Content() string

Content returns the content of the post. This is loaded lazily and this method will panic if the file is unavailable or can't be read.

type PostIndex

type PostIndex []PostIndexEntry

PostIndex is a slice of entries where each entry contains a set of posts that share a common key e.g. post year, tag, etc.

type PostIndexEntry

type PostIndexEntry struct {
	Key   string
	Posts Posts
}

PostIndexEntry represents a collection of posts that shared a common key e.g. post year, tag, etc.

type Posts

type Posts []Post

Posts is an alias for a slice of Post objects.

func NewPosts

func NewPosts(dir string) (Posts, error)

NewPosts returns a slice of Posts by parsing the contents of the provided directory.

func (Posts) ByTag

func (ps Posts) ByTag() PostIndex

ByTag returns an index of posts grouped by common tags. A post with multiple tags will appear in multiple entries in the index.

func (Posts) ByYear

func (ps Posts) ByYear() PostIndex

ByYear returns an index of posts grouped by the year they were authored. A given post will only appear in one entry in the index.

func (Posts) First

func (ps Posts) First() *Post

First returns the earliest post by authored date. This method assumes that the posts are sorted in descending order by timestamp.

func (Posts) Head

func (ps Posts) Head() (*Post, Posts)

Head returns the first posts in the slice and a Posts object containing the remaining posts. If there is only one post, the second return value will be nil. If there are no posts, both return values will be nil.

func (Posts) MostRecent

func (ps Posts) MostRecent(n int) Posts

MostRecent returns the n most recent posts. If n > len(ps), it will return all of the posts.

Directories

Path Synopsis
cmd
internal
markdown
Package markdown contains thin wrappers around third-party markdown implementations.
Package markdown contains thin wrappers around third-party markdown implementations.
Package template contains template definitions for the default stele blog pages.
Package template contains template definitions for the default stele blog pages.
components
Package components contains templates for components used on multiple pages.
Package components contains templates for components used on multiple pages.
components/icons
Package icons contains components that render SVG icons.
Package icons contains components that render SVG icons.
pages
Package pages contains templates for individual pages in a rendered blog.
Package pages contains templates for individual pages in a rendered blog.

Jump to

Keyboard shortcuts

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