Scaffold the storefront
This is chapter 1 of the storefront track. Before you can sell anything you need a workspace on disk
and a running system to grow it in. In this chapter you create my-shop/ with the netscript CLI,
tour what it generated, and bring the whole thing up under Aspire — Postgres,
the Redis cache, and an example service all running together behind one dashboard.
- 1 · Scaffold
- 2 · Catalog service
- 3 · Cart contracts
- 4 · Checkout saga
- 5 · Shipping webhook
- 6 · Deploy
What you will build
By the end of this chapter you will have a real NetScript workspace named my-shop/ on disk — with a
shared contracts/ workspace, a products service, a Fresh app, and a Postgres database — and you
will have watched it boot under a single aspire start, with the Aspire dashboard live on
http://localhost:18888 and Postgres plus Redis reporting healthy.
Before you begin
This is the first chapter, so the only prerequisites are a working local toolchain. You need:
- Deno 2.x on your
PATH— check withdeno --version. - The Aspire CLI — check with
aspire --version. NetScript uses Aspire to provision your database and cache locally, so you never wire up Docker containers by hand. - Docker running, so Aspire can start the Postgres and Redis containers. Confirm with
docker info— it should print engine details, not a connection error.
Install the NetScript CLI from JSR once:
deno install --global --allow-all --name netscript jsr:@netscript/cli@0.0.1-alpha.12
Confirm it resolves and inspect the command groups:
netscript --help
You should see the public groups: init, contract, db, deploy, generate, marketplace,
plugin, service, ui:add, and ui:init. If netscript is not found, make sure Deno's install
directory (printed by deno install) is on your PATH, then open a fresh terminal.
Step 1 — Preview the scaffold with a dry run
Before writing any files, ask the CLI what it would create. --dry-run plans the scaffold and
prints the result without touching disk:
netscript init my-shop --dry-run
netscript init validates your options, then runs an ordered pipeline that lays down the project
root, Aspire orchestration, the shared contracts workspace, a Fresh app, an empty plugin registry,
and — when you ask for them — a database workspace and an example service. The dry run reports file
and directory totals per phase, so you can see the project's shape before committing to it. A clean
dry run is your green light to scaffold for real.
Step 2 — Create the workspace
Scaffold my-shop/ with an example service named products on port 3001 and a Postgres
database, so you have something real to run and a place for the catalog you build next chapter:
netscript init my-shop --service --service-name products --service-port 3001 --db postgres
cd my-shop
This scaffolds my-shop/, formats the output with deno fmt, and initializes a git repository. On
completion the CLI prints a next steps summary tailored to your options — keep it handy; the
steps below mirror the common path.
This track uses Postgres, but the database is polyglot: swap --db postgres for mysql, mssql, or
sqlite and the scaffold wires Prisma for that engine instead (sqlite is file-backed, with no Aspire
container). Keep --db postgres to follow along.
A few init options you will reach for (run netscript init --help for the full list):
| Name | Type | Description |
|---|---|---|
--service --service-name |
flag group |
Include an example oRPC service on the given port. We use products on 3001. |
--db |
flag |
Scaffold a Prisma-backed database workspace. First-class engines: postgres (default for this track), mysql, mssql, sqlite. Omit or use --db none to skip database tooling. |
--no-aspire |
flag |
Skip the Aspire orchestration files — you would then wire infrastructure yourself. Do NOT pass this for the track; we rely on aspire start. |
--editor |
flag |
Generate editor settings for the chosen editor. |
--dry-run |
flag |
Plan the scaffold and print totals without writing any files. |
Step 3 — Tour what you got
Open my-shop/ and you will find this shape:
-
my-shop/
- apps/dashboard/ # Fresh frontend (defineFreshApp)
- contracts/ # Shared oRPC contracts, versioned under versions/v1/
- services/products/ # The example oRPC service (src/main.ts, router.ts, routers/)
- plugins/ # Plugin registry + manifests — empty until chapter 4
-
aspire/
- apphost.mts # Entry point for aspire start
- aspire.config.json # AppHost language + SDK pin
- appsettings.json # Infrastructure config (Services / Databases / Persistent)
- deno.json # Workspace root (members, tasks, dependency catalog)
- netscript.config.ts # Framework config (defineConfig)
What each piece is for:
contracts/— the typed seam between your services and any client. Contracts are oRPC + Zod, versioned underversions/v1/. Everything else derives its types from here. You add the cart contract here in chapter 3. See Contracts & type flow.services/products/— a working oRPC service.src/main.tscallsdefineService(...); handlers live undersrc/routers/. You make it a real catalog in chapter 2.apps/dashboard/— a Fresh app for your storefront UI, already wired to consume contracts. The@netscript/freshmeta-framework powers it. This track stays on the backend, so you will not edit it.plugins/— where background capabilities (workers, sagas, triggers, streams) register. Empty until you add the sagas plugin in chapter 4.aspire/— the orchestrator.aspire startreadsapphost.mtsand starts every resource your app declares — Postgres, the Redis cache, your services — with one command.appsettings.json— the infrastructure manifest Aspire reads: which services, databases, and persistent resources to provision.netscript.config.ts— declares paths, plugins, logging, and database wiring viadefineConfig. See the config reference.
Step 4 — Bring up orchestration
This is the step that turns a folder of files into a running system — and the one most people miss.
Aspire provisions your database and cache; you do not start containers by hand, and you run it
before any netscript db command. Run it from the aspire/ subfolder so the CLI finds
apphost.mts:
cd aspire
aspire restore # once per machine: restores the Aspire SDK modules into .aspire/
aspire start # starts the AppHost and every declared resource
aspire start brings up the Postgres database, the Redis cache, and your products service
together, then prints a URL and a one-time login token for the Aspire dashboard:
http://localhost:18888
The dashboard lists every resource (postgres, redis, your service), live console logs, and
distributed traces. Leave aspire start running in this terminal — it is your storefront's control
plane for the rest of the track.
Verify your progress
The example products service exposes a plain health endpoint. In a second terminal — leave
aspire start going in the first — confirm the service answers on port 3001:
curl http://localhost:3001/health
You should get a healthy JSON response. Then type-check the whole workspace from the project root to confirm the scaffold, contracts, and service all line up:
deno task check
A clean check, plus a healthy curl, means the scaffold is sound.
- [ ]
netscript --helplists the public command groups. - [ ]
my-shop/exists withcontracts/,services/products/, andaspire/. - [ ]
aspire startis up; the dashboard athttp://localhost:18888showspostgresandredishealthy. - [ ]
curl http://localhost:3001/healthreturns healthy JSON. - [ ]
deno task checkpasses with no errors.
What you built
A real NetScript workspace, my-shop/: a shared contracts/ workspace, a products service, a
Fresh app, and a Postgres database plus Redis cache — all orchestrated by Aspire and visible in one
dashboard. Next, you turn that placeholder products service into a real, typed catalog.