Static Site Generation
all2md includes a powerful generate-site command that converts document collections into production-ready Hugo, Jekyll, MkDocs, Zola, or Eleventy static sites. The command handles frontmatter generation, asset copying, directory scaffolding, and metadata mapping, enabling you to transform documentation folders or blog posts into fully-functional static sites.
Overview
The generate-site command is purpose-built for creating static sites from document collections. Unlike the HTML template-based approach (which remains available for custom HTML generation), generate-site produces complete Hugo, Jekyll, MkDocs, Zola, or Eleventy site structures with proper frontmatter, asset organization, and configuration files.
Key Features
Hugo, Jekyll, MkDocs, Zola, and Eleventy Support - Target any of the five static site generators with appropriate directory structures and frontmatter formats
Automatic Frontmatter - Intelligently maps document metadata to frontmatter fields (title, date, author, tags, categories)
Asset Management - Collects images from documents, copies them to the correct static directories, and updates references
Scaffolding - Optionally creates complete site structures with config files and layout templates
Batch Processing - Recursively process entire directories with file exclusion patterns
Flexible Output - Control content subdirectories, frontmatter formats, and file naming conventions
When to Use generate-site
Choose generate-site when you want to:
Convert documentation folders to Hugo, Jekyll, MkDocs, Zola, or Eleventy sites
Migrate blog posts to a static site generator
Create a documentation site from markdown files
Build a knowledge base with proper categorization
Maintain content in simple markdown while publishing to a static site
For custom HTML generation with full template control, see the all2md.renderers.html HTML renderer documentation.
Quick Start
Basic Hugo Example
Convert a documentation folder to a Hugo site:
# Create a complete Hugo site with scaffolding
all2md generate-site docs/ \
--output-dir my-hugo-site \
--generator hugo \
--scaffold \
--recursive
# Result:
# my-hugo-site/
# ├── config.toml
# ├── content/
# │ ├── _index.md
# │ ├── getting-started.md
# │ └── api-reference.md
# ├── static/images/
# │ └── (copied images)
# ├── themes/
# ├── layouts/
# └── data/
Basic Jekyll Example
Convert blog posts to a Jekyll site:
# Create a complete Jekyll blog with scaffolding
all2md generate-site posts/ \
--output-dir my-blog \
--generator jekyll \
--scaffold \
--recursive
# Result:
# my-blog/
# ├── _config.yml
# ├── _posts/
# │ ├── 2025-01-22-welcome.md
# │ └── 2025-01-20-first-post.md
# ├── assets/images/
# │ └── (copied images)
# ├── _layouts/
# │ ├── default.html
# │ └── post.html
# └── _includes/
Basic MkDocs Example
Convert a documentation folder to an MkDocs site:
# Create a complete MkDocs site with scaffolding
all2md generate-site docs/ \
--output-dir my-mkdocs-site \
--generator mkdocs \
--scaffold \
--recursive
# Result:
# my-mkdocs-site/
# ├── mkdocs.yml
# └── docs/
# ├── index.md
# ├── getting-started.md
# ├── api-reference.md
# └── images/
# └── (copied images)
Command Syntax
all2md generate-site INPUT... \
--output-dir DIR \
--generator {hugo|jekyll|mkdocs|zola|eleventy} \
[--scaffold] \
[--frontmatter-format {yaml|toml}] \
[--content-subdir PATH] \
[--recursive] \
[--exclude PATTERN]
The generate-site Command
Command Reference
Required Arguments:
INPUT...One or more input files or directories to convert. Can be specific files (
posts/welcome.md posts/intro.md) or directories (docs/).--output-dir DIROutput directory for the generated site. Will be created if it doesn’t exist.
--generator {hugo|jekyll|mkdocs|zola|eleventy}Target static site generator. Determines directory structure, frontmatter defaults, and asset paths.
Optional Arguments:
--scaffoldCreate complete site structure including config files, layouts, and directory placeholders. Without this flag, only the content and static assets are generated.
--frontmatter-format {yaml|toml}Override default frontmatter format. Hugo and Zola default to TOML (
+++delimiters); Jekyll, MkDocs, and Eleventy default to YAML (---delimiters).--content-subdir PATHSubdirectory within the content directory for output files. For example,
--content-subdir postswith Hugo creates files incontent/posts/.--recursiveRecursively process directories, converting all found documents.
--exclude PATTERNExclude files matching the pattern. Can be specified multiple times for multiple patterns. Supports glob patterns.
Usage Examples
Content Only (No Scaffolding):
# Just convert documents, don't create config/layouts
all2md generate-site reports/*.pdf \
--output-dir hugo-reports \
--generator hugo
Custom Content Subdirectory:
# Place output in content/blog/ instead of content/
all2md generate-site posts/ \
--output-dir my-site \
--generator hugo \
--content-subdir blog \
--recursive
With File Exclusions:
# Skip drafts and private files
all2md generate-site content/ \
--output-dir site \
--generator jekyll \
--recursive \
--exclude "draft-*" \
--exclude "private/*" \
--exclude "*.tmp"
Custom Frontmatter Format:
# Use YAML frontmatter with Hugo (instead of default TOML)
all2md generate-site docs/ \
--output-dir hugo-site \
--generator hugo \
--frontmatter-format yaml \
--scaffold
Hugo Static Sites
Hugo Overview
Hugo is a fast, flexible static site generator written in Go. It uses a content-centric approach with markdown files in the content/ directory and places static assets in static/.
Standard Hugo Directory Structure:
hugo-site/
├── config.toml # Site configuration
├── content/ # Markdown content files
│ ├── _index.md # Homepage content
│ └── posts/ # Post subdirectories (optional)
├── static/ # Static assets (images, CSS, JS)
│ └── images/ # Image files
├── themes/ # Theme directory
├── layouts/ # Custom templates
└── data/ # Data files
Generating a Hugo Site
With Scaffolding:
# Create complete Hugo site structure
all2md generate-site documentation/ \
--output-dir my-docs \
--generator hugo \
--scaffold \
--recursive
This creates:
config.tomlwith basic site configurationcontent/_index.mdhomepage placeholderEmpty
themes/,layouts/, anddata/directoriesConverted markdown files in
content/Copied images in
static/images/
Without Scaffolding:
# Only convert content and copy assets
all2md generate-site docs/*.md \
--output-dir my-docs \
--generator hugo
This creates only:
Converted markdown files in
content/Copied images in
static/images/
Hugo Frontmatter
By default, Hugo uses TOML frontmatter with +++ delimiters:
+++
title = "Getting Started with all2md"
date = 2025-01-22T10:00:00
author = "Jane Developer"
description = "A comprehensive guide to document conversion"
tags = ["tutorial", "documentation", "beginner"]
draft = false
weight = 10
+++
Metadata Mapping:
The command automatically maps document metadata to Hugo frontmatter:
Hugo Field |
Source Metadata |
|---|---|
|
Document |
|
|
|
|
|
|
|
|
|
Always set to |
|
|
YAML Frontmatter with Hugo:
You can use YAML frontmatter with Hugo by specifying the format:
all2md generate-site docs/ \
--output-dir hugo-site \
--generator hugo \
--frontmatter-format yaml
Result:
---
title: Getting Started with all2md
date: 2025-01-22 10:00:00
author: Jane Developer
description: A comprehensive guide to document conversion
tags:
- tutorial
- documentation
- beginner
draft: false
weight: 10
---
Hugo Asset Organization
Images and other assets are copied to static/images/ and referenced with the /images/ path prefix:
Before conversion (in source document):

After conversion (in Hugo content):

The actual file is copied to static/images/architecture.png.
Asset Handling:
Local files - Copied to
static/images/with sanitized filenamesData URIs - Left unchanged (
data:image/png;base64,...)Remote URLs - Left unchanged (
https://example.com/image.png)Duplicate names - Automatically made unique with suffixes
Jekyll Static Sites
Jekyll Overview
Jekyll is a Ruby-based static site generator that emphasizes convention over configuration. It uses markdown files in _posts/ for blog posts and places static assets in assets/.
Standard Jekyll Directory Structure:
jekyll-site/
├── _config.yml # Site configuration
├── _posts/ # Blog posts (with date-prefixed names)
│ ├── 2025-01-22-welcome.md
│ └── 2025-01-20-intro.md
├── assets/ # Static assets
│ └── images/ # Image files
├── _layouts/ # Page templates
│ ├── default.html
│ └── post.html
└── _includes/ # Reusable template fragments
Generating a Jekyll Site
With Scaffolding:
# Create complete Jekyll site structure
all2md generate-site posts/ \
--output-dir my-blog \
--generator jekyll \
--scaffold \
--recursive
This creates:
_config.ymlwith basic site configuration_layouts/default.htmland_layouts/post.htmltemplates_includes/directory for template fragmentsConverted markdown files in
_posts/with date prefixesCopied images in
assets/images/
Without Scaffolding:
# Only convert content and copy assets
all2md generate-site posts/*.md \
--output-dir my-blog \
--generator jekyll
This creates only:
Converted markdown files in
_posts/Copied images in
assets/images/
Jekyll Frontmatter
By default, Jekyll uses YAML frontmatter with --- delimiters:
---
title: Getting Started with all2md
date: 2025-01-22 10:00:00
author: Jane Developer
description: A comprehensive guide to document conversion
categories:
- tutorial
- documentation
layout: post
permalink: /getting-started/
---
Metadata Mapping:
The command automatically maps document metadata to Jekyll frontmatter:
Jekyll Field |
Source Metadata |
|---|---|
|
Document |
|
|
|
|
|
|
|
|
|
Always set to |
|
|
TOML Frontmatter with Jekyll:
You can use TOML frontmatter with Jekyll by specifying the format:
all2md generate-site posts/ \
--output-dir jekyll-site \
--generator jekyll \
--frontmatter-format toml
Result:
+++
title = "Getting Started with all2md"
date = 2025-01-22T10:00:00
author = "Jane Developer"
description = "A comprehensive guide to document conversion"
categories = ["tutorial", "documentation"]
layout = "post"
permalink = "/getting-started/"
+++
Jekyll Asset Organization
Images and other assets are copied to assets/images/ and referenced with the /assets/images/ path prefix:
Before conversion (in source document):

After conversion (in Jekyll content):

The actual file is copied to assets/images/login.png.
Asset Handling:
Local files - Copied to
assets/images/with sanitized filenamesData URIs - Left unchanged (
data:image/png;base64,...)Remote URLs - Left unchanged (
https://example.com/image.png)Duplicate names - Automatically made unique with suffixes
Jekyll Date-Prefixed Filenames
Jekyll requires blog posts to use date-prefixed filenames in the format YYYY-MM-DD-title.md. The generate-site command automatically handles this:
If the document has date metadata:
# Source: getting-started.md with metadata: date: 2025-01-22
# Output: _posts/2025-01-22-getting-started.md
If the document has no date metadata:
# Source: tutorial.md (no date metadata)
# Output: _posts/tutorial.md (no date prefix)
MkDocs Static Sites
MkDocs Overview
MkDocs is a fast, Python-based static site generator geared toward project documentation. All content lives under a single docs/ directory, and the site is configured by a mkdocs.yml file at the project root.
Standard MkDocs Directory Structure:
mkdocs-site/
├── mkdocs.yml # Site configuration
└── docs/ # Content directory (site root)
├── index.md # Homepage
├── guide.md # Content pages
└── images/ # Image files
Generating an MkDocs Site
With Scaffolding:
# Create complete MkDocs site structure
all2md generate-site documentation/ \
--output-dir my-docs \
--generator mkdocs \
--scaffold \
--recursive
This creates:
mkdocs.ymlwith basic site configurationdocs/index.mdhomepage placeholderConverted markdown files in
docs/Copied images in
docs/images/
Without Scaffolding:
# Only convert content and copy assets
all2md generate-site docs/*.md \
--output-dir my-docs \
--generator mkdocs
This creates only:
Converted markdown files in
docs/Copied images in
docs/images/
MkDocs Frontmatter
MkDocs reads page metadata from YAML frontmatter with --- delimiters (the same meta convention used by the Material theme):
---
title: Getting Started with all2md
date: 2025-01-22 10:00:00
author: Jane Developer
description: A comprehensive guide to document conversion
tags:
- tutorial
- documentation
---
Only the common metadata fields (title, date, author, description, tags) are emitted; MkDocs does not use Hugo’s draft/weight or Jekyll’s layout/permalink fields.
MkDocs Asset Organization
Because MkDocs serves everything under docs/, images are copied to docs/images/ and referenced with the /images/ path prefix:
Before conversion (in source document):

After conversion (in MkDocs content):

The actual file is copied to docs/images/architecture.png.
MkDocs Theme Note:
The scaffolded mkdocs.yml references the popular Material theme (theme: name: material), which requires pip install mkdocs-material. Switch to the built-in readthedocs or mkdocs theme if you prefer no extra dependency.
Zola Static Sites
Zola Overview
Zola is a fast, single-binary static site generator written in Rust. Like Hugo, it keeps pages in a content/ directory and assets in static/ (served at the site root), and it defaults to TOML +++ frontmatter. Tera templates live in templates/.
Standard Zola Directory Structure:
zola-site/
├── config.toml # Site configuration
├── content/ # Markdown content (with _index.md sections)
├── static/ # Static assets (served at the root)
│ └── images/
└── templates/ # Tera templates
Generating a Zola Site
With Scaffolding:
all2md generate-site documentation/ \
--output-dir my-docs \
--generator zola \
--scaffold \
--recursive
This creates config.toml, a content/_index.md homepage, minimal working Tera templates (base.html, index.html, section.html, page.html), converted pages in content/, and copied images in static/images/.
Zola Frontmatter
Zola validates page frontmatter against a fixed schema and errors on unknown top-level keys. generate-site handles this by nesting tags/categories under [taxonomies] and non-standard fields (such as author) under [extra]:
+++
title = "Getting Started with all2md"
date = 2025-01-22T10:00:00
description = "A comprehensive guide to document conversion"
draft = false
[taxonomies]
tags = ["tutorial", "documentation"]
[extra]
author = "Jane Developer"
+++
Zola Asset Organization
Images are copied to static/images/ and referenced with the /images/ path prefix (Zola serves static/ at the site root), identical to Hugo.
Eleventy Static Sites
Eleventy Overview
Eleventy (11ty) is a flexible JavaScript static site generator. generate-site scaffolds a conventional layout that reads content from a src/ input directory and uses YAML --- frontmatter.
Standard Eleventy Directory Structure:
eleventy-site/
├── .eleventy.js # Site configuration
├── package.json # Declares the @11ty/eleventy dependency
└── src/ # Input directory
├── index.md # Homepage
└── images/ # Passthrough-copied to the output
Generating an Eleventy Site
With Scaffolding:
all2md generate-site documentation/ \
--output-dir my-docs \
--generator eleventy \
--scaffold \
--recursive
This creates .eleventy.js (input src/, output _site/, with src/images passthrough copy), a package.json declaring the Eleventy dependency, a src/index.md homepage, converted pages in src/, and copied images in src/images/.
Eleventy Frontmatter
Eleventy imposes no frontmatter schema, so only the common fields are emitted (title, date, author, description, tags). Note that tags also double as Eleventy collection names.
Eleventy Asset Organization
Images are copied to src/images/ and referenced with the /images/ path prefix. The scaffolded .eleventy.js configures a passthrough copy so src/images/ is emitted to /images/ in the built site.
Eleventy Dependency Note:
Eleventy is an npm package. After scaffolding, run npm install (which installs @11ty/eleventy from the generated package.json) before npx @11ty/eleventy --serve.
Frontmatter Generation
Metadata Mapping
The command intelligently extracts metadata from source documents and maps it to appropriate frontmatter fields. The mapping is smart enough to handle various metadata field names and formats.
Title Extraction:
titlemetadata fieldDocument filename (without extension) as fallback
Date Extraction:
creation_datemetadata field (highest priority)datemetadata fieldmodifiedmetadata fieldNo date if none found
Author Extraction:
authormetadata fieldNot included if missing
Description Extraction:
descriptionmetadata fieldsubjectmetadata field (fallback)Not included if missing
Tags Extraction (Hugo):
tagsmetadata field (can be list or comma-separated string)keywordsmetadata field (comma-separated string)Empty list if missing
Categories Extraction (Jekyll):
categoriesmetadata field (can be list or comma-separated string)categorymetadata field (single category or comma-separated string)Empty list if missing
Example Metadata:
# In source document metadata
title: Advanced Python Techniques
author: Sarah Developer
creation_date: 2025-01-22T14:30:00
keywords: python, programming, advanced, tips
description: Learn advanced Python techniques for cleaner code
Resulting Hugo Frontmatter (TOML):
+++
title = "Advanced Python Techniques"
date = 2025-01-22T14:30:00
author = "Sarah Developer"
description = "Learn advanced Python techniques for cleaner code"
tags = ["python", "programming", "advanced", "tips"]
draft = false
+++
Resulting Jekyll Frontmatter (YAML):
---
title: Advanced Python Techniques
date: 2025-01-22 14:30:00
author: Sarah Developer
description: Learn advanced Python techniques for cleaner code
categories:
- python
- programming
- advanced
- tips
layout: post
---
Format Comparison
YAML and TOML are both popular frontmatter formats with different syntax:
YAML Format (``—`` delimiters):
---
title: My Article
date: 2025-01-22
tags:
- tutorial
- beginner
nested:
key: value
---
Advantages:
More readable for complex nested structures
Native list syntax
Jekyll default
Wide tool support
TOML Format (``+++`` delimiters):
+++
title = "My Article"
date = 2025-01-22T00:00:00
tags = ["tutorial", "beginner"]
[nested]
key = "value"
+++
Advantages:
More explicit with quotation
Hugo default
Strongly typed
Better date/time handling
String Escaping
The frontmatter generator automatically handles string escaping:
YAML:
Quotes strings containing special characters (:, #, {, }, etc.):
title: "Advanced: Python Tips" # Colon requires quotes
description: This is a simple title # No special chars, no quotes
TOML:
Escapes inner quotes with backslashes:
title = "Book: \"Python Patterns\"" # Inner quotes escaped
description = "A comprehensive guide" # Normal strings quoted
Asset Management
Image Collection
The generate-site command automatically finds all images in your documents by walking the Abstract Syntax Tree (AST). This ensures no images are missed regardless of how they’re embedded in the markdown structure.
Images Are Collected From:
Standard markdown image syntax:
Images in tables
Images in lists
Images in nested block structures
Reference-style images
Images Are NOT Collected:
Data URIs (
data:image/png;base64,...) - left unchanged in markdownRemote URLs (
http://orhttps://) - left unchanged in markdown
File Copying
After collection, local image files are:
Sanitized - Filenames are cleaned to be filesystem-safe
Uniquified - Duplicate names get numeric suffixes (
image.png,image-1.png,image-2.png)Copied - Files are physically copied to the static directory
Referenced - Markdown is updated with the new path
Sanitization Example:
Original: My Diagram (2024).png
Sanitized: My-Diagram-2024.png
Uniqueness Example:
diagram.png → /images/diagram.png
diagram.png → /images/diagram-1.png
diagram.png → /images/diagram-2.png
Path Updates:
The markdown is automatically updated to reference the new location:
# Before


# After (Hugo)


# After (Jekyll)


Generator-Specific Paths
Hugo:
Static directory:
static/images/Markdown reference:
/images/filename
Jekyll:
Static directory:
assets/images/Markdown reference:
/assets/images/filename
MkDocs:
Static directory:
docs/images/Markdown reference:
/images/filename
Zola:
Static directory:
static/images/Markdown reference:
/images/filename
Eleventy:
Static directory:
src/images/(passthrough-copied)Markdown reference:
/images/filename
Output File Naming
The command generates output filenames using a intelligent fallback strategy:
Slugification from Titles
If the document has a title metadata field, it is converted to a URL-safe slug:
Title: "Getting Started with Python"
Output: getting-started-with-python.md
Title: "API Reference: Version 2.0"
Output: api-reference-version-2-0.md
Slugification Rules:
Convert to lowercase
Replace spaces and special characters with hyphens
Remove consecutive hyphens
Remove leading/trailing hyphens
Fallback to Source Filenames
If no title metadata exists, the source filename (without extension) is used:
Source: my-document.pdf
Output: my-document.md
Source: 2024-Q4-Report.docx
Output: 2024-q4-report.md
Jekyll Date Prefixes
For Jekyll, if the document has date metadata (creation_date, date, or modified), the date is prepended in YYYY-MM-DD format:
# With date metadata: 2025-01-22
Title: "Welcome Post"
Output: 2025-01-22-welcome-post.md
# Without date metadata
Title: "About Page"
Output: about-page.md
Hugo does not use date prefixes - filenames are based solely on title or source filename.
Index-Based Fallback
If both title and filename are unusable (e.g., invalid characters), an index-based name is used:
Output: document-0.md
Output: document-1.md
Output: document-2.md
Batch Processing
The --recursive flag enables batch processing of entire directory trees:
Recursive Directory Scanning
# Process all markdown and PDF files in docs/ and subdirectories
all2md generate-site docs/ \
--output-dir hugo-site \
--generator hugo \
--recursive
This will:
Scan
docs/and all subdirectoriesDetect all convertible file types
Convert each document
Preserve relative directory structure (optional)
File Exclusion Patterns
Use --exclude to skip files matching specific patterns:
# Skip drafts, private files, and temporary files
all2md generate-site content/ \
--output-dir site \
--generator jekyll \
--recursive \
--exclude "draft-*" \
--exclude "private/*" \
--exclude "*.tmp" \
--exclude "README.md"
Glob Patterns Supported:
*.tmp- All .tmp filesdraft-*- Files starting with “draft-”private/*- Everything in private/ subdirectoryREADME.md- Specific file
Integration with CLI Features
The generate-site command works seamlessly with other all2md CLI features:
# Use with format-specific options
all2md generate-site reports/*.pdf \
--output-dir site \
--generator hugo \
--pdf-pages "1-10" \
--attachment-mode save
# Use with transforms
all2md generate-site docs/ \
--output-dir site \
--generator jekyll \
--recursive \
--transform add-heading-ids \
--transform add-toc
Scaffolding
Hugo Scaffolding
With --scaffold, a complete Hugo site structure is created:
Directory Structure:
output-dir/
├── config.toml # Site configuration
├── content/ # Content directory
│ └── _index.md # Homepage placeholder
├── static/ # Static assets
│ └── images/ # Image directory
├── themes/ # Themes directory (empty)
├── layouts/ # Custom layouts (empty)
└── data/ # Data files (empty)
config.toml Contents:
baseURL = "https://example.com/"
languageCode = "en-us"
title = "My Site"
theme = ""
[params]
description = "Site description"
content/_index.md Contents:
+++
title = "Home"
draft = false
+++
# Welcome
This is the homepage.
Building the Site:
After generating the scaffolded structure:
cd output-dir
hugo server # Start development server
hugo # Build for production
Jekyll Scaffolding
With --scaffold, a complete Jekyll site structure is created:
Directory Structure:
output-dir/
├── _config.yml # Site configuration
├── _posts/ # Posts directory
├── assets/ # Static assets
│ └── images/ # Image directory
├── _layouts/ # Layout templates
│ ├── default.html
│ └── post.html
└── _includes/ # Template fragments (empty)
_config.yml Contents:
title: My Site
description: Site description
baseurl: ""
url: "https://example.com"
markdown: kramdown
permalink: /:year/:month/:day/:title/
plugins:
- jekyll-feed
- jekyll-seo-tag
_layouts/default.html Contents:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ page.title }} | {{ site.title }}</title>
</head>
<body>
<header>
<h1><a href="/">{{ site.title }}</a></h1>
</header>
<main>
{{ content }}
</main>
<footer>
<p>© 2025 {{ site.title }}</p>
</footer>
</body>
</html>
_layouts/post.html Contents:
---
layout: default
---
<article>
<header>
<h1>{{ page.title }}</h1>
<p class="meta">
{% if page.author %}By {{ page.author }} | {% endif %}
{{ page.date | date: "%B %d, %Y" }}
</p>
</header>
<div class="content">
{{ content }}
</div>
</article>
Building the Site:
After generating the scaffolded structure:
cd output-dir
bundle exec jekyll serve # Start development server
bundle exec jekyll build # Build for production
MkDocs Scaffolding
With --scaffold, a complete MkDocs site structure is created:
Directory Structure:
output-dir/
├── mkdocs.yml # Site configuration
└── docs/ # Content directory
├── index.md # Homepage placeholder
└── images/ # Image directory
mkdocs.yml Contents:
site_name: My Site
site_description: Site generated with all2md
theme:
name: material
markdown_extensions:
- admonition
- tables
- fenced_code
- toc:
permalink: true
Building the Site:
After generating the scaffolded structure:
cd output-dir
mkdocs serve # Start development server
mkdocs build # Build for production
Zola Scaffolding
With --scaffold, a complete Zola site structure is created (config.toml, content/_index.md, static/images/, and minimal Tera templates under templates/).
Building the Site:
cd output-dir
zola serve # Start development server
zola build # Build for production
Eleventy Scaffolding
With --scaffold, a complete Eleventy site structure is created (.eleventy.js, package.json, src/index.md, and src/images/).
Building the Site:
cd output-dir
npm install # Install @11ty/eleventy
npx @11ty/eleventy --serve # Start development server
npx @11ty/eleventy # Build for production
Complete Examples
Convert Documentation Folder to Hugo Site
Scenario: You have a docs/ folder with markdown files and PDF reports that you want to convert to a Hugo documentation site.
Directory Structure (Before):
docs/
├── index.md
├── getting-started.md
├── api/
│ ├── authentication.md
│ └── endpoints.md
├── tutorials/
│ ├── tutorial-1.pdf
│ └── tutorial-2.docx
└── images/
└── logo.png
Command:
all2md generate-site docs/ \
--output-dir my-hugo-docs \
--generator hugo \
--scaffold \
--recursive \
--exclude "images/*"
Directory Structure (After):
my-hugo-docs/
├── config.toml
├── content/
│ ├── _index.md
│ ├── index.md
│ ├── getting-started.md
│ ├── api/
│ │ ├── authentication.md
│ │ └── endpoints.md
│ └── tutorials/
│ ├── tutorial-1.md # Converted from PDF
│ └── tutorial-2.md # Converted from DOCX
├── static/
│ └── images/
│ └── logo.png # Copied from source
├── themes/
├── layouts/
└── data/
Sample Converted File (content/getting-started.md):
+++
title = "Getting Started Guide"
date = 2025-01-22T10:00:00
author = "Documentation Team"
description = "Quick start guide for new users"
tags = ["tutorial", "beginner"]
draft = false
+++
# Getting Started
Welcome to our product! This guide will help you get up and running.

## Installation
Follow these steps to install...
Building the Site:
cd my-hugo-docs
hugo server -D # Preview at http://localhost:1313
Convert Blog Posts to Jekyll Site
Scenario: You have blog posts as markdown files with frontmatter metadata that you want to convert to a Jekyll blog.
Directory Structure (Before):
posts/
├── welcome.md
├── first-tutorial.md
├── advanced-tips.md
└── images/
├── welcome-banner.png
└── tutorial-screenshot.png
Sample Source File (posts/welcome.md):
---
title: Welcome to My Blog
author: Jane Blogger
creation_date: 2025-01-22T09:00:00
keywords: blog, welcome, introduction
description: Welcome post introducing my new blog
---
# Welcome!
This is my first blog post...

Command:
all2md generate-site posts/ \
--output-dir my-jekyll-blog \
--generator jekyll \
--scaffold \
--recursive \
--exclude "images/*"
Directory Structure (After):
my-jekyll-blog/
├── _config.yml
├── _posts/
│ ├── 2025-01-22-welcome.md
│ ├── first-tutorial.md
│ └── advanced-tips.md
├── assets/
│ └── images/
│ ├── welcome-banner.png
│ └── tutorial-screenshot.png
├── _layouts/
│ ├── default.html
│ └── post.html
└── _includes/
Sample Converted File (_posts/2025-01-22-welcome.md):
---
title: Welcome to My Blog
date: 2025-01-22 09:00:00
author: Jane Blogger
description: Welcome post introducing my new blog
categories:
- blog
- welcome
- introduction
layout: post
---
# Welcome!
This is my first blog post...

Building the Site:
cd my-jekyll-blog
bundle exec jekyll serve # Preview at http://localhost:4000
Migration Workflows
PDF Reports to Hugo Documentation:
# Convert quarterly reports to a Hugo docs site
all2md generate-site reports/*.pdf \
--output-dir company-docs \
--generator hugo \
--content-subdir reports \
--scaffold \
--pdf-pages "1-10" # Only first 10 pages
DOCX Policies to Jekyll Knowledge Base:
# Convert policy documents to a searchable Jekyll site
all2md generate-site policies/ \
--output-dir kb-site \
--generator jekyll \
--scaffold \
--recursive \
--exclude "templates/*" \
--exclude "drafts/*"
Mixed Format Archives to Hugo:
# Convert docs from multiple formats
all2md generate-site archives/ \
--output-dir unified-docs \
--generator hugo \
--scaffold \
--recursive
API Reference
The generate-site command is powered by utilities in the all2md.utils.static_site module:
Python API
You can use these utilities directly in Python code:
from pathlib import Path
from all2md import to_ast
from all2md.utils.static_site import (
StaticSiteGenerator,
FrontmatterFormat,
FrontmatterGenerator,
SiteScaffolder,
ImageCollector,
copy_document_assets,
generate_output_filename,
)
# Parse a document
doc = to_ast('document.md')
# Generate frontmatter
fm_gen = FrontmatterGenerator(
generator=StaticSiteGenerator.HUGO,
format=FrontmatterFormat.TOML
)
frontmatter = fm_gen.generate(doc.metadata)
# Collect images
collector = ImageCollector()
collector.collect(doc)
print(f"Found {len(collector.images)} images")
# Copy assets and update document
output_dir = Path('my-site')
modified_doc, asset_paths = copy_document_assets(
doc=doc,
output_dir=output_dir,
generator=StaticSiteGenerator.HUGO,
source_file=Path('document.md')
)
# Generate output filename
filename = generate_output_filename(
source_file=Path('document.md'),
metadata=doc.metadata,
generator=StaticSiteGenerator.HUGO
)
# Scaffold a site
scaffolder = SiteScaffolder(StaticSiteGenerator.JEKYLL)
scaffolder.scaffold(output_dir)
Module Documentation
See the complete API reference:
all2md.utils.static_site- Static site generation utilitiesall2md.utils.static_site.FrontmatterGenerator- Frontmatter generationall2md.utils.static_site.SiteScaffolder- Site scaffoldingall2md.utils.static_site.ImageCollector- Image collectionall2md.utils.static_site.copy_document_assets()- Asset copyingall2md.utils.static_site.generate_output_filename()- Filename generation
Comparison with HTML Templating
all2md provides two distinct approaches for static site generation:
generate-site Command (This Document)
Best for:
Creating Hugo, Jekyll, MkDocs, Zola, or Eleventy sites quickly
Migrating documentation to static site generators
Working with established static site ecosystems
Batch converting document collections
Features:
Purpose-built for Hugo, Jekyll, MkDocs, Zola, and Eleventy
Automatic frontmatter generation
Site scaffolding
Generator-specific conventions
Integrated asset management
Example:
all2md generate-site docs/ \
--output-dir hugo-site \
--generator hugo \
--scaffold
HTML Renderer with Templates
Best for:
Custom HTML generation with full control
Creating standalone HTML sites
Using custom templates (Jinja2, inject, replace modes)
Integrating with custom build pipelines
Features:
Full template control (Jinja2, inject, replace modes)
CSS class mapping
Syntax highlighting
Table of contents generation
Custom metadata integration
Example:
all2md document.md --output-format html \
--html-renderer-template-mode jinja \
--html-renderer-template-file custom-template.html \
--out document.html
For HTML templating documentation, see:
all2md.renderers.html - HTML Renderer API
Python API Workflows - Markdown to HTML conversion
Best Practices
Organizing Source Documents
Use Meaningful Filenames:
Source filenames become output filenames when there’s no title metadata:
Good: getting-started-guide.md
Poor: doc1.md
Include Metadata:
Add frontmatter to source markdown files for better results:
---
title: Advanced Python Techniques
author: Sarah Developer
date: 2025-01-22
keywords: python, advanced, tutorial
description: Learn advanced Python patterns
---
# Advanced Python Techniques
...
Organize Images Relative to Documents:
Keep images near the documents that reference them:
docs/
├── guide.md
├── tutorial.md
└── images/
├── guide-diagram.png
└── tutorial-screenshot.png
Metadata Conventions
Use Consistent Date Formats:
Prefer ISO 8601 format for dates:
date: 2025-01-22T14:30:00 # ISO 8601 with time
date: 2025-01-22 # ISO 8601 date only
Use Lists for Tags/Categories:
Lists are more maintainable than comma-separated strings:
# Preferred
tags:
- python
- tutorial
- beginner
# Also works
tags: python, tutorial, beginner
Include Descriptions:
Descriptions improve SEO and readability:
description: A comprehensive guide to getting started with Python programming
Asset Organization
Use Relative Paths in Source:
Relative paths work best with asset copying:
 # Good
 # Good
 # May not be found
Avoid Special Characters in Filenames:
Use simple, URL-safe filenames:
Good: user-flow-diagram.png
Poor: User Flow (2024) [Final].png
Don’t Commit Remote URLs:
Remote images won’t be copied but will remain as references:
# These will be left as-is (not copied)


Testing Generated Sites
Preview Locally:
Always preview the generated site before deployment:
# Hugo
cd my-hugo-site
hugo server -D # -D includes drafts
# Visit http://localhost:1313
# Jekyll
cd my-jekyll-blog
bundle exec jekyll serve
# Visit http://localhost:4000
Check Asset Links:
Verify that all images and assets load correctly in the preview.
Review Frontmatter:
Check that metadata was mapped correctly by viewing the generated markdown files.
Test Search and Navigation:
If using a theme with search or navigation, ensure it works with your content structure.
Incremental Updates
Regenerate Only Changed Content:
Use --exclude to skip already-converted files:
# First run: convert everything
all2md generate-site docs/ \
--output-dir site \
--generator hugo \
--scaffold
# Later: convert only new files
all2md generate-site docs/new/ \
--output-dir site \
--generator hugo
# Note: No --scaffold to avoid overwriting config
Version Control:
Commit both source documents and generated site to version control for reproducibility:
project/
├── source-docs/ # Original documents (commit)
├── hugo-site/ # Generated site (commit)
└── .gitignore # Ignore build artifacts
See Also
Related Documentation:
Command Line Interface - Complete CLI reference with all global options
Python API Workflows - Markdown to HTML and other formats
Configuration Options - Document conversion options
AST Transforms and Hooks - Document transformation guide
Attachment Handling - Attachment handling strategies
API Reference:
all2md.utils.static_site- Static site generation utilitiesall2md.renderers.html.HtmlRenderer- HTML renderer for custom templates
External Resources:
Hugo Documentation - Official Hugo docs
Jekyll Documentation - Official Jekyll docs
Hugo Themes - Hugo theme gallery
Jekyll Themes - Jekyll theme gallery