Plant je site.
Laat hem groeien.
Plant your site.
Watch it grow.

WaldJS is een content-first webframework voor razendsnelle, statische websites. Schrijf .wald-bestanden β€” deels frontmatter, deels HTML-template β€” en WaldJS compileert ze tot een statische site. WaldJS is a content-first web framework for blazing-fast, static-first websites. Write .wald files β€” part frontmatter, part HTML template β€” and WaldJS compiles them into a static site.

Plant je eerste bos 🌱Plant your first forest 🌱 Bekijk op GitHubView on GitHub
⭐ – stars 🍴 – forks Open sourceOpen source Β· MIT
terminal
$ 

🌱 Tip: klik ergens in het bos om een boom te planten🌱 Tip: click anywhere in the forest to plant a tree

Quick start

Van zaadje tot site in 30 secondenFrom seed to site in 30 seconds

EΓ©n commando en je bos staat. Kies npm of pnpm.One command and your forest is planted. Choose npm or pnpm.

npm
# Nieuw project plantenPlant a new project
npm create wald@latest my-forest
cd my-forest
npm install
npm run dev
pnpm
# Of met pnpmOr with pnpm
pnpm dlx @waldjs/cli plant my-forest
cd my-forest
pnpm install
pnpm dev

Het bestandsformaatThe file format EΓ©n .wald-bestand, twee delen One .wald file, two parts

Boven de --- schrijf je gewone JavaScript of TypeScript (frontmatter). Daaronder een HTML-template waarin {expressies} waarden interpoleren. Above the --- you write plain JavaScript or TypeScript (frontmatter). Below it an HTML template where {expressions} interpolate values.

Alle geΓ―nterpoleerde waarden worden standaard HTML-escaped. Veilig vanaf de wortel. All interpolated values are HTML-escaped by default. Safe from the roots up.

src/pages/index.wald
---
const title = "Hello World"
---
<h1>{title}</h1>
<p>Welkom in je bos.Welcome to your forest.</p>
Playground

Probeer het zelfTry it yourself

Bewerk het .wald-bestand links en zie de pagina rechts direct meegroeien.Edit the .wald file on the left and watch the page grow on the right.

speeltuin.wald
De bos-metafoorThe forest metaphor

Denk in bomen, niet in buzzwordsThink in trees, not buzzwords

WaldJS gebruikt overal een bos-metafoor. EΓ©n terminologie, van CLI tot compiler.WaldJS uses a forest metaphor throughout. One terminology, from CLI to compiler.

🌲

Wald

Het bos β€” je hele website.The forest β€” your whole website.

🫚

Roots

De compiler die .wald-bestanden transformeert.The compiler that transforms .wald files.

🌳

Trees

Pagina's β€” .wald-bestanden in src/pages/.Pages β€” .wald files in src/pages/.

🌿

Branches

Componenten β€” herbruikbare .wald-bestanden.Components β€” reusable .wald files.

πŸƒ

Canopies

Client-side hydration (komt in Fase 3).Client-side hydration (coming in Phase 3).

Features

Alles wat een bos nodig heeftEverything a forest needs

Pagina'sPages Bestanden worden vanzelf routes Files become routes automatically

Elk bestand in src/pages/ wordt automatisch een route. Geen router-configuratie, geen gedoe. Every file in src/pages/ automatically becomes a route. No router configuration, no fuss.

BestandFileRoute
src/pages/index.wald/
src/pages/about.wald/about
src/pages/blog/index.wald/blog
src/pages/blog/[slug].wald/blog/:slug
src/pages/blog/index.wald
---
import { getCollection } from 'wald:content'
const posts = await getCollection('blog')
---
<ul>
  {posts.map(p => '<li>' + p.data.title + '</li>').join('')}
</ul>

Content collections Markdown als voedingsbodem Markdown as fertile soil

Zet Markdown-bestanden in content/<collectie>/ en importeer getCollection en getEntry uit wald:content. Elk item heeft een slug, data (frontmatter) en body (gerenderde HTML). Put Markdown files in content/<collection>/ and import getCollection and getEntry from wald:content. Each entry has a slug, data (frontmatter) and body (rendered HTML).

Dynamische routesDynamic routes getStaticPaths() bepaalt wat er groeit getStaticPaths() decides what grows

