The WFL website — written in WFL, powered by Scriptorium.
This is the marketing + docs site for WFL, the WebFirst Language,
and it is written in WFL end to end. It runs on the
Scriptorium CMS engine
(vendored into this repo): one WFL web server opens a SQLite database, serves the
public site, and hosts a login-protected /admin panel. Pages are rendered with
the Scribe templating engine, code
samples are colored by a WFL-native syntax highlighter, and the whole thing wears
the WFL Design System (dark, teal-on-Ink).
Programming that reads like plain English — including the program that serves this page, stores its News posts, and runs its playground.
You need the wfl CLI (build it with
cargo build --release). Then, from the repository root (template and asset
paths resolve relative to the working directory):
wfl main.wfl # or: scripts/run.shOn first run it creates scriptorium.db, seeds default settings, prints a
one-time admin password, and seeds a few launch News posts:
==================================================
wfl-web — first run: seeded an admin account
username: admin
password: <generated-password> # a fresh random value is printed here
(shown once — sign in at /admin and add users under Users)
==================================================
wfl-web — seeded 3 launch News posts.
wfl-web (powered by Scriptorium) is running at http://127.0.0.1:8080 (admin: /admin)
Open http://127.0.0.1:8080/ for the site and http://127.0.0.1:8080/admin to
sign in. Bind address, TLS, and the body-size cap live in .wflcfg; the server
listens on 127.0.0.1:8080 by default (set web_server_bind_address = 0.0.0.0
to expose it behind a reverse proxy).
The site is a hybrid: rich, hand-authored pages for the marketing/docs surface, and genuine CMS content for anything that changes over time.
- Rich pages are HTML, not markdown, so they stay custom routes rendered from
this repo's own templates via
lib/site.wflandlib/playground.wfl: the landing page (hero, language compare, feature grid, error showcase), the getting-started docs page, the live playground, and the 404. - The News section is Scriptorium CMS content — SQLite-backed posts, authored
and edited in
/admin, served at/newsand/post/:slug. It's the same blog engine Scriptorium ships; here it powers project announcements.
Both surfaces render through the same templates/base.html, so News and the
marketing pages share one nav, footer, and design system — they never look like
two different sites.
base.html follows the Scriptorium section‑assembly model: a page is
assembled from sections, in order — a header
(templates/sections/header.html, site identity + navbar), a body
(<main class="site-body">, the per‑page content), and a footer
(templates/sections/footer.html). base.html is the assembler; the header and
footer sections are reused on every page. The full contract lives in the
Scriptorium repo at docs/THEMING.md;
wfl-web is a hand-styled conformant theme.
| Method | Path | What |
|---|---|---|
| GET | / |
Landing page (hero, compare, features, errors, install) |
| GET | /getting-started |
Getting-started docs |
| GET/POST | /playground |
The live playground (see below); POST runs a tool |
| GET | /news · /news/page/:n |
News feed (paginated) |
| GET | /post/:slug |
A published News post |
| GET | /page/:slug |
A published CMS page |
| GET | /assets/* |
Static files (design system, uploads) → static/ |
| GET/POST | /admin/login · /admin/logout |
Auth |
| GET | /admin |
Dashboard |
| GET/POST | /admin/posts… · /admin/pages… · /admin/media… |
Content CRUD |
| GET/POST | /admin/users… · /admin/settings |
Users & settings (admin only) |
| — | (any miss) | Rich 404 |
Every admin POST carries the session's CSRF token; the public playground POST is outside that gate (it's a public form, not an admin action).
/playground is a page about WFL that is running WFL on every request:
- Three real programs execute on each load.
playground/examples/*.wfl(FizzBuzz, Fibonacci, primes) are read, highlighted, and run withexecute wfl file … and read output— the output you see is whatever the program just displayed, computed at request time. A broken example can't take the server down;execute wfl fileturns its error into a catchable one. - Interactive tools compute on your input, server-side, with the standard
library: WFLHASH-256 + SHA-256 (crypto), text stats (length, words,
uppercase, reverse), and email validation with the readable pattern engine.
You submit a form; WFL parses it (
parse_form_urlencoded), computes, and re-renders the page with the answer.
The whole app loads through a single include in main.wfl. WFL analyses each
included file against the scope that exists when it is included, and rejects a
call to an action an earlier include already executed — so the modules form one
linear spine, each pulling in its own dependencies exactly once (no shared
dependency is included from two branches, which WFL would treat as a
redefinition):
main.wfl
└─ lib/playground.wfl # live playground: run examples + compute on input
└─ lib/site.wfl # marketing content, routing, code samples
├─ app/render.wfl # Scriptorium engine …
│ ├─ auth.wfl # sessions, CSRF, roles
│ │ └─ db.wfl # SQLite schema + queries
│ │ └─ util.wfl # slugify, to_int, field_or, …
│ └─ lib/scribe.wfl # Scribe templating engine (vendored)
├─ lib/highlight.wfl # WFL → highlighted HTML
└─ lib/icons.wfl # inline Lucide-style SVG icons
The templates use Scribe's Twig-style syntax: {% extends %} / {% block %}
inheritance from templates/base.html, {% include %} for the header and footer
sections, {% for %} loops, the markdown filter for post/page bodies, and
{{ value | raw }} to emit trusted, pre-highlighted code HTML.
Note. WFL's static checker prints non-fatal
Undefined action …/could not infer typenotes to stderr for cross-file calls resolved at runtime. The program still runs and serves — this is expected.
- Marketing copy & structure —
templates/index.html,templates/getting-started.html,templates/404.html, and the shared shelltemplates/base.html+templates/sections/{header,footer}.html. Nav links, feature cards, footer columns, and code samples are plain WFL maps/lists inlib/site.wfl. - News — write and edit posts in
/admin/posts. The feed and article templates aretemplates/news_index.htmlandtemplates/news_post.html; standalone CMS pages usetemplates/cms_page.html. - Design tokens (colors, type, spacing, effects, syntax) — under
static/ds/(taken verbatim from the WFL Design System). Site-specific layout and the component ports (buttons, cards, callouts, badges, code blocks) live instatic/site.css; admin styling instatic/admin.css. Every value references a design-system token.
The brand is dark, teal-on-Ink, code-forward.
| Token | Value | Role |
|---|---|---|
| Ink | #10221F |
background (--surface-base) |
| Mist | #F5FAF8 |
text (--text-primary) |
| Verdant Teal | #12A594 |
primary accent (--accent) |
| Deep Teal | #0B7A6E |
pressed accent |
| Warm Amber | #F2A73B |
highlight + code strings |
Type: Alegreya (display serif, self-hosted), Hanken Grotesk (body/UI),
JetBrains Mono (code). The logo mark (static/ds/assets/wfl-mark.svg) is an
outlined teal speech bubble with a chevron prompt and a leaf cursor.
wfl-web/
├── main.wfl # boot (DB open, migrate, seed) + request loop + router
├── .wflcfg # WFL runtime config (bind address, TLS, body-size cap)
├── app/ # Scriptorium engine (vendored)
│ ├── util.wfl · db.wfl · auth.wfl · render.wfl
├── lib/
│ ├── site.wfl # marketing content, routing, code samples
│ ├── playground.wfl # live playground: run examples + compute on input
│ ├── scribe.wfl # Scribe templating engine (vendored)
│ ├── highlight.wfl # WFL-native syntax highlighter
│ └── icons.wfl # inline SVG icon set
├── playground/examples/ # real .wfl programs the server runs live
│ └── fizzbuzz.wfl · fibonacci.wfl · primes.wfl
├── templates/ # public site (assembled through base.html)
│ ├── base.html · index.html · getting-started.html · playground.html · 404.html
│ ├── news_index.html · news_post.html · cms_page.html
│ └── sections/{header,footer}.html # reusable section library
├── admin/templates/ # admin panel (Scriptorium)
├── static/ # served at /assets/*
│ ├── ds/ # WFL Design System: tokens, fonts, logo
│ ├── site.css · admin.css # site + admin styling
│ └── uploads/ # uploaded media (runtime)
├── TestPrograms/ # engine test suites (wfl --test)
└── scripts/run.sh
wfl --test TestPrograms/util.test.wfl # helpers (slugify, file_ext, parsing, …)
wfl --test TestPrograms/db.test.wfl # data layer against sqlite::memory:
wfl --test TestPrograms/auth.test.wfl # sessions + CSRF token checksApache-2.0. See LICENSE. WFL, the Scriptorium engine, and the Scribe engine are Apache-2.0; the WFL Design System and brand assets are © Logbie LLC.