New project
Onboarding (above) is for a project you already have. New project is for one that doesn't exist yet: a Lovable/v0-style arrival where you name what you're building, watch Potter draft a plan and a starter file tree, refine it in a chat, and watch the v1 land on disk — git initialised, ready to open.
Reach it from File ▸ New Project (⌃⌘N) or the Plan a new project card on the launcher. When no project is open, kiln rests on the launcher — a small, chrome-less home (LauncherView) rather than the full IDE shell — with two clear paths: plan something new, or open a folder you already have, plus your recent projects. It's where the app lands at first launch with nothing to restore, after Close Folder, and after you close the last project window — so closing a window no longer snaps the same project straight back (#close-shows-launcher).
The flow
Describe. Name it, say what it should be in a line or two, and confirm where it lives — ~/Developer by default, changeable with the folder picker. The folder name is slugged from the project name (My Cool App! → my-cool-app), and the flow refuses to build over a folder that already exists, so a new project never clobbers existing work.
Empty start. Don't want Potter to guess? Leave the description blank and skip the gallery: with nothing to plan from — just a name — the button reads Create empty project, and it bypasses the whole AI pass. Instead of asking the model to invent a stack, it seeds a sensible empty repo (a README titled with your project name and a broad, ecosystem-agnostic .gitignore), inits git with a first commit, and drops you straight on the done step. The fast path for "I just want somewhere to start."
Templates. The describe step opens onto a gallery of the things people most often start — marketing site, documentation site, to-do app, blog, portfolio, REST API, CLI tool, native macOS app, AI chat app — the way Logic Pro or v0 open onto starters rather than a blank box. A template is a seed, not a baked file tree: picking one fills the description, suggests a folder name (only when the field is still empty), and biases Potter's stack with a one-line hint — the same plan → review → build pipeline still runs, so there are no mini-repos to keep current and the hint never hard-constrains the result. Tapping the selected card again clears it; you can always ignore the gallery and describe your own.
Planning. Potter takes the description and streams its reasoning live — the "see the agent thinking" beat — while it picks a sensible, modern, minimal stack and sketches a manifest of the files it'll write: each a path and a one-line purpose, not the contents. Keeping the bytes out of this reply is what keeps it small. It prefers the top-tier cloud model (it writes better starter code), falling back to the free on-device model when that's all that's on. Changed your mind while it's thinking? Back to plan drops the in-flight re-plan and returns to the plan you were refining — so a tweak you started typing can be abandoned without losing the plan. (On the very first plan, when there's nothing to fall back to, the same button reads Cancel and returns to the form.)
Review. The plan lands as a summary of the stack it chose, the steps it's taking, and the manifest of files it wants to write, each with its purpose. Read it over and either build it as-is or tweak it in the composer — "use TypeScript", "add tests" — which re-plans carrying the whole conversation. A refinement is never a commitment: backing out of an in-flight re-plan returns you to the plan, and you can always build as-is without giving feedback at all. Start over drops back to the form.
Building. This is the second pass: Potter writes each planned file's contents in turn — one call per file — so however many files the project needs, no single reply has to carry them all and overflow the model's output ceiling (which used to cut the old all-in-one plan off mid-JSON, #595). The generated files land under the target folder (parent directories and all) only once they're all in hand, so a mid-build hiccup never leaves a half-written tree. Then the template's recommended skills are seeded with skills.sh (npx skills add <source> --all, fully non-interactive so the headless build never stalls on an agent-selection prompt), then git init plus a first commit — so the skills land in the first commit. Finally, the project's dependencies are installed so it's runnable the moment it opens: kiln reads the manifest the build just wrote and runs the matching package manager — npm install (or pnpm/yarn if a lockfile says so), pip install -r requirements.txt, cargo fetch, go mod download, swift package resolve, or bundle install. This runs after the first commit, so the installed tree (node_modules, .venv) never lands in it. The skills, git, and install are all best-effort: a missing npx, no network, a source that won't resolve, or a package manager that isn't on PATH is logged, not fatal — the project still opens, and DepsCheck nudges you to install if it didn't take. All of it runs off the main thread.
Skills
Each template can carry a couple of skills.sh skills worth having from day one — the docs site seeds mcclowes/skills-docusaurus, the web-facing templates seed Vercel's open web-design-guidelines and writing-guidelines. They show in the review step before you build, and install at build time via npx skills add, landing under .agents/skills/ with a skills-lock.json. Sources are curated owner/repo slugs (or single-skill owner/repo/skills/name catalog paths); every one passes a shell-safety gate (ProjectScaffold.isSafeSkillSource) before it's handed to the shell, so a source can never carry metacharacters or escape into a flag. Templates with no curated skill yet just skip the step.
Done. A celebratory beat — the kiln-ember glow, a success chime (the Cue seam), and the project's name — then Open project lands you in the new workspace.
Design
All the logic that can be wrong without a window is pure and tested in ProjectScaffold (Sources/kiln/NewProject/): slugging a name into a folder, the path-safety gate every scaffolded file passes before its bytes touch disk (no absolute, home-rooted, or .. paths), trimming and capping the plan's manifest (sanitizePlan) and the generated files (cappedFiles, which also enforces the byte cap), the lenient JSON parser that pulls the first balanced object out of a reply that may be wrapped in prose or a ```json fence, and fileContents, which unwraps a stray Markdown fence around a second-pass file. The split into two passes — a small manifest first (planSystem/planUser), then one file's contents at a time (fileSystem/fileUser) — is what stops a many-file project from blowing the model's output ceiling (#595). The template catalog is pure data in ProjectTemplate— each is an id, a card (title/blurb/icon), a description seed, astackHintthatplanUserfolds into the prompt between the summary and any refinements (so a later tweak always wins), and a list of skills.sh sources. The skill seeding's pure parts — the shell-safety gate and the human label — live inProjectScaffoldand are tested;NewProjectModel.installSkillsis the best-effortnpxwiring. The empty-start bypass is pure too —ProjectScaffold.isBlankBriefdecides when there's nothing to plan from, andgenericFiles/genericReadme/genericGitignoreproduce the seed pair, all tested without a window;NewProjectModel.seedGenericis the disk/git wiring that skips generation, skills, and deps entirely. The dependency-install command is inferred purely too —ProjectScaffold.installStep(forFiles:)reads only the root manifests in the written path set and returns the package manager to run (the same family as the reactiveJobFix/DepsCheck, just ahead of the failure); NewProjectModel.installDependenciesis the best-effort shell wiring.NewProjectModelis the live wiring onto Potter, the disk, andAppState; NewProjectViewis the sheet, a cousin ofOnboardingView.