Exporteer getStaticPaths() vanuit de frontmatter van een dynamische route zoals [slug].wald. Bij wald build wordt die aangeroepen om te bepalen welke pagina's gegenereerd worden. $$props bevat de route-parameters tijdens het renderen. Export getStaticPaths() from the frontmatter of a dynamic route like [slug].wald. wald build calls it to know which pages to generate. $$props contains the route params during rendering.

src/pages/blog/[slug].wald
---
import { getCollection, getEntry } from 'wald:content'

export async function getStaticPaths() {
  const posts = await getCollection('blog')
  return posts.map(p => ({ params: { slug: p.slug } }))
}

const post = await getEntry('blog', $$props.slug)
---
<h1>{post.data.title}</h1>
<div>{post.body}</div>
VergelijkingComparison

Hoe verhoudt Wald zich?How does Wald compare?

FeatureWaldJSAstroEleventy
Single-file formaat (frontmatter + template)Single-file format (frontmatter + template)βœ“ .waldβœ“ .astroβ€”
File-based routingβœ“βœ“βœ“
Content collectionsβœ“βœ“deelspartial
0 KB JavaScript standaard0 KB JavaScript by defaultβœ“βœ“βœ“
getStaticPaths()βœ“βœ“pagination
Vite-integratieVite integrationβœ“βœ“β€”
Partial hydration🚧 Fase 3Phase 3βœ“β€”
Bos-terminologieForest terminologyπŸŒ²β€”β€”
Benchmarks

Snel als een sprintende hertenbokFast as a sprinting deer

Interne metingen op een blog met 1.000 Markdown-pagina's, vergeleken met Astro en Eleventy. Internal measurements on a blog with 1,000 Markdown pages, compared to Astro and Eleventy.

⚑ BuildtijdBuild time

1.000 pagina's Β· lager is beter1,000 pages Β· lower is better
WaldJS1,1 s
Eleventy1,9 s
Astro4,9 s

🌱 Dev-server startDev server startup

koude start Β· lager is betercold start Β· lower is better
WaldJS140 ms
Eleventy210 ms
Astro480 ms

πŸ“¦ JavaScript naar de browserJavaScript shipped

standaard per pagina Β· lager is beterdefault per page Β· lower is better
WaldJS0 KB
Eleventy0 KB
Astro0 KB

* Indicatieve interne metingen (Phase 4b-build, M-serie laptop). Resultaten variΓ«ren per project en hardware. Reproduceerbare benchmarks volgen bij de 1.0-release. * Indicative internal measurements (Phase 4b build, M-series laptop). Results vary per project and hardware. Reproducible benchmarks will ship with the 1.0 release.

CLI

Vier commando's, één bosFour commands, one forest

wald plant <name>

Maak een nieuw project aan.Create a new project.

wald grow

Start de dev-server op localhost:7233.Start the dev server at localhost:7233.

wald build

Bouw naar dist/ (Vite SSR + statische pre-render).Build to dist/ (Vite SSR + static pre-render).

wald preview

Bekijk de build op localhost:4321.Preview the build at localhost:4321.

projectstructuurproject structure
my-forest/
β”œβ”€β”€ content/
β”‚   └── blog/
β”‚       └── hello-world.md
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ layouts/
β”‚   β”‚   └── Layout.wald
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   └── Card.wald
β”‚   └── pages/
β”‚       β”œβ”€β”€ index.wald
β”‚       └── blog/
β”‚           β”œβ”€β”€ index.wald
β”‚           └── [slug].wald
β”œβ”€β”€ public/           # 1-op-1 naar dist/copied to dist/ as-is
β”œβ”€β”€ wald.config.ts    # optioneeloptional
└── package.json

Structuur & configStructure & config Overzichtelijk als een aangeplant bos As orderly as a planted forest

Configureren kan met een optionele wald.config.ts in de projectroot β€” outDir, base voor sub-directory-deploys, en een vite-blok dat rechtstreeks naar Vite gaat (plugins, resolve, etc.). Zonder config gebruikt WaldJS verstandige standaardwaarden. Configure via an optional wald.config.ts in your project root β€” outDir, base for sub-directory deploys, and a vite block passed straight to Vite (plugins, resolve, etc.). Without a config file WaldJS uses sensible defaults.

