dreego — Go Web Framework
SSR-first web framework and evolving Go-native application platform. Write
.dreego files, transpile to Go code, and deploy the current SSR target as a
single binary. File-based routing, built-in form handling, and compile-time
validation work without runtime template parsing.
<!-- www/routes/login/+page.dreego -->
<head><title>Dreego</title></head>
<server>
type LoginForm struct {
Email string `form:"email" validate:"required,email"`
}
func Login(c dreego.Context, form LoginForm) error {
c.SetSessionVal("user", form.Email)
return c.Redirect("/dashboard", 303)
}
</server>
<body>
<h1>Login</h1>
{#if c.Errors("email")}<p class="error">{{ c.Errors("email") }}</p>{/if}
<form g-action="Login" method="post">
<input name="email" type="email" value="{{ c.Old("email") }}">
<button type="submit">Login</button>
</form>
</body>
dreego new myapp && cd myapp && dreego generate && go run .
→ Getting Started
Philosophy
Dreego is a compile-time transpiler, not a runtime framework. .dreego files compile to standard Go code — no reflection-based routers, no runtime template parsing. Your app is a plain Go binary using net/http. See Benchmarks for measured code-generation and request performance.
Four principles:
- SSR-First — SSR is the production web foundation through v1. Future
targets remain separate from the stable core until real applications prove
their contracts.
- File-Based —
www/routes/+page.dreego and www/routes/index.dreego map to /. Other filenames become URL segments, and method-specific sections select HTTP methods.
- Type-Safe — Generated handlers and components use typed Go contracts; dynamic HTTP boundary data stays explicit.
- Accessibility-Aware Tooling — CLI output and diagnostics are designed for screen readers, and the scaffolded
web-minimal template ships a skip link and a <main> landmark. Applications still verify their own content and conformance.
Direction after v0.1
Dreego first stabilizes its typed SSR application and render model. Optional
client behavior and additional hosts are explored only after that baseline is
proven in real applications.
Root sections describe purpose while an optional lang selects the source
processor: server, head, body, style, and client. Go, HTML, CSS, and
JavaScript are the built-in defaults.
JavaScript remains the built-in, dependency-free client language. Markdown and
TypeScript are first-party processors. Browser Lua compiles through Dreego's
dependency-free first-party compiler and a generated feature-linked runtime.
See the public Roadmap and detailed
implementation plans.
Features
Core
- Transpiler Pipeline — Lexer → Parser → AST → CodeGen.
.dreego → Go code.
- File-based Routing —
www/routes/+page.dreego → GET /, www/routes/login/+page.dreego → GET /login (method via method="..." sections)
- Dynamic Segments —
[id] brackets for URL params, (group)/ for layout groups
- Single Binary —
go build → deploy one file. Zero runtime dependencies beyond net/http.
Template & Components
- Template Logic —
{{ value }}, {#if}...{#else}...{/if}, {#each items as item}...{#each else}...{/each}
- Template Helpers —
{{ $loop.Index }}, {{ value|raw }}, {{ value|upper }}, {#verbatim}
- Component System —
www/components/, <@Card title="x">...<\@Card>, named slots, scoped CSS
- Layout System —
www/layouts/default.dreego with {#slot} + {#head}
- CSS Scoping —
data-scope via source hash, automatically applied
- g-action Forms —
<form g-action="Login"> generates full handler pipeline
- Auto-Validation —
validate:"required,email,min=3" struct tags, no external deps
- Auto-Binding —
form:"email" struct tags → r.ParseForm() + reflection mapping
- Error Re-render —
c.Errors("email") and c.Old("email") available in templates after validation failure
- PRG Pattern —
c.Redirect(url, 303) with ErrRedirect sentinel for after-success redirect
API Endpoints (v0.0.15)
- Content-Type Routing —
<server type="json">, <server type="xml">, <server type="custom">
- JSON API —
c.JSON(200, data), c.Bind(&target), auto Content-Type: application/json
- XML API —
c.XML(200, data), auto Content-Type: application/xml
- Custom —
c.Write(status, contentType, body) for arbitrary formats
Middleware (v0.0.14, v0.0.20)
- Health Checks —
GET /health → 200, GET /ready → 200/503 via app.SetReady(bool)
- Security Headers — X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, Content-Security-Policy (configure via
app.SetCSP before build)
- Gzip Compression —
Accept-Encoding → compressed response wrapping
- Recovery — Panic → generic 500 response; internal details stay in server logs
- Request Logging — JSONL format with duration, IP, status
- Session — Cookie store via
app.SetSessionStore(), c.SetSessionVal()
- CSRF — Double-submit cookie, auto-validation on POST/PUT/DELETE, Secure flag TLS-aware
Developer Experience
- CLI —
dreego new [-t <template>] [-l], dreego task [args...], dreego generate [--force] [--check], dreego fmt [--check]
- CI Mode —
dreego generate --check exits non-zero when generated files are stale
- Auto-Imports — Required standard-library packages are added to generated code as needed
- Accessibility Checks —
dreego generate warns about missing image alternatives and unassociated form labels; CLI output is color-free and screen-reader-linear
Quick Start
Requires Go 1.27 or newer (go version). The dreego new command scaffolds a
project, writes a go.mod that requires the published dreego module, and
runs go mod tidy so the build resolves from the public Go proxy. No
repository-local replace directive is needed for a release-installed CLI.
# 1. Install the Dreego CLI
go install github.com/dreego-stack/dreego/cmd/dreego@latest
# 2. Scaffold a new project (writes go.mod, main.go, www/ tree, runs go mod tidy)
dreego new myapp
# 3. Generate Go code from .dreego files and run the server
cd myapp
dreego generate
go run .
# → http://localhost:8080
# or build for production
dreego build --target linux/amd64
main.go uses the explicit App API — no globals, no hidden state:
package main
import (
"log"
"os"
dreego "github.com/dreego-stack/dreego/core"
"github.com/dreego-stack/dreego/adapter/ssr"
"myapp/www"
)
const port = "8080"
func main() {
app := dreego.New()
if err := www.Register(app); err != nil {
log.Fatal(err)
}
addr := ":" + port
if p := os.Getenv("DREEGO_PORT"); p != "" {
addr = ":" + p
}
if err := ssr.Listen(app, addr); err != nil {
log.Fatal(err)
}
}
If dreego new cannot resolve the dreego dependency (e.g. no network, or the
CLI was built from an untagged checkout), set DREEGO_LOCAL_REPO=/path/to/dreego
to point the scaffold at a local checkout via a replace directive. This is a
developer escape hatch and is not part of the canonical path.
VS Code Extension
Syntax highlighting, snippets, and dreego.config.json validation for
.dreego files. Install via a symlinked clone — always up to date:
git clone --depth 1 https://github.com/dreego-stack/vscode-dreego ~/dev/vscode-dreego
cd ~/dev/vscode-dreego
./install.sh
Restart VS Code afterwards. Uninstall: ./install.sh uninstall in the same
directory. The install script links ~/.vscode/extensions/dreego to the
checkout, so use a permanent directory (not /tmp, which is cleared on
reboot). Source: https://github.com/dreego-stack/vscode-dreego
Architecture
A website lives in its own directory — any name, marked by a
dreego.config.json. dreego generate produces one dree.go per directory
with .dreego sources; the website root gets a Register(app) entry point:
www/ # website root (name is free, marker: dreego.config.json)
├── dreego.config.json # logging, redirects, rewrites
├── dree.go # GENERATED — package www, Register(app)
├── routes/ # .dreego files → URL routes
│ ├── +page.dreego → GET /
│ ├── login/
│ │ └── +page.dreego → GET /login (POST via method="post" section)
│ ├── [id]/+page.dreego → GET /{id}
│ └── dree.go # GENERATED — package routes, handlers + Register
├── layouts/
│ ├── default.dreego # {#slot} + {#head} wrapper
│ └── dree.go # GENERATED — package layouts
├── components/
│ ├── Card.dreego # <@Card title="x"/>
│ └── dree.go # GENERATED — package components
├── static/
│ └── style.css # inlined into binary
└── main.go # imports "myapp/www", calls www.Register(app)
Multiple websites can share one module — each directory with a
dreego.config.json is an independent website.
Plugins
Official plugins live in separate repos under github.com/dreego-stack/. Each plugin has its own go.mod and requires github.com/dreego-stack/dreego; Core stays dependency-free and never imports a plugin package.
Provider integrations such as Stripe, MapLibre, auth, storage, Tailwind, SSE,
and WebSockets remain external. The small first-party language set—Markdown,
TypeScript, and Lua—stays in the transpiler and may manage pinned tools after
explicit approval. The SSR host stays in the monorepo as part of the current
production baseline. Future hosts and client systems must first prove their
boundaries in working applications.
github.com/dreego-stack/
├── dreego/ # main repo (core + CLI, single module)
├── plugin-example/ # minimal example plugin
├── plugin-auth/ # future: OAuth2, JWT, sessions
├── plugin-db/ # future: SQL drivers, migrations
└── ...
→ Plugin System
Documentation
Getting Started
| Doc |
Topic |
_docs/index.md |
Documentation index and navigation |
_docs/getting-started.md |
Step-by-step tutorial |
_docs/file-anatomy.md |
Anatomy of a .dreego file |
_docs/cli.md |
CLI Reference |
_docs/config.md |
dreego.config.json |
Guides
| Doc |
Topic |
_docs/routing.md |
File-based routing, dynamic segments, content-type routing |
_docs/layouts.md |
Layouts, {#slot} and {#head} |
_docs/server-section.md |
Go declarations and route handlers |
_docs/head-section.md |
Metadata and layout head composition |
_docs/body-html.md |
HTML body templates and embedded processors |
_docs/markdown.md |
Markdown bodies and the <md> custom tag |
_docs/style-section.md |
Route CSS and component scoping |
_docs/client-javascript.md |
Built-in JavaScript client sections |
_docs/client-typescript.md |
TypeScript setup and generated JavaScript |
_docs/lua.md |
Browser Lua syntax, semantics, and exclusions |
_docs/middleware.md |
Health, security, compression, session, CSRF |
_docs/components.md |
Component system, slots, scoped CSS |
_docs/forms.md |
g-action forms, validation, redirects, error handling |
_docs/session-encryption.md |
AES-256-GCM encrypted session cookies |
_docs/progressive-enhancement.md |
HTMX, Alpine.js, plain JavaScript |
_docs/security.md |
Context-aware escaping, output safety |
_docs/accessibility.md |
Accessibility guarantees and template defaults |
Reference
| Doc |
Topic |
_docs/runtime.md |
Practical guide to the main Go runtime APIs |
_docs/plugin-interfaces.md |
Plugin interface contracts |
_docs/plugins.md |
Plugin model, middleware and route hooks |
_docs/compatibility.md |
Breaking-change policy and the v0.1 promise |
_docs/roadmap.md |
Product direction and release phases |
_plan/README.md |
Detailed phased architecture and implementation guidance |
Testing & Ops
| Doc |
Topic |
_docs/testing.md |
Integration test strategy |
_docs/benchmarks.md |
Code generation and request benchmarks |
_docs/reference-apps.md |
Reference applications under _tests/fixtures/ |
_docs/dev-server.md |
dreego dev watcher and auto-reload |
_docs/hot-reload.md |
Hot reload with Air (.air.toml config) |
_docs/deployment.md |
Build, cross-compile, containers |
Contributing
See CONTRIBUTING.md for the PR workflow, commit
conventions, and local development setup.
License
MPL-2.0