Build a static site from Markdown, MDX, and TypeScript. PureStack provides a CLI for local development and release builds, plus a TypeScript API for custom build workflows.
Pages become routes based on their filenames. PureStack renders the HTML, generates theme styles, copies assets, and bundles browser-side TypeScript when a page needs it.
PureStack Forge is PureStack's website builder. Build, customize, and maintain your PureStack website.
npx purestack@latest initPureStack CLI prints a link to open Forge in your browser. Configure your site's details, choose a template and its settings, decide whether to install dependencies and set up Git, then create the project and follow its progress. Use Browse live site to open the running project. Forge stays open, and source edits reload the live site. Finish Forge stops both local servers.
The starter template creates a site with a home page, about page, and
customization guide. Template files become your project's source, and
AGENTS.md explains customization and validation. Generated starter projects
provide yarn dev, yarn build, and yarn publish; the latter prepares
dist/publish for deployment without uploading anything.
Forge listens on 127.0.0.1 with an automatically assigned port. Command-line
options can preset its choices, for example a folder, template, and options:
npx purestack@latest init my-site --template starter --set palette=mintTemplates can be official aliases, explicit releases such as starter@1.1.20,
npm package names, or local folders and .tgz archives. Run
npx purestack@latest init --help for every option, including --yes, which
creates a site directly for scripts and CI.
Create a Node project and install PureStack:
mkdir my-site
cd my-site
npm init -y
npm install purestack
mkdir contentAdd content/siteConfig.json:
{
"siteTitle": "My Site",
"logo": { "brand": "My Site", "href": "/" },
"outDir": "../dist/site",
"publishDir": "../dist/publish"
}Add content/index.mdx:
---
title: Welcome
description: My first PureStack site.
template: doc
---
# Welcome
This page is written in MDX and served by PureStack.
<Panel tone="info" variant="surface">
<p>Edit this file and see the page update.</p>
</Panel>Start the development server:
npx purestack serve --content ./content --host 127.0.0.1 --port 5000Open http://127.0.0.1:5000/. The server watches the content directory and reloads the page when you edit it.
The two files above are enough for a working site. Add content/about.mdx for
an /about/ route, or content/guides/install.mdx for /guides/install/.
Images and other static files inside content are copied to the output with
their relative paths intact.
Pages can load a local TypeScript file with PageScript. Add this to
content/index.mdx:
<button id="hello-button" type="button">Say hello</button>
<output id="hello-output" aria-live="polite"></output>
<PageScript src="./hello.ts" />Then create content/hello.ts:
const button = document.querySelector<HTMLButtonElement>('#hello-button')
const output = document.querySelector<HTMLOutputElement>('#hello-output')
button?.addEventListener('click', () => {
if (output) output.textContent = 'Hello from TypeScript!'
})PureStack bundles the script and serves it with the generated page. The same
content directory can contain ordinary Markdown (.md), MDX (.mdx), and
Regor MDX (.rmdx) pages. MDX pages can also use PureStack's built-in
components, as the Panel example above does.
Run these commands from the project root:
| Command | Result |
|---|---|
npx purestack serve --content ./content |
Build, serve, watch, and reload locally. Default port: 4173. |
npx purestack build --content ./content |
Write the static site to outDir (dist/site in the example). |
npx purestack publish --content ./content |
Clean and build a minified release artifact in publishDir (dist/publish in the example). |
publish prepares files for a static host; it does not upload them. Use
--clean with build or serve to clear the output directory before a build.
PureStack writes only into output directories it created, so a mistyped path
cannot overwrite or clear other files. Use --out <name> with build or
serve to use <outDir>-<name> instead, for example to run a second server
with --out 2 --port 4174.
Use --no-cache with any command to skip persistent caches, such as
highlighted code and optimized images, for a fully cold build.
Use --host and --port with serve to choose its address. Every command
needs --content pointing to a directory with siteConfig.json.
For the full option list, run npx purestack --help.
Plugins add a site's own skins, components, templates, generated pages, and
build steps. List them in content/purestack.config.ts; every command loads it,
and serve reloads it when it or a file it imports changes:
import { defineConfig, definePlugin } from 'purestack'
const releaseNotes = definePlugin({
name: 'release-notes',
pages: () => [{ path: 'releases.mdx', source: '# Releases' }],
})
export default defineConfig({ plugins: [releaseNotes] })The Plugins guide covers each kind of extension.
The package also re-exports the @purestack/ts-ssg API. For example, a custom
build script can run the same pipeline as the CLI:
import path from 'node:path'
import { buildSite } from 'purestack'
const result = await buildSite({
siteConfig: { contentDir: path.resolve('content') },
})
console.log(`Built ${result.pages} pages in ${result.outDir}`)startDevServer is available too. Neither function looks for
purestack.config.ts; pass plugins through options.plugins.
MIT licensed. Source and issues: PureStack on GitHub.