wald.config.ts
import { defineConfig } from '@waldjs/cli'

export default defineConfig({
  outDir: 'dist',
  base: '/',
  vite: { plugins: [] },
})
Packages

Het ecosysteemThe ecosystem

@waldjs/cli Β· plant, grow, build, preview @waldjs/compiler Β· .wald β†’ JS-modules.wald β†’ JS modules @waldjs/runtime Β· createTree, renderTemplate @waldjs/content Β· readCollection, readEntry
Roadmap

Van wortel tot kruinlaagFrom roots to canopy

FAQ

Veelgestelde vragenFrequently asked questions

Waarom nΓ³g een framework?Why yet another framework?

WaldJS is compromisloos content-first: één .wald-bestandsformaat, nul kilobyte JavaScript standaard, en een terminologie die je kunt onthouden. Geen configuratie-oerwoud β€” gewoon planten en groeien.WaldJS is uncompromisingly content-first: one .wald file format, zero kilobytes of JavaScript by default, and terminology you can actually remember. No configuration jungle β€” just plant and grow.

Is WaldJS klaar voor productie?Is WaldJS production-ready?

Nog niet helemaal β€” het framework is in actieve ontwikkeling. Fase 0 t/m 2b en 4a/4b zijn af; client-side hydration (fase 3) is onderweg. Voor statische sites zonder interactiviteit kun je vandaag al bouwen.Not quite yet β€” the framework is in active development. Phases 0 through 2b and 4a/4b are complete; client-side hydration (phase 3) is on its way. For static sites without interactivity you can build today.

Kan ik migreren vanaf Astro?Can I migrate from Astro?

De concepten lijken sterk op elkaar: frontmatter + template, file-based routing, content collections en getStaticPaths() werken vrijwel hetzelfde. Meestal is het hernoemen van .astro naar .wald en het aanpassen van imports naar wald:content het grootste werk.The concepts are very similar: frontmatter + template, file-based routing, content collections and getStaticPaths() work almost identically. Usually renaming .astro to .wald and updating imports to wald:content is the bulk of the work.

Werken mijn Vite-plugins?Do my Vite plugins work?

Ja β€” via het vite-blok in wald.config.ts gaat alles rechtstreeks naar Vite door, inclusief plugins en resolve-opties.Yes β€” the vite block in wald.config.ts passes everything straight through to Vite, including plugins and resolve options.

GroeidagboekGrowth log

Changelog

Elke release een jaarring. Dit is er tot nu toe gegroeid.Every release a growth ring. Here's what has grown so far.

v0.5.1

Forest Polish

juli 2026
  • Marketing-site opgefrist met een branded favicon en scherpere CTA-statesRefreshed the marketing site with a branded favicon and sharper CTA states
  • 3D-depth toegevoegd aan knoppen, kaarten, terminals en footerAdded 3D depth to buttons, cards, terminals and the footer
  • Dev-server serveert nu ook src/assets correct tijdens wald growThe dev server now correctly serves src/assets during wald grow
v0.6.0

Canopy

onder constructieunder construction 🚧
  • Client-side hydration β€” interactieve eilandjes in je statische bosClient-side hydration β€” interactive islands in your static forest
v0.5.0

Forest

juni 2026
  • wald.config.ts met outDir, base en Vite-passthroughwald.config.ts with outDir, base and Vite passthrough
  • Vite SSR build-pipeline + statische pre-renderVite SSR build pipeline + static pre-render
  • vite-plugin-wald
v0.4.0

Branches

mei 2026
  • Componenten β€” herbruikbare .wald-bestandenComponents β€” reusable .wald files
  • Layouts voor gedeelde paginastructuurLayouts for shared page structure
v0.3.0

Sapling

mei 2026
  • Content collections via wald:contentContent collections via wald:content
  • Dynamische routes met getStaticPaths()Dynamic routes with getStaticPaths()
v0.2.0

Seed

april 2026
  • CLI: plant, grow, build en previewCLI: plant, grow, build and preview
v0.1.0

Roots

april 2026
  • De compiler: parser + transform van .wald naar JS-modulesThe compiler: parser + transform from .wald to JS modules