Skip to main content
Alpha

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. 1 · Scaffold
  2. 2 · Catalog service
  3. 3 · Cart contracts
  4. 4 · Checkout saga
  5. 5 · Shipping webhook
  6. 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 with deno --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):

Common netscript init options
NameTypeDescription
--service --service-name --service-port 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 under versions/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.ts calls defineService(...); handlers live under src/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/fresh meta-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 start reads apphost.mts and 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 via defineConfig. 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 --help lists the public command groups.
  • [ ] my-shop/ exists with contracts/, services/products/, and aspire/.
  • [ ] aspire start is up; the dashboard at http://localhost:18888 shows postgres and redis healthy.
  • [ ] curl http://localhost:3001/health returns healthy JSON.
  • [ ] deno task check passes 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.