| locales | ||
| pages | ||
| scripts | ||
| src | ||
| templates | ||
| themes | ||
| .gitignore | ||
| bssg-editor.html | ||
| bssg.sh | ||
| config.sh | ||
| generate_theme_previews.sh | ||
| LICENSE | ||
| README.md | ||
BSSG - Bash Static Site Generator
BSSG is a simple static site generator written in Bash. It processes Markdown files and builds a minimal, accessible website suitable for personal journals, daily writing, or introspective personal newspapers.
Table of Contents
- Features
- Requirements
- Quick Start
- Recommended Setup: Separating Content from Core
- Directory Structure
- Usage
- Markdown Post Format
- Customization
- Deployment
- Themes
- Theme Previews
- Admin Interface
- BSSG Post Editor
- Performance Features
- Site Configuration
- Future Plans
- Local Development Server
- Troubleshooting
- Author and License
- Documentation
Features
- Generates HTML from Markdown using pandoc, commonmark, or markdown.pl (configurable)
- Supports post metadata (title, date, tags)
- Supports
lastmodtimestamp in frontmatter for tracking content updates (used in sitemap, RSS feed, and optionally displayed on posts). - Full date and time support with timezone awareness
- Post descriptions/summaries for previews, OpenGraph, and RSS
- Admin interface for managing posts and scheduling publications (planned for future release)
- Standalone post editor with modern Ghost-like interface for visual content creation
- Creates tag index pages
- Related Posts: Automatically suggests related posts based on shared tags at the end of each post
- Author index pages with conditional navigation menu
- Archives by year and month for chronological browsing
- Dynamic menu generation based on available pages
- Support for primary and secondary pages with automatic menu organization
- Generates sitemap.xml and RSS feed with timezone support
- Asset pre-compression: Can automatically create gzipped versions of text-based files (
.html,.css,.xml,.js) during the build for servers that support serving pre-compressed content. - Clean design
- No JavaScript required (except for admin interface)
- Works well without images
- Cross-platform (Linux, macOS, BSDs)
- Reading time calculation for posts
- Pagination for blog posts with configurable posts per page
- Multiple themes available (see Themes section)
- Theme preview generator to see all available themes in action
- Supports static files (images, CSS, JS, etc.)
- Configurable clean output directory option
- Draft posts support
- Post scheduling system
- Backup and restore functionality
- Incremental builds with file caching for improved performance
- Smart metadata caching system
- Parallel processing support using GNU parallel (if available)
- File locking for safe concurrent operations
- Automatic handling of different operating systems (Linux/macOS/BSDs)
- Custom URL slugs with SEO-friendly permalinks
- Featured images in posts are displayed in index, tag, and archive pages
- Support for static pages with custom URLs
- Support for custom homepage - useful if you want to build a website, not a blog
- Built-in local development server for easy previewing
Quick Start
-
Clone the repository:
git clone https://brew.bsd.cafe/stefano/BSSG.git cd BSSG -
Create your first post:
./bssg.sh post -
Build the site:
./bssg.sh build(This command now invokes the modular build process located in
scripts/build/) -
View your site in the
outputdirectory or serve it locally:./bssg.sh serverThis will build your site and start a local web server. By default, you can access your site at
http://localhost:8000. Alternatively, to manually serve theoutputdirectory (e.g., if you want to use a different server):cd output python3 -m http.server 8000 # Or any other simple HTTP server -
Open your browser and navigate to the URL provided by the server (e.g., http://localhost:8000).
Recommended Setup: Separating Content from Core
Why separate? This setup keeps your website's content (posts, pages, static files, configuration) in a dedicated directory, separate from the BSSG core scripts. This makes it much easier to update BSSG itself (using git pull in the core directory) without affecting or risking conflicts with your site content. This is the recommended approach for most users.
-
Clone BSSG Core (if you haven't already):
git clone https://brew.bsd.cafe/stefano/BSSG.git cd BSSG # Navigate into the BSSG core directory -
Initialize Your Site Directory: From within the BSSG core directory, run the
initcommand, specifying the path where you want your new site's content to live:./bssg.sh init /path/to/your/new/websiteReplace
/path/to/your/new/websitewith the actual path (e.g.,~/my-blog,./my-website). -
Directory Structure Creation: BSSG will create the necessary content directories (
src,pages,drafts,static) inside/path/to/your/new/website. The build output (output/) will also be placed within this new site directory by default. -
Site Configuration File: A specific
config.sh.localfile will be automatically created inside your new site directory (/path/to/your/new/website/config.sh.local). This file tells BSSG where to find your content (SRC_DIR,PAGES_DIR, etc.) and where to build the output (OUTPUT_DIR). -
Automatic Configuration Loading (Optional but Recommended): The
initscript will ask if you want to modify theconfig.sh.localfile located within the BSSG core directory to automatically point to your new site's configuration.- Choose
yes(y): This is the recommended option. It adds a line to the coreconfig.sh.localthat sources your site's configuration file. This means you can run./bssg.shcommands (likebuild,post,page) directly from the BSSG core directory, and it will automatically use the correct settings for your separated site. (Note: For reliability, thesourcecommand added to the core config will use the resolved absolute path to your site's configuration file, even if you provided a relative or tilde-prefixed path duringinit.) - Choose
no(N): If you choose no, you will need to manually specify your site's configuration file using the--configflag every time you run a BSSG command from the core directory that needs to know about your site:# Example: Running build from the BSSG core directory ./bssg.sh build --config /path/to/your/new/website/config.sh.local # Example: Creating a post from the BSSG core directory ./bssg.sh post --config /path/to/your/new/website/config.sh.local
- Choose
Benefit: With your content separated, you can safely update the BSSG core scripts in their own directory using git pull without worrying about overwriting your posts, pages, or custom configurations.
Requirements
BSSG requires the following tools:
- Bash (Note: On macOS, the default bash is too old and not compatible. You need to install a newer version using Homebrew:
brew install bash) - pandoc, commonmark, or markdown.pl (configurable in config.sh.local)
- Standard Unix utilities (awk, sed, grep, find, date)
Installation of Dependencies
On Debian/Ubuntu:
sudo apt-get update
sudo apt-get install cmark socat
On macOS (using Homebrew):
brew install bash cmark socat
On FreeBSD:
pkg install bash cmark socat
On OpenBSD:
pkg_add bash cmark socat
On NetBSD:
pkgin in bash cmark socat
Using markdown.pl instead of commonmark
If you prefer using markdown.pl instead of commonmark:
- Set
MARKDOWN_PROCESSOR="markdown.pl"in yourconfig.sh.localfile - Make sure markdown.pl is installed:
- You can download it from Daring Fireball
- Place it in your PATH or directly in the BSSG directory
- Make it executable with
chmod +x markdown.pl
BSSG will search for either markdown.pl or Markdown.pl (case-sensitive) in both your system PATH and the current BSSG directory.
Using pandoc instead of commonmark
If you prefer using pandoc instead of commonmark:
- Set
MARKDOWN_PROCESSOR="pandoc"in yourconfig.sh.localfile - Make sure pandoc is installed:
- On Debian/Ubuntu:
apt install pandoc - On Fedora:
dnf install pandoc - On macOS:
brew install pandoc - On FreeBSD:
pkg install hs-pandoc - On OpenBSD:
pkg_add pandoc
- On Debian/Ubuntu:
Commonmark provides a stricter and more standardized Markdown implementation and is portable across different operating systems.
Directory Structure
BSSG/
├── bssg.sh # Main command interface script
├── bssg-editor.html # Standalone post editor (Ghost-like interface)
├── generate_theme_previews.sh # Script to generate previews of all themes
├── scripts/ # Supporting scripts
│ ├── build/ # Modular build scripts
│ │ ├── main.sh # Main build orchestrator
│ │ ├── utils.sh # Utility functions (colors, formatting, etc.)
│ │ ├── cli.sh # Command-line argument parsing
│ │ ├── config_loader.sh # Loads default and user configuration
│ │ ├── deps.sh # Dependency checking
│ │ ├── cache.sh # Cache management functions
│ │ ├── content_discovery.sh # Finds posts, pages, drafts
│ │ ├── markdown_processor.sh # Markdown conversion logic
│ │ ├── process_posts.sh # Processes individual posts
│ │ ├── process_pages.sh # Processes individual pages
│ │ ├── generate_indexes.sh # Creates index, tag, and archive pages
│ │ ├── generate_feeds.sh # Creates RSS feed and sitemap
│ │ ├── generate_secondary_pages.sh # Creates pages.html index
│ │ ├── copy_static.sh # Copies static files and theme assets
│ │ └── theme_utils.sh # Theme-related utilities
│ ├── post.sh # Handles post creation
│ ├── page.sh # Handles page creation
│ ├── edit.sh # Handles post/page editing (updates lastmod)
│ ├── delete.sh # Handles post/page/draft deletion
│ ├── list.sh # Lists posts, pages, drafts, tags
│ ├── backup.sh # Backup functionality
│ ├── restore.sh # Restore functionality
│ ├── theme.sh # Theme management and processing (legacy helper)
│ ├── template.sh # Template processing utilities (legacy helper)
│ └── css.sh # CSS generation utilities (legacy helper)
├── src/ # Source directory for markdown posts (Configurable: $SRC_DIR)
│ └── *.md # Markdown posts
├── pages/ # Source directory for static pages (Configurable: $PAGES_DIR)
│ └── *.md # Markdown pages
├── drafts/ # Source directory for drafts (Configurable: $DRAFTS_DIR)
│ ├── *.md/*.html # Draft posts
│ └── pages/ # Optional subdirectory for page drafts
│ └── *.md/*.html # Draft pages
├── templates/ # HTML templates (used by themes)
│ ├── header.html # Header template
│ └── footer.html # Footer template
├── themes/ # Theme directory for different visual styles
│ ├── default/ # Default theme
│ ├── dark/ # Dark theme
│ └── ... # Other themes
├── static/ # Static files to be copied to output directory
├── admin/ # Admin interface files
├── example/ # Theme preview directory (generated)
├── .bssg_cache/ # Cache directory for improved performance
├── config.sh # Default site configuration
├── config.sh.local # Optional user overrides for configuration
└── output/ # Generated HTML website (created during build)
Usage
Basic Commands
cd BSSG
./bssg.sh [command] [options]
Available Commands
Usage: ./bssg.sh command [options]
Commands:
post [-html] [draft_file] # Interactive: Create/edit post/draft, prompt for title, open editor.
# Rebuilds site afterwards if REBUILD_AFTER_POST=true in config.
# Use -html for HTML format.
post -t <title> [-T <tags>] [-s <slug>] [--html] [-d] {-c <content> | -f <file> | --stdin} [--build]
# Command-line: Create post non-interactively.
# -t: Title (required)
# -T: Tags (comma-sep)
# -s: Slug (optional)
# --html: HTML format (default: MD)
# -d: Save as draft
# -c: Content string
# -f: Content file
# --stdin: Content from stdin
# --build: Force rebuild (overrides REBUILD_AFTER_POST=false)
page [-html] [-s] [draft_file] Create a new page (in $PAGES_DIR or $DRAFTS_DIR/pages)
or continue editing a draft (in $DRAFTS_DIR/pages)
Use -html to edit in HTML instead of Markdown
Use -s to mark page as secondary (for menu)
edit [-n] <file> Edit an existing post/page/draft (updates lastmod)
File path should point to $SRC_DIR, $PAGES_DIR, $DRAFTS_DIR etc.
Use -n to rename based on title (posts/drafts only currently)
delete [-f] <file> Delete a post/page/draft
File path should point to $SRC_DIR, $PAGES_DIR, $DRAFTS_DIR etc.
Use -f to skip confirmation
list {posts|pages|drafts|tags [-n]}
List posts ($SRC_DIR), pages ($PAGES_DIR),
drafts ($DRAFTS_DIR and $DRAFTS_DIR/pages), or tags.
For tags, use -n to sort by count.
backup Create a backup of all posts, pages, drafts, and config
restore [backup_file|ID] Restore from a backup (all content by default)
Options: --no-content, --no-config
backups List all available backups
build [opts] Build the site using the modular build system in scripts/build/
Options: -c|--clean-output, -f|--force-rebuild,
--config FILE, --theme NAME,
--site-url URL, --output DIR
init <target_directory> Initialize a new, empty site structure in the specified directory.
This is useful for separating your site content from the BSSG core scripts.
The script will preserve the path format you provide (relative, absolute, or tilde-prefixed)
in the generated site 'config.sh.local' for portability.
Note: If using '~' for your home directory, quote the path (e.g., '~/mysite' or "~/mysite")
to ensure the tilde is preserved in the generated config.
help Show this help message
Creating Posts and Pages
To create a new post interactively:
./bssg.sh post
To create a new page interactively:
./bssg.sh page
You'll be prompted for a title, and $EDITOR will open for you to write your content. By default, the site rebuilds automatically after saving an interactive post if REBUILD_AFTER_POST is set to true in your configuration (config.sh or config.sh.local).
To create a post non-interactively via the command line (see command list above for all options):
# Example: Create markdown post from file, force build
./bssg.sh post -t "My CLI Post" -f content.md --build
# Example: Create HTML post from stdin, don't force build (relies on REBUILD_AFTER_POST)
echo "<p>Hello</p>" | ./bssg.sh post -t "HTML Test" --html --stdin
To create a secondary page (appears under the "Pages" menu):
./bssg.sh page -s
Secondary pages will be listed under a "Pages" menu item in the navigation, which appears automatically when secondary pages exist.
Creating HTML Content
To create content in HTML format instead of Markdown:
./bssg.sh post -html # For posts
./bssg.sh page -html # For pages
Example of HTML content:
---
title: HTML Example
date: 2023-01-15
tags: html, example
---
<h2>This is an HTML post</h2>
<p>You can use full HTML markup in this post.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
Working with Drafts
To save content as a draft (will not be published):
./bssg.sh post -d # For posts
./bssg.sh page -d # For pages
To continue editing a draft:
./bssg.sh post drafts/your-draft-file.md # For posts
./bssg.sh page drafts/pages/your-draft-file.md # For pages
To list all draft posts:
./bssg.sh drafts
Editing and Deleting Posts
To edit an existing post:
./bssg.sh edit src/your-post-file.md
To rename the file when the title changes:
./bssg.sh edit -n src/your-post-file.md
To delete a post:
./bssg.sh delete src/your-post-file.md
Listing Posts and Tags
To list all posts:
./bssg.sh list
To list all tags:
./bssg.sh tags
To list tags sorted by number of posts:
./bssg.sh tags -n
Backup and Restore
To create a backup of all posts:
./bssg.sh backup
To list available backups:
./bssg.sh backups
To restore from a backup (will prompt for confirmation):
./bssg.sh restore [backup_file|ID]
You can use these options with restore to selectively restore content:
./bssg.sh restore backup_id --no-content # Don't restore content (src, drafts, pages)
./bssg.sh restore backup_id --no-config # Don't restore configuration (config.sh, config.sh.local)
Build Options
Usage: ./bssg.sh build [options]
Options:
-c, --clean-output Empty the output directory before building
-f, --force-rebuild Ignore cache and rebuild all files
--config FILE Use a specific configuration file (e.g., my_config.sh)
instead of the default config.sh
--src DIR Override the SRC_DIR specified in the config file
--pages DIR Override the PAGES_DIR specified in the config file
--drafts DIR Override the DRAFTS_DIR specified in the config file
--output DIR Build the site to a specific output directory
--templates DIR Override the TEMPLATES_DIR specified in the config file
--themes-dir DIR Override the THEMES_DIR specified in the config file
--theme NAME Override the theme specified in the config file for this build
--static DIR Override the STATIC_DIR specified in the config file
--site-url URL Override the SITE_URL specified in the config file for this build
--deploy Force deployment after successful build (overrides config)
--no-deploy Prevent deployment after build (overrides config)
Internationalization (i18n)
BSSG supports generating the site in different languages.
-
Configuration:
- Set the desired language code in your
config.sh.localfile:SITE_LANG="es" # Use 'es' for Spanish, 'fr' for French, etc. - If
SITE_LANGis not set or the specified locale file doesn't exist, BSSG will default to English (en).
- Set the desired language code in your
-
Locale Files:
- Translations are stored in the
locales/directory. - Each language has its own file (e.g.,
locales/en.sh,locales/es.sh). - These files contain exported shell variables for all translatable strings used in the templates and the build script (e.g.,
export MSG_HOME="Home").
- Translations are stored in the
-
Adding a New Language:
- Copy
locales/en.shto a new file named after the language code (e.g.,locales/fr.shfor French). - Translate the string values within the new file.
- Set
SITE_LANGinconfig.sh.localto the new language code (e.g.,SITE_LANG="fr"). - Run
./bssg.sh buildto generate the site in the new language.
- Copy
Post and Page Management
- Edit Posts:
./bssg.sh edit <post_filename.md> - Delete Posts:
./bssg.sh delete <post_filename.md> - List Posts:
./bssg.sh list - List Tags:
./bssg.sh tags
Markdown Post Format
Posts should include YAML frontmatter at the beginning:
---
title: Post Title
date: YYYY-MM-DD HH:MM:SS +TIMEZONE
lastmod: YYYY-MM-DD HH:MM:SS +TIMEZONE # Optional: Last modification date
tags: tag1, tag2, tag3
slug: custom-slug
image: /path/to/image.jpg
image_caption: Optional caption for the image
description: A brief summary of your post that will appear in listings, social media shares, and RSS feeds.
author_name: John Doe # Optional: Override default site author
author_email: john@example.com # Optional: Override default site author email
---
Content goes here...
- The
dateformat supports full timestamps with timezone information. If you don't specify a time, the system will use the current time. If you don't specify a timezone, the system will use your local timezone. - The optional
lastmodfield allows you to specify the date and time the content was last modified. It uses the same format asdate. If omitted, it defaults to thedatevalue. This field is used:- For the
<lastmod>tag insitemap.xml. - For the
<atom:updated>tag inrss.xml. - To optionally display an "Updated on" date on the post page if it differs from the publish
date.
- For the
Post Description
The description field in the frontmatter lets you provide a brief summary of your post. This description will be used in:
- Post previews on the index, tag, and archive pages
- OpenGraph meta tags for better social media sharing
- RSS feed entries
If you don't specify a description, the system will automatically extract one from the beginning of your post content.
Featured Images
The image field in the frontmatter allows you to specify an image path that will be displayed with your post. This can be:
- A relative path (e.g.,
/images/photo.jpg) that refers to a file in your static directory - An absolute URL (e.g.,
https://example.com/images/photo.jpg)
The optional image_caption field lets you add a descriptive caption to the featured image.
When you specify an image, it will appear:
- At the top of individual post pages
- As a thumbnail in index pages, tag pages, and archive pages
- In the RSS feed
- In OpenGraph and Twitter metadata for better social media sharing
Multi-Author Support
BSSG supports multiple authors through optional frontmatter fields that can override the default site author configuration on a per-post basis.
Author Fields
author_name: The name of the post author (optional)author_email: The email address of the post author (optional)
Fallback Behavior
BSSG uses intelligent fallback logic for author information:
- Custom Author: If both
author_nameandauthor_emailare specified, they will be used for that post - Name Only: If only
author_nameis specified, the name will be used but no email will be included in metadata - Default Fallback: If author fields are empty or missing, the default
AUTHOR_NAMEandAUTHOR_EMAILfrom your site configuration will be used
Author Index Pages
When multiple authors are detected in your posts, BSSG automatically generates:
- Main Authors Index: A page at
/authors/listing all authors with their post counts - Individual Author Pages: Pages at
/authors/author-slug/showing all posts by a specific author - Conditional Navigation: An "Authors" menu item that only appears when you have multiple authors (configurable threshold)
The author pages reuse the same styling as tag pages for visual consistency and include:
- Post listings sorted by date (newest first)
- Post counts and metadata
- Schema.org structured data for SEO
- Responsive design that works on all devices
Configuration Options
You can control author page behavior in your config.sh.local:
# Enable/disable author pages (default: false)
ENABLE_AUTHOR_PAGES=false
# Minimum number of authors to show the Authors menu (default: 2)
SHOW_AUTHORS_MENU_THRESHOLD=2
# Enable author-specific RSS feeds (default: false)
ENABLE_AUTHOR_RSS=false
Where Author Information Appears
Author information is displayed and used in:
- Post Pages: Copyright notices in the footer
- Index Pages: "by Author Name" in post listings
- Author Pages: Dedicated pages listing posts by each author
- Navigation Menu: "Authors" link (when multiple authors exist)
- RSS Feeds: Dublin Core
dc:creatorelements with proper author attribution - Schema.org Metadata: JSON-LD structured data for search engines
- Archive Pages: Author information in post listings
Examples
Post with custom author:
---
title: Guest Post Example
author_name: Jane Smith
author_email: jane@example.com
---
Post with name only (no email):
---
title: Anonymous Contributor Post
author_name: Anonymous Contributor
author_email: # Leave empty - no email will be included
---
Post using default site author:
---
title: Regular Post
# No author fields - will use AUTHOR_NAME and AUTHOR_EMAIL from config
---
This feature is particularly useful for:
- Guest posts from different authors
- Multi-author blogs or publications
- Posts where you want to credit a specific contributor
- Maintaining author attribution when migrating content from other platforms
- Creating author-focused content organization alongside tags and archives
Customization
To customize the appearance of your site, you can edit:
-
Custom Homepage Content: If you want a custom landing page instead of the default "Latest Posts" list (useful for non-blog websites), simply create a file named
index.mdinside yourpages/directory (${PAGES_DIR}). BSSG will automatically use the content of this file for the homepage (index.html) and will not display the post list. Ensure theindex.mdfile has the frontmatterslug: indexset. -
templates/header.html- Site header and navigation -
templates/footer.html- Site footer -
CSS styles are generated in
output/css/style.css -
config.sh.local- Configuration file for site-wide settings -
CUSTOM_CSS: (Optional) Specify a path (relative to the output directory root) to a custom CSS file. If set, a<link>tag will be added to the<head>of every generated page, after the theme's defaultstyle.css. The CSS file itself should be placed in your$STATIC_DIR(default:static/) to be copied to the output directory. Example:CUSTOM_CSS="/css/my-styles.css"(assumingstatic/css/my-styles.cssexists).
Configuration
The config.sh file contains the default configuration settings for the site generator:
# Directory configuration
SRC_DIR="src"
PAGES_DIR="pages" # Directory for static pages
OUTPUT_DIR="output"
TEMPLATES_DIR="templates"
THEMES_DIR="themes"
STATIC_DIR="static"
DRAFTS_DIR="drafts" # Directory for drafts
THEME="default"
CACHE_DIR=".bssg_cache" # Default cache directory location (relative to BSSG root)
# Build configuration
CLEAN_OUTPUT=false # If true, BSSG will always perform a full rebuild
REBUILD_AFTER_POST=true # Build site automatically after creating a new post (scripts/post.sh)
REBUILD_AFTER_EDIT=true # Build site automatically after editing a post (scripts/edit.sh)
PRECOMPRESS_ASSETS="false" # Options: "true", "false". If true, compress text assets (HTML, CSS, XML, JS) with gzip during build.
# Customization
CUSTOM_CSS="" # Optional: Path to custom CSS file relative to output root (e.g., "/css/custom.css"). File should be placed in STATIC_DIR.
# Site information
SITE_TITLE="My new BSSG site"
SITE_DESCRIPTION="A complete SSG - written in bash"
SITE_URL="http://localhost:8000"
AUTHOR_NAME="Anonymous"
AUTHOR_EMAIL="anonymous@example.com"
# Content configuration
DATE_FORMAT="%Y-%m-%d %H:%M:%S %z"
TIMEZONE="local" # Options: "local", "GMT", or a specific timezone like "America/New_York"
SHOW_TIMEZONE="false" # Options: "true", "false". Whether to display the timezone in rendered dates.
POSTS_PER_PAGE=10
RSS_ITEM_LIMIT=15 # Number of items to include in the RSS feed.
RSS_INCLUDE_FULL_CONTENT="false" # Options: "true", "false". Include full post content in RSS feed.
RSS_FILENAME="rss.xml" # The filename for the main RSS feed (e.g., feed.xml, rss.xml)
ENABLE_ARCHIVES=true # Enable or disable archive pages
ENABLE_AUTHOR_PAGES=false # Enable or disable author pages (default: false)
ENABLE_AUTHOR_RSS=false # Enable or disable author-specific RSS feeds (default: false)
SHOW_AUTHORS_MENU_THRESHOLD=2 # Minimum authors to show menu (default: 2)
URL_SLUG_FORMAT="Year/Month/Day/slug" # Format for post URLs. Available: Year, Month, Day, slug
ENABLE_TAG_RSS=true # Enable or disable tag-specific RSS feed generation (default: true)
# Archive Page Configuration
ARCHIVES_LIST_ALL_POSTS="false" # Options: "true", "false". If true, list all posts on the main archive page.
# Page configuration
PAGE_URL_FORMAT="slug" # Format for page URLs. Available: slug, filename (without ext)
# Markdown processing configuration
MARKDOWN_PROCESSOR="commonmark" # Options: "pandoc", "commonmark", or "markdown.pl"
# Language Configuration
SITE_LANG="en" # Default language code (e.g., en, es, fr). See locales/ directory.
# Related Posts Configuration
ENABLE_RELATED_POSTS=true # Enable or disable related posts feature
RELATED_POSTS_COUNT=3 # Number of related posts to show (default: 3)
# Server Configuration (for 'bssg.sh server' command)
# These are the defaults used by 'bssg.sh server' if not overridden by command-line options.
BSSG_SERVER_PORT_DEFAULT="8000" # Default port for the local development server
BSSG_SERVER_HOST_DEFAULT="localhost" # Default host for the local development server
# Deployment configuration
DEPLOY_AFTER_BUILD="false" # Options: "true", "false". Automatically deploy after a successful build.
DEPLOY_SCRIPT="" # Path to the deployment script to execute if DEPLOY_AFTER_BUILD is true.
# Terminal colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
Date Format Examples
DATE_FORMAT="%Y-%m-%d %H:%M:%S"- 2023-05-15 14:30:45 (default)DATE_FORMAT="%d-%m-%Y %H:%M:%S"- 15-05-2023 14:30:45 (European format)DATE_FORMAT="%b %d, %Y at %I:%M %p"- May 15, 2023 at 02:30 PM (American format)DATE_FORMAT="%d/%m/%Y"- 15/05/2023 (date only)
Local Configuration
IMPORTANT: Do not modify config.sh directly. This file is part of the git repository and your changes could be lost during updates.
For local modifications, use the config.sh.local file instead. This file will override any settings in the main configuration and is ignored by git. You can override any variable from config.sh, including SRC_DIR, PAGES_DIR, and DRAFTS_DIR.
Example config.sh.local:
# Override site information for local development
SITE_TITLE="Development Site"
SITE_URL="http://localhost:8080"
AUTHOR_NAME="Your Name"
Static Files
Any files placed in the static/ directory will be automatically copied to the output directory during the build process. This is useful for including:
- Images
- Additional CSS files
- JavaScript files
- Downloadable files
- Favicons
- Any other static assets
Example usage:
- Place an image in
static/images/photo.jpg - Reference it in your post as:
 - Or set it as a featured image in your post frontmatter:
--- title: Post with Image image: /images/photo.jpg ---
Deployment
BSSG allows you to automatically execute a custom deployment script after a successful build process. This is useful for uploading your site to a server, updating a Git repository, or performing any other post-build actions.
Configuration:
Two configuration variables in config.sh.local control this feature:
DEPLOY_AFTER_BUILD: Set this to"true"to enable automatic deployment after a successful build. Defaults to"false".DEPLOY_SCRIPT: Specify the path to your deployment script. This can be an absolute path or a path relative to the project root (wherebssg.shresides).
Example config.sh.local:
# Automatically deploy after build
DEPLOY_AFTER_BUILD="true"
# Path to the deployment script (relative to project root)
DEPLOY_SCRIPT="scripts/deploy.sh"
Command-Line Overrides:
You can override the DEPLOY_AFTER_BUILD setting for a specific build using command-line flags:
./bssg.sh build --deploy: Forces the deployment script to run, regardless of theDEPLOY_AFTER_BUILDsetting../bssg.sh build --no-deploy: Prevents the deployment script from running, regardless of theDEPLOY_AFTER_BUILDsetting.
Deployment Script:
- Your deployment script (e.g.,
scripts/deploy.sh) must be executable (chmod +x scripts/deploy.sh). - BSSG will execute the script from the project root directory.
- The script receives two arguments:
- The path to the generated output directory (
$OUTPUT_DIR). - The site URL (
$SITE_URL).
- The path to the generated output directory (
- The script should exit with a status code of
0on success. A non-zero exit code will be reported as an error in the build output, but will not necessarily stop the build process itself (unless you modifyscripts/build/main.shto do so).
Example scripts/deploy.sh using rsync:
#!/usr/bin/env bash
OUTPUT_DIR="$1"
SITE_URL="$2"
REMOTE_USER="your_user"
REMOTE_HOST="your_server.com"
REMOTE_PATH="/path/to/your/webroot/"
echo "Deploying site from '$OUTPUT_DIR' to $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH"
echo "Site URL: $SITE_URL"
# Example rsync command (ensure ssh keys are set up for passwordless login)
rsync -avz --delete "$OUTPUT_DIR/" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH"
if [ $? -eq 0 ]; then
echo "Deployment successful."
exit 0
else
echo "Deployment failed!"
exit 1
fi
Themes
BSSG includes a variety of themes to customize the look of your site. Themes are organized in the themes/ directory. You can see a list and preview of the available themes here
Some of the Available Themes
Modern Themes
default- A clean and accessible blog thememinimal- A clean and minimal themedark- Dark mode themeflat- Microsoft Metro/Modern UI inspired flat designglassmorphism- Modern frosted glass effect with blue/teal gradientmaterial- Material Design inspired themeart-deco- Inspired by 1920s-30s Art Deco style with geometric patterns, elegant fonts, and gold/black/silver/jewel color palettesbauhaus- Inspired by the Bauhaus school, focusing on functionality, primary geometric shapes, primary colors plus black and white, and clean sans-serif typographymid-century- Mid-century modern aesthetic (1950s-60s), with clean lines, organic shapes, specific color palettes and characteristic fontsswiss-design- International Typographic Style, focused on grids, sans-serif typography (like Helvetica), strong visual hierarchy, and minimalismnordic-clean- Inspired by Scandinavian design, very minimal, airy, with plenty of white space, light and natural colors, and clean typographybraun- Inspired by iconic Braun design with a focus on minimalism, functionality, and understated elegancemondrian- Inspired by Piet Mondrian's De Stijl artwork featuring primary colors, black grid lines, geometric shapes, and white backgrounds
Retro Computing Themes
amiga500- Amiga 500 inspired themeapple2- Apple II inspired themeatarist- Atari ST inspired themec64- Commodore 64 inspired thememsdos- MS-DOS inspired themeterminal- Terminal/console themezxspectrum- ZX Spectrum inspired themenes- Retro theme inspired by Nintendo Entertainment System, using the NES color palette and pixel art aestheticsgameboy- Retro theme inspired by Game Boy, using a light green background with dark green text for readability while maintaining nostalgic feeltty- Ultra-minimal theme simulating an old teletype output with monospace text on simple background and terminal-like aestheticsmario- Super Mario Bros inspired theme with iconic blue sky background, green pipes for navigation, brick blocks, question blocks, and the classic Mario color palette
Operating System Themes
beos- BeOS inspired thememacclassic- Classic Mac OS inspired thememacos9- Mac OS 9 inspired themenextstep- NeXTSTEP inspired themeosx- macOS inspired themewin311- Windows 3.11 inspired themewin95- Windows 95 inspired themewin7- Windows 7 inspired themewinxp- Windows XP inspired theme
Web Era Themes
web1- Web 1.0 theme with HTML 3.2 aestheticsweb2- Web 2.0 theme with glossy buttons and gradientsvaporwave- Retro futurism with 80s aesthetics and neon colorsy2k- Turn of the millennium aesthetic with bold colors and bubble effectsbbs- Bulletin Board System theme with ANSI colors and ASCII art aesthetics
Content-Focused Themes
docs- A clean, structured theme ideal for technical documentation with excellent code formatting and clear navigationlongform- Optimized for reading long articles with highly readable typography, contained text width, and minimal distractionsreader-mode- Simulates browser reader mode with almost total emphasis on text, sepia background, very readable serif font, and minimal graphic elementsthoughtful- A warm, accessible, and performant theme for personal reflection blogs and thoughtful writingtext-only- A step beyond minimalism using browser defaults with clean base typography for readability and lightning-fast loading
Special Themes
brutalist- Raw, minimalist concrete-inspired designnewspaper- Classic newspaper layoutdiary- Personal diary/journal stylerandom- Selects a random theme (from the available themes) for each build
To use a theme, specify it in your config file:
THEME="msdos"
For a surprise each time, use the random option:
THEME="random"
Theme Previews
BSSG includes a script to generate previews of all available themes. This is useful for seeing how each theme looks with your content before deciding which one to use.
To generate theme previews:
./generate_theme_previews.sh
This will create a directory called example/ containing subdirectories for each theme, along with an index.html file that allows you to navigate between them.
You can also specify a custom SITE_URL for the previews:
./generate_theme_previews.sh --site-url "https://example.com/blog"
The script will use the SITE_URL from the following sources in order of precedence:
- Command line argument (--site-url)
- Local config file (config.sh.local)
- Main config file (config.sh)
- Default value (http://localhost)
Each theme preview will be accessible at SITE_URL/theme (e.g., https://example.com/blog/dark).
Admin Interface
Note: The admin interface is currently in development and has not been released yet. This section describes planned features for a future release.
BSSG will include an admin interface for managing your blog. When released, the admin interface will provide a user-friendly way to:
- Create and edit posts with a WYSIWYG Markdown editor
- Create and manage drafts
- Schedule posts for future publication
- Organize posts with tags
- View statistics about your blog
The admin interface will feature:
- Node.js-based server
- Modern web interface
- Post scheduling capabilities
- Draft management
- Blog statistics and analytics
Post Scheduling (Planned Feature)
The planned admin interface will allow you to schedule posts for future publication. When available, you will be able to:
- Choose "Schedule for later" option
- Select the date and time for publication
- The post will be stored as a draft until the scheduled time
- At the scheduled time, the post will be automatically published
BSSG Post Editor
BSSG includes a standalone post editor (bssg-editor.html) that provides a modern, Ghost-like writing experience entirely in your browser. This editor is perfect for users who prefer a visual interface over command-line tools.
Features
- Modern Interface: Clean, distraction-free design inspired by Ghost CMS
- Split-Pane Editor: Side-by-side markdown editor and live preview (toggleable)
- Complete BSSG Integration: Full support for all BSSG frontmatter fields
- Smart Auto-Save: Automatically saves your work every 10 words or after 5 seconds of inactivity
- Article Management: Save, load, search, and organize multiple articles locally
- Unsplash Integration: Built-in image browser with search and automatic attribution
- Rich Toolbar: Quick formatting buttons for headers, lists, links, images, code, and more
- Keyboard Shortcuts: Full keyboard support (Ctrl+B for bold, Ctrl+I for italic, Ctrl+S to save, etc.)
- Theme Support: Dark/light mode toggle
- Focus Mode: Distraction-free writing environment
- Export Options: Export to .md files, copy to clipboard, or import existing files
- Responsive Design: Works on desktop, tablet, and mobile devices
- Offline Capable: No server required - runs entirely in your browser
Getting Started
- Open the Editor: Simply open
bssg-editor.htmlin your web browser - Configure Settings (Optional): Add your Unsplash API key in the settings panel for real image search
- Start Writing: Fill in the post metadata in the sidebar and start writing in the editor
- Save Your Work: Use Ctrl+S to save articles locally, or use the auto-save feature
- Export: When ready, export your post as a .md file with proper BSSG formatting
Usage Tips
- Frontmatter: All BSSG frontmatter fields are supported - title, date, tags, slug, description, image, etc.
- File Naming: Exported files follow BSSG naming convention:
YYYY-MM-DD-slug.md - Image Integration: Use the Unsplash button (🖼️) to search and insert images with proper attribution
- Article Management: Save multiple articles locally and switch between them using the Load button
- Keyboard Shortcuts:
Ctrl+N: New articleCtrl+S: Save articleCtrl+O: Load articleCtrl+P: Toggle previewCtrl+B: Bold textCtrl+I: Italic textCtrl+K: Insert linkEsc: Exit focus mode
Unsplash Integration
To use real Unsplash images instead of demo placeholders:
- Get a free API key from Unsplash Developers
- Enter your API key in the Settings section of the editor
- Use the image button (🖼️) to search and select professional photos
- Images are automatically attributed according to Unsplash guidelines
The editor works without an API key using demo images, but real Unsplash integration provides access to millions of high-quality photos.
Integration with BSSG Workflow
The BSSG Post Editor generates markdown files that are fully compatible with your BSSG workflow:
- Write your post in the editor
- Export the .md file to your BSSG
src/directory - Build your site with
./bssg.sh build - Publish as usual
The editor can also import existing BSSG posts for editing, making it easy to update content with a visual interface.
Embedding the Editor in Your Website
Since the BSSG Post Editor runs entirely in the browser with no server dependencies, you can safely embed it directly in your published website. This allows you to access the editor from anywhere and provides a convenient way to create content on-the-go.
To embed the editor:
-
Copy the editor file to your static directory:
cp bssg-editor.html static/editor.html -
Build your site as usual:
./bssg.sh build -
Access the editor through your website:
https://yoursite.com/editor.html
Benefits of embedding:
- Remote Access: Write posts from any device with internet access
- No Installation: No need to have BSSG installed locally to create content
- Secure: Since it's client-side only, there are no security implications
- Convenient: Always available alongside your published content
- Mobile Friendly: The responsive design works well on tablets and phones
Workflow with embedded editor:
- Access the editor at
yoursite.com/editor.html - Write your post using the visual interface
- Export the markdown file when finished
- Upload the file to your
src/directory (via FTP, Git, or your preferred method) - Rebuild your site to publish the new content
Security Note: The editor stores data only in your browser's local storage and never transmits content to external servers (except for optional Unsplash image search). All article management and auto-save functionality works entirely offline, making it safe to embed in public websites.
Performance Features
BSSG is designed to be efficient even with large sites, using several performance-enhancing techniques:
Incremental Builds
BSSG intelligently rebuilds only what has changed. When you run the build command, it:
- Checks if source files have been modified since the last build
- Checks if templates have been modified
- Checks if configuration has changed
- Only rebuilds files affected by changes
Metadata Caching
The system maintains a cache of extracted metadata from markdown files to reduce repeated parsing:
- Extracted frontmatter is stored in
.bssg_cache/meta/ - File index information is stored in
.bssg_cache/file_index.txt - Tags index information is stored in
.bssg_cache/tags_index.txt
Parallel Processing
If GNU parallel is installed on your system, BSSG can process multiple files simultaneously:
- Automatically detects GNU parallel and enables it for builds with many files
- Uses 80% of available CPU cores for optimal performance
- Falls back to sequential processing if parallel is not available
To take advantage of parallel processing, install GNU parallel:
# Debian/Ubuntu
sudo apt-get install parallel
# macOS
brew install parallel
# FreeBSD
pkg install parallel
Site Configuration
Key configuration options:
# Site information
SITE_TITLE="My Journal"
SITE_DESCRIPTION="A personal journal and introspective newspaper"
SITE_URL="http://localhost"
AUTHOR_NAME="Anonymous"
AUTHOR_EMAIL="anonymous@example.com"
# Content configuration
DATE_FORMAT="%Y-%m-%d %H:%M:%S %z"
TIMEZONE="local" # Options: "local", "GMT", or a specific timezone
SHOW_TIMEZONE="false" # Options: "true", "false". Determines if the timezone offset (e.g., +0200) is shown in displayed dates.
POSTS_PER_PAGE=10
ENABLE_ARCHIVES=true # Enable or disable archives by year/month
URL_SLUG_FORMAT="Year/Month/Day/slug" # Format for post URLs
RSS_ITEM_LIMIT=15 # Number of items to include in the RSS feed.
RSS_INCLUDE_FULL_CONTENT="false" # Options: "true", "false". If set to "true", the full post content will be included in the RSS feed description instead of the excerpt. Useful for readers that consume entire posts via RSS.
ENABLE_TAG_RSS=true # Options: "true", "false". If set to "true" (default), an additional RSS feed will be generated for each tag at `output/tags/<tag-slug>/rss.xml`.
# Related Posts configuration
ENABLE_RELATED_POSTS=true # Options: "true", "false". If set to "true" (default), related posts based on shared tags will be shown at the end of each post.
RELATED_POSTS_COUNT=3 # Number of related posts to display (default: 3, recommended maximum: 5).
# Multi-author configuration
ENABLE_AUTHOR_PAGES=false # Options: "true", "false". If set to "true", author index pages will be generated.
ENABLE_AUTHOR_RSS=false # Options: "true", "false". If set to "true", RSS feeds will be generated for each author.
SHOW_AUTHORS_MENU_THRESHOLD=2 # Minimum number of authors required to show the "Authors" menu item.
The URL_SLUG_FORMAT setting determines how your post URLs are structured. By default, it uses Year/Month/Day/slug which creates URLs like http://yoursite.com/2023/01/15/my-post-title/.
Other possible formats include:
slug- For simple/post-title/URLsYear/slug- For/2023/post-title/URLsYear/Month/slug- For/2023/01/post-title/URLs
Local Development Server
BSSG includes a simple built-in web server to help you preview your site locally.
./bssg.sh server [options]
This command will:
- Build your site: It automatically runs the build process.
- Adjust
SITE_URL: For the duration of this build, it temporarily setsSITE_URLto match the local server's address (e.g.,http://localhost:8000orhttp://<your-host>:<your-port>). This ensures that all generated links and asset paths work correctly during local preview. The originalSITE_URLin your configuration files remains unchanged for regular builds. - Start the server: It serves files from your configured
OUTPUT_DIR.
Server Options:
--port <PORT>: Specifies the port for the server to listen on.- Default: Value of
BSSG_SERVER_PORT_DEFAULTfrom your configuration (typically8000).
- Default: Value of
--host <HOST>: Specifies the host/IP address for the server.- Default: Value of
BSSG_SERVER_HOST_DEFAULTfrom your configuration (typicallylocalhost).
- Default: Value of
--no-build: Skips the build step and immediately starts the server with the existing content in theOUTPUT_DIR. Useful if you have just built the site and want to quickly restart the server.
Example:
# Build and serve on http://localhost:8080
./bssg.sh server --port 8080
# Serve on a specific host, accessible on your local network (if firewall allows)
./bssg.sh server --host 192.168.0.2 --port 8000
# Serve existing build without rebuilding
./bssg.sh server --no-build
Press Ctrl+C to stop the server.
Future Plans
While BSSG is designed to be simple, there are a few enhancements planned for the future:
- Stale Content Banner: Add an option to display a banner on posts that haven't been updated in a configurable amount of time (e.g., more than X days/months).
Troubleshooting
Common Issues
Missing Dependencies
If you encounter errors about missing commands, make sure you've installed all required dependencies for your platform as mentioned in the Requirements section.
Permissions Issues
If you get "Permission denied" errors when running scripts, make them executable:
chmod +x bssg.sh
chmod -R +x scripts/*.sh
Pandoc Not Found
If you get errors about pandoc not being found, either install pandoc or switch to commonmark or markdown.pl in your config.sh.local:
# Use commonmark (recommended)
MARKDOWN_PROCESSOR="commonmark"
# Or use markdown.pl
MARKDOWN_PROCESSOR="markdown.pl"
Build Errors
If the build process fails, check:
- That your Markdown files have proper frontmatter
- That there are no syntax errors in your templates
- That all required directories exist
For more help, use the issue tracker on the project's GitHub page.
Author and License
BSSG has been developed by Stefano Marinelli (stefano@dragas.it) - https://it-notes.dragas.net
Read the announcement post detailing the journey behind BSSG: Launching BSSG: My Journey from Dynamic CMS to Bash Static Site Generator
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
Documentation
- Getting Started: See the installation and usage instructions above.
- Configuration: Customize your site using the options in
config.sh. - Templates: Learn how to create custom templates in the
templatesdirectory. - Themes: Explore the available themes in the
themesdirectory. - Backup & Restore: Use
./bssg.sh backupand./bssg.sh restoreto manage content backups. - Development Blog: Stay up-to-date with the latest release notes, development progress, and announcements on the official BSSG Dev Blog: https://blog.bssg.dragas.net