@digitalfruition/spark
v0.1.0
Published
Digital Fruition SPARK static Markdown site generator.
Downloads
14
Maintainers
Readme
DF SPARK
Digital Fruition SPARK is a lightweight static website generator written in Node.js.
It converts Markdown files into HTML pages using a shared HTML template and reusable include files. It supports both:
- Live preview mode for local development
- Static build mode for CI/CD pipelines and CDN deployment
The generated output is pure static HTML, CSS, JavaScript, and assets suitable for deployment to:
- Cloudflare Pages
- Cloudflare R2 + CDN
- Amazon S3 + CloudFront
- GitHub Pages
- Netlify
- Any static web host
Quick Start
Use DF SPARK from a website repository that contains your content, templates, includes, components, and assets.
Install the package:
npm install --save-dev @digitalfruition/sparkAdd package scripts:
{
"scripts": {
"build": "df-spark build",
"serve": "df-spark serve --port 3000"
}
}Create the expected site files:
.
├── package.json
├── template.html
├── content/
│ └── index.md
├── includes/
├── components/
└── assets/Add a minimal template.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
</head>
<body>
<main>
{{body}}
</main>
</body>
</html>Add content/index.md:
---
title: Home
---
# Home
Welcome to the site.Preview locally:
npm run serveBuild static output:
npm run buildThe generated site is written to dist/.
Example Site
For a fuller starter, copy the example website:
cp -R examples/basic-site my-site
cd my-site
npm install
npm run serveThe example is shaped like a standalone website repository. Its npm scripts call the package binary:
{
"scripts": {
"build": "df-spark build",
"serve": "df-spark serve --port 3000"
}
}It demonstrates:
- A SitePalette-style template structure with
header_div,topnav_div,leftnav_div,rightnav_div,content_div, andfooter_div - Frontmatter titles
- HTML and Markdown includes
- Markdown components
- A nested page under
content/docs/ - Static CSS under
assets/
Project Goals
Simplicity
Content should be written as Markdown files stored directly in Git.
No databases, build servers, CMS platforms, or runtime dependencies are required once the site is published.
Reusable Layouts
All pages share a common HTML template containing:
- Site header
- Navigation
- Footer
- Shared CSS and JavaScript references
Individual page content is injected into the template automatically.
Modular Components
Reusable content fragments can be stored separately and included wherever needed.
Examples:
- Navigation menus
- Callout boxes
- Sidebars
- Shared notices
- Legal disclaimers
Fast Local Development
A local preview server renders pages on demand.
Content changes are immediately visible without running a full site build.
CI/CD Friendly
A single command renders the entire site into a static dist/ directory suitable for publication by a CI pipeline.
Directory Structure
.
├── site.js
├── package.json
├── template.html
│
├── includes/
│ ├── header.html
│ ├── nav.md
│ └── footer.md
│
├── components/
│ ├── sidebar.md
│ ├── rightnav.md
│ └── callout.md
│
├── assets/
│ └── css/
│ └── site.css
│
├── examples/
│ └── basic-site/
│ ├── package.json
│ ├── template.html
│ ├── assets/
│ ├── components/
│ ├── content/
│ └── includes/
│
├── content/
│ ├── index.md
│ ├── about.md
│ └── docs/
│ └── getting-started.md
│
└── dist/Content Model
Pages
Markdown files under content/ become full website pages.
Example:
content/about.mdbecomes:
dist/about.htmlThe generated HTML is wrapped using template.html.
Components
Markdown files under components/ become reusable HTML fragments.
Example:
components/sidebar.mdbecomes:
dist/components/sidebar.htmlComponent output is not wrapped in the site template.
Nested component paths are preserved:
components/cards/callout.mdbecomes:
dist/components/cards/callout.htmlComponents may include files from includes/ or other Markdown components, and pages, templates, and other components may include them using the standard include syntax.
This allows components to be reused independently and previewed directly.
Includes
Files under includes/ are inserted directly into templates or pages.
Examples:
includes/header.html
includes/footer.md
includes/nav.mdThese are not published directly.
They exist only to build pages.
Template System
The main template file is:
template.htmlExample:
<!doctype html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<!-- include: includes/header.html -->
<!-- include: includes/nav.html -->
<main>
{{body}}
</main>
<!-- include: includes/footer.html -->
</body>
</html>Template Variables
Page Body
{{body}}Replaced with rendered Markdown content.
Page Title
{{title}}Populated from the first available source:
titlein frontmatter- First Markdown H1
- Markdown filename stem
Titles are HTML-escaped when inserted into the template.
Include Syntax
Includes use standard HTML comments:
<!-- include: includes/nav.html -->Markdown components may also be included:
<!-- include: components/sidebar.md -->The same include syntax works in template.html, Markdown pages under content/, HTML fragments under includes/, and Markdown components under components/.
Include targets must be relative paths under one of these project source directories:
includes/
components/The renderer will:
- Load the file
- Render Markdown if necessary
- Insert the resulting HTML
- Resolve nested includes recursively
Nested includes are supported across HTML and Markdown fragments. For example, an HTML include may include another HTML fragment or a Markdown component, and a Markdown component may include additional fragments.
Missing includes, include cycles, absolute-path includes, and includes that use .. traversal to escape the approved directories fail rendering with a controlled include diagnostic. Static build mode exits non-zero. Live preview mode returns a 500 response with a readable diagnostic.
Frontmatter
Optional YAML frontmatter may be added to any page.
Example:
---
title: About Us
---
# About
Welcome to our website.For v1.0.0, the supported frontmatter field is:
title: used for the{{title}}template variable
Frontmatter is metadata only and is not rendered into the page body.
URL Mapping
Page Output Mapping
Static build mode writes Markdown pages under content/ to matching .html files under dist/.
content/index.md
→ dist/index.htmlcontent/about.md
→ dist/about.htmlcontent/docs/getting-started.md
→ dist/docs/getting-started.htmlDirectory-style build output is not part of v1.0.0. A source file such as:
content/docs/getting-started.mddoes not generate:
dist/docs/getting-started/index.htmlFuture enhancements may add directory-style output, canonical URL generation, or redirects.
Page Preview Mapping
Live preview mode accepts classic .html page URLs and extensionless aliases:
content/index.md
→ /content/about.md
→ /about
→ /about.htmlcontent/docs/getting-started.md
→ /docs/getting-started
→ /docs/getting-started.htmlPreview does not alias a leaf Markdown file to a trailing-slash route. For example, this source file:
content/docs/getting-started.mdis not served from:
/docs/getting-started/That route is reserved for an actual directory index source such as:
content/docs/getting-started/index.mdThis keeps v1.0.0 preview behavior aligned with classic .html build output instead of implying directory-style output that the build does not generate.
Component Mapping
components/sidebar.md
→ /components/sidebar.htmlcomponents/cards/callout.md
→ /components/cards/callout.htmlComponent preview routes render the same unwrapped HTML fragments as static build output. The preview server also accepts extensionless component routes such as:
/components/sidebarLive Preview Mode
Start the development server:
npm run serveDefault URL:
http://127.0.0.1:3000Features:
- Render pages on demand
- Render component routes as unwrapped HTML fragments
- No build step required
- Supports includes
- Supports Markdown rendering
- Suitable for local development
The preview server binds to 127.0.0.1 by default. Use --host 0.0.0.0 only when you intentionally need access from another device or container.
Static Build Mode
Generate a complete static site:
npm run buildOutput:
dist/All Markdown files are rendered and written to disk.
This mode is intended for CI/CD pipelines.
Command Line
Show CLI usage:
df-spark --helpFrom this repository checkout, the primary project commands remain:
npm run build
npm run serveThe package exposes a df-spark binary for website repositories that depend on SPARK.
Supported build flags:
--out dist
--content content
--components components
--includes includes
--template template.htmlSupported preview flags:
--port 3000
--host 127.0.0.1
--content content
--components components
--includes includes
--template template.htmlIndependent website repositories should call the package binary from their npm scripts instead of referencing this repository's site.js file directly. For example:
{
"devDependencies": {
"@digitalfruition/spark": "^0.1.0"
},
"scripts": {
"build": "df-spark build",
"serve": "df-spark serve --port 3000"
}
}The direct node site.js ... entrypoint remains available for repository development and tests, but website repositories should use df-spark.
Package Metadata
DF SPARK is shaped as a public scoped npm package named @digitalfruition/spark with the CLI binary df-spark.
Publishing remains a human release action. The package includes no publish script, credentials, or deployment configuration.
The npm package uses a files allowlist so packed releases include runtime source, public documentation, and the copyable basic example. Local planning files, generated output, reports, tests, and dependency folders are excluded from the package tarball.
The package is configured with MIT licensing, public npm access, and public GitHub repository metadata.
CI/CD Example
npm ci
npm test
npm run buildPublish the contents of:
dist/to the desired static hosting platform.
Testing
Run the deterministic test suite with:
npm testGitHub Actions runs on pull requests and pushes to main with explicit Node.js versions. It installs dependencies with npm ci, runs npm test, builds the sample site, packs the @digitalfruition/spark package, installs the tarball into a temporary external website fixture, and invokes df-spark build from that fixture.
GitLab CI also runs the test suite for merge requests and main branch pipelines using the JUnit reporter.
See TESTING.md for the current test cases, fixture strategy, and CI reporting details.
Asset Handling
Intentional static assets belong under:
assets/During static builds, files in assets/ are copied to:
dist/assets/Nested asset paths are preserved. For example:
assets/images/logo.pngbecomes:
dist/assets/images/logo.pngThe build also copies approved root static files when present:
favicon.ico
robots.txtProject source files, package metadata, dependencies, local planning files, and previous build output are not copied into dist/.
Design Principles
- Git-first workflow
- Markdown-first content authoring
- No runtime dependencies in production
- Static hosting compatible
- Minimal configuration
- Easy to understand
- Easy to extend
The system intentionally favors simplicity over feature richness. It is designed to be understandable by a single developer in a short amount of time while still supporting reusable layouts and automated deployment.
