Dev Server
Run sitemd launch to start a local dev server at localhost:4747. Every feature works — pages, auth, forms, data, analytics, SEO, gating — regardless of activation status. Save any file and the site rebuilds automatically.
How it works
The dev server renders your site in memory and serves it as a single-page application. Instead of writing HTML files to disk, it builds all pages into an in-memory store and serves them through a lightweight HTTP server with SPA navigation.
Browser request → skeleton HTML shell
└─ hydrate.js fetches shell (header, footer) from /__api/shell
└─ hydrate.js fetches page content from /__api/page?slug=/about
└─ hydrate.js fetches metadata from /__api/meta?slug=/about
└─ clicking a link → fetches the new page without a full reload
The skeleton HTML is an empty document with container elements. All content is loaded client-side by the hydration script. View-sourcing a page shows references to localhost URLs — without the dev server running, the page is blank.
Skeleton HTML
Every page request returns the same HTML shell:
<div id="sitemd-shell"></div> <!-- header + nav injected here -->
<main id="sitemd-main">
<article class="content"></article> <!-- page content injected here -->
</main>
<div id="sitemd-footer"></div> <!-- footer injected here -->
The hydration script (hydrate.js) populates these containers by calling the dev server API. Navigation between pages swaps the content without reloading — page transitions are instant.
API endpoints
The dev server exposes internal endpoints for the hydration layer:
| Endpoint | Returns |
|---|---|
/__api/shell |
Header HTML, footer HTML, brand, theme CSS path |
/__api/page?slug=/about |
Rendered page content (the <article> inner HTML) |
/__api/meta?slug=/about |
Page title, description, sidebar, nav, auth attributes |
/__api/layout-scripts |
Inline JS from theme/layout.html (search, lightbox, modals) |
/__reload |
Server-Sent Events stream for live reload |
These endpoints are internal to the dev server. They don't exist in production builds.
Auth and data in dev mode
When an auth provider is configured in settings/auth.md, the dev server injects:
- The account button in the header (person icon linking to
/login) - Auth config (
window.__sitemdAuthCfg) and theauth.jsruntime script - Flash prevention — hides page content until auth state resolves on gated pages
- Gated section CSS — hides
gated:blocks until the auth runtime reveals them - Per-page auth attributes —
data-auth="required"anddata-gated-typeson<main>for pages that require login
When a data provider is configured in settings/data.md, the dev server injects the data.js runtime script with provider credentials.
Auth and data work identically in dev and production. The only difference is where the HTML comes from — memory (dev) vs disk (production build).
Local auth testing
When using provider: custom, the dev server includes a built-in auth stub so you can test login, signup, magic links, gated pages, and account dashboards without a real API backend.
The stub intercepts all auth API calls locally — no external server needed. It accepts any email and password, exchanges any magic link code, and returns mock session data. Page gating, the header auth button, and gated sections all work exactly as they would in production.
How it works
The dev server overrides apiUrl to point to a local endpoint (/__auth) and handles all auth routes in-memory:
| Action | What happens |
|---|---|
| Login (any email + password) | Creates a session, logs you in |
| Signup (any email + password) | Creates a session, logs you in |
| Magic link exchange (any code) | Creates a session, logs you in |
| Logout | Clears the session |
| Account endpoints | Returns mock user data from the current session |
| Licenses, activations, API keys | Returns mock data |
Sessions are stored in memory on the dev server. Restarting the server clears all sessions.
Testing magic links
Navigate directly to your afterLogin page with any magic code in the URL hash:
http://localhost:4747/account#magic=anytoken
The stub accepts any value as a valid exchange code. You're logged in immediately.
Testing page gating
- Set
auth: requiredin a page's frontmatter - Visit the page while logged out — you're redirected to
/login - Log in with any email and password
- Visit the gated page again — content is visible
Testing gated sections
Add gated: blocks in your page content. Log in to see them appear. Log out to confirm they're hidden.
What the stub does not do
The stub is for testing UI flows. It does not:
- Send emails (magic link requests return success but no email is sent)
- Validate passwords (any password is accepted)
- Persist data (sessions clear on server restart)
- Run webhooks (
userDataUrlcalls still go to the configured external URL)
For production auth behavior, configure your real API URL in settings/auth.md and deploy.
Third-party providers
The local auth stub only applies to provider: custom. If you use Supabase, Firebase, Clerk, or Auth0, the dev server connects to your provider directly — those providers handle auth in both dev and production.
What you see vs what ships
The dev server shows you the exact same site that sitemd deploy produces. The differences are structural, not visual:
| Dev server | Production build | |
|---|---|---|
| HTML source | Skeleton + client hydration | Standalone, fully rendered |
| Output location | Memory only | site/ directory on disk |
| Navigation | SPA (no full reloads) | Standard page loads |
| SEO metadata | Rendered in memory | Written to HTML, sitemap.xml, robots.txt |
| Search | Uses search index from last build | Fresh search-index.json in output |
| Dev panel | Available (⌘/) | Not included |
| Trial banner | Shown if not activated | Not included |
Trial vs activated
The dev server behaves the same whether the site is activated or not. All features render fully in both modes.
The only visible differences in trial mode:
- A trial mode banner at the bottom of every page
- The "built with sitemd" footer badge is always visible
sitemd buildandsitemd deployare not available
These are licensing markers, not feature restrictions. Activate your site to unlock production builds. See Activate a Site.
Why skeleton HTML?
The dev server never writes standalone HTML to disk during development. This is by design:
- Faster rebuilds — writing to memory is faster than writing files
- SPA navigation — instant page transitions during development
- Source protection — the dev server binary contains the build logic; skeleton HTML has no value without the running server
Production-ready HTML is produced by sitemd build or sitemd deploy, both of which require activation.
Starting the dev server
Three ways to start:
# CLI
sitemd launch
# Agent skill
/launch
# MCP tool
sitemd_build # with serve mode
The dev server watches pages/, settings/, and theme/ for changes. Saves trigger a rebuild and the browser refreshes automatically via Live Build Sync.
Related
- User Auth & Gating — full auth setup, gating pages, user types
- Magic Link Auth — passwordless login configuration
- Live Build Sync — file watching, theme sync, auto-reload
- Dev Panel — in-browser editor
- Build Modes — trial vs activated
- Activate a Site — unlock production builds
- Site Diagnostics — debugging auth and data issues on deployed sites