Yet another markdown site generator (because Jekyll, Hugo, 11ty, Astro, Next.js, Gatsby, VitePress, Docusaurus, MkDocs, MkDocs Material, GitBook, Docus, VuePress, and Nuxt Content weren't enough)
A simple markdown-to-HTML site builder with optional translations.
bun add simple-markdown-builderimport { build } from 'simple-markdown-builder'
await build({
baseUrl: 'https://aerialyoga.example.com',
templatePath: 'scripts/template.html',
defaultMeta: {
title: 'Aerial Yoga Studio',
description: 'Aerial yoga classes and equipment',
sidebarTitle: 'Aerial Yoga Studio',
sidebarSummary: 'Welcome to our aerial yoga studio',
backLinkHref: '/',
backLinkLabel: 'Back to home',
},
})import { build, ensureTranslations } from 'simple-markdown-builder'
const config = {
baseUrl: 'https://aerialyoga.example.com',
templatePath: 'scripts/template.html',
defaultMeta: { /* ... */ },
translations: {
apiKey: process.env.DEEPL_API_KEY,
targetLanguages: ['fr', 'nl'],
defaultLang: 'en',
supportedLangs: ['en', 'fr', 'nl'],
customGlossary: {
fr: {
'aerial silks': 'soies aériennes',
},
},
},
}
await ensureTranslations(config, 'content', false)
await build(config)import { startDevServer } from 'simple-markdown-builder'
await startDevServer(config, {
port: 4173,
outputDir: 'docs',
clean: true, // Optional: clean HTML files before building
refreshTranslations: false, // Optional: refresh translations on start
})contentDir- Source markdown directory (default:content)outputDir- Output HTML directory (default:docs)baseUrl- Base URL for absolute links (required)defaultMeta- Default front matter values (required)templatePath- Path to HTML template file (required)homepageTemplatePath- Optional separate template for homepagemarkdownOptions- MarkdownIt configuration optionstranslations- Translation config:falseto disable, or object with DeepL settingsutmParams- UTM parameters object for external linksskipLinkCheck- Whether to skip link validationclean- Clean HTML files from output directory before building (default:false)
Templates support these placeholders:
{{TITLE}}- Page title{{DESCRIPTION}}- Page description{{BODY}}- Rendered HTML body{{LANGUAGE_SWITCHER}}- Language selector UI{{LANG}}- Current page language code{{BACK_LINK_HREF}}- Back link URL{{BACK_LINK_LABEL}}- Back link text{{SIDEBAR_TITLE}}- Sidebar title{{SIDEBAR_SUMMARY}}- Sidebar summary{{YEAR}}- Current year
Images can be set in two ways:
- Default for all pages: Set in
defaultMetaconfiguration - Per-page: Set in the page's front-matter
ogImage: Used for Open Graph tags. If not provided, a warning is logged and the tag is omitted.
twitterImage: Used for Twitter Card image. Only set if explicitly provided (no fallback to ogImage).
Example:
await build({
baseUrl: 'https://example.com',
templatePath: 'template.html',
defaultMeta: {
title: 'My Site',
description: 'Site description',
ogImage: 'img/default-og.png', // Default for all pages
twitterImage: 'img/default-twitter.png', // Optional
// ... other meta fields
},
})Or per-page in front-matter:
---
title: My Page
ogImage: img/page-specific-og.png
twitterImage: img/page-specific-twitter.png
---Template Placeholders Removed: The following placeholders are no longer needed - meta tags are automatically injected:
{{OG_URL}},{{OG_TITLE}},{{OG_DESCRIPTION}},{{OG_IMAGE}}{{TWITTER_TITLE}},{{TWITTER_DESCRIPTION}},{{TWITTER_IMAGE}}{{CANONICAL_URL}},{{HREFLANG_LINKS}},{{NOINDEX}},{{META_TAGS}}
Note: {{DESCRIPTION}} is still available as a template placeholder for use in the body content, but the meta description tag is automatically injected in the head.
Migration: Remove these placeholders from your templates. Ensure your template has a </head> tag - all meta tags will be automatically injected before it.
UTM parameters are provided as an object:
{
utmParams: {
utm_campaign: 'mycampaign',
utm_medium: 'website',
utm_source: 'mysite',
},
}These are automatically appended to external links.
Slugs default to the filename (without extension). Directory structure is automatically preserved in the output:
content/index.md→docs/index.htmlcontent/about.md→docs/about.htmlcontent/classes/beginner.md→docs/classes/beginner.html
You can override the slug in front matter if needed:
---
title: About Us
slug: about
---If the slug contains a path (e.g., slug: shop/aerial-silks), it will be used directly for the output path.
