PROJECT SCAFFOLDING
One source → an entire project tree¶
A single .capy source file can scaffold a complete project — web
app, Android app, iOS app, ML training code, full Python service.
Same engine, vastly different artifacts. Add --zip to bundle
the tree into a single archive.
📱 Mobile — same source, two platforms¶
The same source declaration produces a working Android skeleton and an iOS SwiftUI skeleton. Each library encodes its platform's conventions (Kotlin/SwiftUI idioms, manifest formats, build configs); the source stays platform-agnostic.
The whole declaration:
app "Habit Tracker"
package "com.example.habits"
min_sdk 24
screen Home "Today's habits"
screen History "Past 30 days"
feature Home "Daily checklist"
feature Home "Streak counter"
feature Home "Reset day"
feature History "Calendar view"
feature History "Per-habit stats"
end
The Android library encodes Kotlin source layout, AndroidManifest.xml, gradle build, fragment scaffolding. The iOS library encodes SwiftUI App/View structure, Info.plist, SPM manifest.
Add a screen line, regenerate, both platforms update.
The phone above runs the same idea as a single-page web app
(generated by samples/webapp-trio/) so you can interact with it.
The Android + iOS samples generate native code with the same screens
and features.
🌐 Web app — 12 lines of DSL → 3-file browser-ready app¶
app "Habit Tracker"
description "A tiny daily-habit tracker that persists to localStorage."
color_primary "#4f46e5"
color_bg "#0f172a"
habit drink_water "Drink 8 glasses of water"
habit read "Read 20 pages"
habit walk "30 min walk"
habit code "Practice coding"
habit meditate "Meditate 10 min"
end
Three files, properly cross-referenced:
📁 out/
├ index.html // links to styles.css + app.js
├ app.js // localStorage persistence + streak counter
└ styles.css // themed by source variables
- localStorage persistence baked in by the library
- Streak counter computed across consecutive days
- Theme variables pulled from
color_primary/color_bg - Cross-references wired correctly — the
<link>and<script src>point at sibling files
🧪 Backend — handler + test code from one declaration¶
Every handler line generates two things: the Go stub and the
smoke test. The team's directory layout and the "every handler has a
test" rule are mechanically enforced.
Source:
handler ListUsers method GET path "/users" returns "[]User"
handler GetUser method GET path "/users/{id}" returns "User"
handler CreateUser method POST path "/users" accepts "UserCreateRequest" returns "User"
handler DeleteUser method DELETE path "/users/{id}" returns "void"
Generated tree:
📁 internal/handlers/
├ handlers.go // router + 4 stubs (501)
└ handlers_test.go // 4 Test_X_RouteRegistered
README.md // auto-generated route catalog
$ go test ./... ok example/handlers 0.448s $ go test -v ./... === RUN Test_ListUsers_RouteRegistered --- PASS: Test_ListUsers_RouteRegistered (0.00s) === RUN Test_GetUser_RouteRegistered --- PASS: Test_GetUser_RouteRegistered (0.00s) === RUN Test_CreateUser_RouteRegistered --- PASS: Test_CreateUser_RouteRegistered (0.00s) === RUN Test_DeleteUser_RouteRegistered --- PASS: Test_DeleteUser_RouteRegistered (0.00s) PASS ok example/handlers 0.448s
The generated tests actually pass. Verified.
🧠 ML training — declarative architecture → native libtorch C++¶
model "MNIST classifier"
dataset MNIST
batch_size 64
epochs 10
learning_rate 0.001
optimizer adam
layer conv2d in 1 out 32 kernel 3
layer relu
layer maxpool kernel 2
layer conv2d in 32 out 64 kernel 3
layer relu
layer maxpool kernel 2
layer flatten
layer linear in 1600 out 128
layer relu
layer linear in 128 out 10
end
17 lines → native code that compiles to a CUDA-enabled trainer.
📁 out/
├ CMakeLists.txt // finds libtorch, links targets
├ run.sh // configure + build + run
└ src/
├ model.h // torch::nn::Module with register_module + forward
└ main.cpp // training loop with optimizer + checkpoints
The same architecture declaration could target PyTorch Python, Keras, ONNX, or TFLite — write a new library, keep the source.
🐍 Multi-file Python service — 9 lines, 6 files¶
A REST API declaration produces a complete FastAPI project:
project "todo-api"
description "A tiny TODO REST service"
author "you@example.com"
route GET "/health" health_check
route GET "/todos" list_todos
route POST "/todos" create_todo
route GET "/todos/{id}" get_todo
route DELETE "/todos/{id}" delete_todo
end
📁 generated/
├ README.md
├ pyproject.toml // fastapi + uvicorn deps
├ .gitignore
├ src/
├ main.py // FastAPI app with 5 routes mounted
└ handlers.py // handler stubs ready to implement
└ tests/
└ test_smoke.py // route-mount tests
How it works¶
# Write the source to a tree of file blocks declared in the library
capy run --out-dir generated lib.capy script.capy
# OR bundle the whole tree as a zip for delivery
capy run --zip project.zip lib.capy script.capy
The library has one file "..." ... end block per output file. File
paths support the same ${...} interpolation as write literals — so
you can name outputs dynamically (file "${name | pascalCase | unquote}Page.tsx" ... end).