# Description of Changes
Adds `tools/templates/` scripts to derive template metadata from
manifests and generate READMEs from quickstart docs. Replaces slug-based
`builtWith` with manifest-derived data and hardcoded quickstart mappings
with discovery from docs.
**Manifest-based `builtWith`** (`update-template-jsons.ts`)
- Reads `package.json`, `Cargo.toml`, and `.csproj` to populate
`builtWith` in `.template.json`.
- Scoped npm packages normalize to scope (`@angular/core` → `angular`).
Excludes `@types/*`. Adds `nodejs` only for nodejs-ts when `@types/node`
is present.
- Root manifests processed before subdirs; primary framework first (e.g.
`react` before `spacetimedb` in react-ts). Dependencies reordered in
package.json where needed.
**Dynamic quickstart discovery** (`generate-template-readmes.ts`)
- Discovers template → quickstart by parsing `--template X` from files
in `docs/docs/00100-intro/00200-quickstarts/`.
- Optional `quickstart` override in `.template.json`; must resolve under
quickstarts dir.
- chat-react-ts has no quickstart; uses manual README.
**New:** `tools/templates/` (update-template-jsons.ts,
generate-template-readmes.ts, README, package.json, pnpm-lock).
**Modified:** all `templates/*/.template.json` (added `builtWith`),
new/generated `templates/*/README.md`.
# API and ABI breaking changes
None.
# Expected complexity level and risk
**1** – Dev tooling only. No runtime or API changes. Scripts are
isolated; failures only affect generated metadata and READMEs.
# Testing
- [ ] `cd tools/templates && pnpm run generate` completes without errors
- [ ] Spot-check `builtWith` and generated READMEs for a few templates
This pull request updates the template system to support richer metadata
and improves the interactive CLI experience for selecting templates. The
main changes are the addition of a `client_framework` field to template
metadata, a refactor of the templates JSON generation and parsing, and a
redesign of the interactive template selection flow to group templates
by language/framework and use fuzzy search for easier navigation.
<img width="407" height="409" alt="image"
src="https://github.com/user-attachments/assets/d3548505-80e8-4778-8bfb-71d5e3fe31e9"
/>
**Template Metadata and Serialization Improvements:**
* Added a new `client_framework` field to all template metadata files
(e.g., `.template.json`) and updated the Rust structs (`TemplateInfo`,
`TemplateDefinition`, etc.) to support this field, enabling more
descriptive and flexible template selection.
[[1]](diffhunk://#diff-5438edbe7b41e3e0a1a62ce0ebde2a833a0441d76c6ffdf16093a3cff258f462R3)
[[2]](diffhunk://#diff-34a44755a07373e9c2872db87a64c3fd752cfee7d8d536045909daf861ea4728R3)
[[3]](diffhunk://#diff-a826c5a2eac977cff44022d72856ec4b1af176ffbb50697f22857e1e3d478aa1R3)
[[4]](diffhunk://#diff-7a21474fbc5bbbd989e89f32aa8dcc25fcc6fe4ac43d418c42b2b38603d21714R3)
[[5]](diffhunk://#diff-d8ee9fd0ef15ed23f0f7f38e556d789bdefc6c37dab67fbfccebc513b9da871cR3)
[[6]](diffhunk://#diff-7224fd4300f9c5af7834ff5989a76a399ce9117c28f5d7e2c1fbd6bdaf45be1bR3)
[[7]](diffhunk://#diff-8b015b0ce6339c444ef5ef4dc5e862275d98967e5c189da37b51bdaa58443606R3)
[[8]](diffhunk://#diff-89e32f7fc9fc42863998d7651bc7fa1fdfb352e8ac3ef45792e3f1374052c9ddR3)
[[9]](diffhunk://#diff-8259d300fda149c968a68989aec2bc2afa479aded649ac6b8d3c4b277f610542R3)
[[10]](diffhunk://#diff-bb8b9202e51fb7038efa2f2bb23872afa02caf71ab3a0fb7f513ca7822c1b8faR3)
[[11]](diffhunk://#diff-18497b72a2306fc2560475e2548cfe1b96b6206c395380437ba1fafefd66e126L199-R221)
[[12]](diffhunk://#diff-18497b72a2306fc2560475e2548cfe1b96b6206c395380437ba1fafefd66e126R279)
* Refactored the templates JSON generation to use `serde` for
serialization, replacing manual string building, and ensured that
optional string fields serialize as empty strings when not present.
**CLI Interactive Template Selection Redesign:**
* Removed the previous "highlights" concept and reworked the interactive
selection to group templates by language/framework combinations, showing
counts and using fuzzy search for easier filtering.
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL38-L48)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL772-R833)
[[3]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL813-L850)
* Updated the selection menus to allow users to pick a
language/framework group, then choose from multiple templates if
available, or opt to clone from GitHub or select "None."
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL772-R833)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL813-L850)
* Improved language label formatting for better user experience in the
CLI prompt.
**Codebase Cleanup and API Changes:**
* Removed unused highlight-related structs and logic from the CLI,
simplifying the template fetching API to return only templates.
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL38-L48)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL198-R198)
* Updated all template selection logic to use the new API and data
structures.
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL683-R679)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL748-R744)
These changes make template selection more intuitive and scalable as
more templates and frameworks are added.
---------
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
## Summary
Multiple fixes and improvements to `spacetime dev`, `spacetime publish`,
`spacetime init`, and templates:
### CLI fixes
- **Fix `spacetime dev` watch path and .env.local handling** for
templates with a `spacetimedb/` subdirectory
- **Validate package manager availability** before installing
dependencies — re-prompts if the selected PM isn't on PATH
- **Remove JS/TS beta warning** from `spacetime publish`
- **Remove unstable warning** from `spacetime init`
- **Remove unused `spacetime energy` command** (can be re-added later
when properly implemented)
- **Fix `tsc` detection on Windows** — `set_extension(".cmd")` produced
`tsc..cmd` (double dot); fixed to `set_extension("cmd")`
- **Add `typescript` as devDependency** to all server template
`spacetimedb/package.json` files so `tsc` is available during build
- **Strip `\?\` extended-length path prefix** from user-facing output in
both `dev` and `publish` commands (produced by `fs::canonicalize()` on
Windows)
- **Fix publish reporting success when user declines** non-local server
prompt — changed `return Ok(())` to `bail!()` consistent with other
abort cases
- **Forward stdin to client process** in `spacetime dev` so interactive
CLI templates work
### Template fixes
- **Fix Angular template environment variables** — Angular's esbuild
builder doesn't support `import.meta.env`, so we use a dev script to
generate `environment.local.ts` with Angular's native `fileReplacements`
pattern
- **Fix TanStack Start template** — rename `createRouter` to `getRouter`
(v1.121+ breaking change), upgrade to React 19, and add
`@vitejs/plugin-react` for automatic JSX runtime support
- **Fix `moduleResolution` in remix-ts and nextjs-ts** server tsconfigs
— change from `"node"` to `"bundler"` to support subpath exports like
`spacetimedb/server`
- **Fix browser-ts template** — convert from static HTML + IIFE bundle
to standard Vite dev server app so it works with `spacetime dev` and
reads env vars from `.env.local`
- **Add `deno` as devDependency** to deno-ts template (matches how
bun-ts includes bun)
- **Convert basic-ts from empty web app to CLI app** matching basic-rs —
connect, subscribe to person table, print on insert
## Test plan
- [x] `cargo test -p spacetimedb-cli` — all 133 tests pass
- [ ] `spacetime dev --template angular-ts` — verify Angular app
connects with correct database name
- [ ] `spacetime dev --template react-ts` — verify React template still
works
- [ ] `spacetime dev --template tanstack-ts` — verify TanStack Start
template loads without errors
- [ ] `spacetime dev --template remix-ts` — verify Remix template builds
and runs
- [ ] `spacetime dev --template nextjs-ts` — verify Next.js template
still works
- [ ] `spacetime dev --template browser-ts` — verify Vite dev server
starts and app connects
- [ ] `spacetime dev --template bun-ts` — verify Bun CLI template runs
interactively
- [ ] `spacetime dev --template basic-ts` — verify CLI connects and
prints on insert
- [ ] Verify no `\?\` prefix in any displayed paths on Windows
- [ ] Verify no `tsc not found` warning when building server modules
- [ ] Select unavailable package manager at init prompt — verify
re-prompt
- [ ] Decline non-local server prompt — verify clean error instead of
"Published successfully!"
---------
Co-authored-by: Piotr Sarnacki <drogus@gmail.com>
Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
# Description of Changes
`spacetime build` now attempts to run tsc for typescript modules, and
will emit a warning if it's not present. This PR makes it so our CLI
stops emitting a warning for our templates.
# Expected complexity level and risk
1
# Testing
- [x] Verified that typescript gets properly installed.
# Description of Changes
- Node.js: Use esbuild instead of tsx
- Node.js: Remove interactive CLI since it doesn't work with `spacetime
dev`
- Next.js: Fix onError callback to use single argument (ctx) and use
ctx.event for the error.
- Next.js: Replace lint-disable comment with `_connection` for the
unused variable.
- Updated quickstart docs to use proper `withDatabaseName`
# API and ABI breaking changes
None.
# Expected complexity level and risk
**Complexity: 1–2.** Small tooling, type, and lint tweaks. Low risk.
# Testing
- [ ] Build affected templates (e.g. `pnpm build` in nextjs-ts).
- [ ] Lint passes.
# Description of Changes
- Quickstart templates: use workspace:* for spacetimedb instead of 1.*
so in-repo dev uses the local SDK.
# API and ABI breaking changes
None.
# Expected complexity level and risk
1. Template and workspace config only.
# Testing
- [ ] `pnpm install` from repo root; `spacetime dev --no-config` from a
template.
- [ ] `spacetime init` in a new dir; generated project has versioned
`spacetimedb`, not `workspace:*`.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
# Description of Changes
- Add back `{ public: true }` to tables, update `module_bindings`
accordingly
- Add missing templates to `pnpm-workspace.yaml`
<!-- Please describe your change, mention any related tickets, and so on
here. -->
# API and ABI breaking changes
<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->
# Expected complexity level and risk
<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.
This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.
If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->
# Testing
<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->
- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
---------
Co-authored-by: bradleyshep <148254416+bradleyshep@users.noreply.github.com>
# Description of Changes
Fix `withModuleName` -> `withDatabaseName` in server-side code across
multiple TypeScript templates. The 2.0 SDK renamed this method, but
several templates still used the old 1.x API name, causing a runtime
error (`DbConnection.builder(...).withUri(...).withModuleName is not a
function`).
**Files changed:**
- `templates/nuxt-ts/server/api/people.get.ts`
- `templates/remix-ts/app/lib/spacetimedb.server.ts`
- `templates/nextjs-ts/lib/spacetimedb-server.ts`
- `templates/nodejs-ts/src/main.ts`
- `templates/deno-ts/src/main.ts`
- `templates/keynote-2/src/connectors/spacetimedb.ts`
# API and ABI breaking changes
None. This aligns templates with the existing 2.0 SDK API.
# Expected complexity level and risk
1 — Trivial string replacement across template files. No logic changes.
# Testing
- [ ] Run `spacetime dev --template nuxt-ts` and verify the Nuxt SSR
server API (`/api/people`) connects without `withModuleName is not a
function` error
- [ ] Run `spacetime dev --template nextjs-ts` and verify the
server-side SpacetimeDB connection works
- [ ] Run `spacetime dev --template remix-ts` and verify the server-side
SpacetimeDB connection works
# Description of Changes
All types are now defined and exported in `module_bindings/types.ts`,
meanings there's only one module you need to import from to access
types.
# Expected complexity level and risk
2
# Testing
n/a, no change in behavior.
# Description of Changes
Basic tests for templates, the test tries to generate each of the
template, build and publish the SpacetimeDB part, and build or type
check the client side.
This PR also includes bindings for all of the clients as it's needed for
the tests to work and given the choices to either generate during the
test run or include the bindings in git we chose the latter. This makes
it consistent across the templates as some of them already included
bindings.
# Expected complexity level and risk
1
---------
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: rekhoff <r.ekhoff@clockworklabs.io>
# Description of Changes
This PR implements support for the `spacetime.json` configuration file
that can be used to set up common `generate` and `publish` targets. An
example of `spacetime.json` could look like this:
```
{
"dev_run": "pnpm dev",
"generate": [
{ "out-dir": "./foobar", "module-path": "region-module", "language": "c-sharp" },
{ "out-dir": "./global", "module-path": "global-module", "language": "c-sharp" },
],
"publish": {
"database": "bitcraft",
"module-path": "spacetimedb",
"server": "local",
"children": [
{ "database": "region-1", "module-path": "region-module", server: "local" },
{ "database": "region-2", "module-path": "region-module", server: "local" }
]
}
}
```
With this config, running `spacetime generate` without any arguments
would generate bindings for two targets: `region-module` and
`global-module`. `spacetime publish` without any arguments would publish
three modules, starting from the parent: `bitcraft`, `region-1`, and
`region-2`. On top of that, the command `pnpm dev` would be executed
when using `spacetime dev`.
It is also possible to pass additional command line arguments when
calling the `publish` and `generate` commands, but there are certain
limitations. There is a special case when passing either a module path
to generate or a module name to publish. Doing that will filter out
entries in the config file that do not match. For example, running:
```
spacetime generate --project-path global-module
```
would only generate bindings for the second entry in the `generate`
list.
In a similar fashion, running:
```
spacetime publish region-1
```
would only publish the child database with the name `region-1`
Passing other existing arguments is also possible, but not all of the
arguments are available for multiple configs. For example, when running
`spacetime publish --server maincloud`, the publish command would be
applied to all of the modules listed in the config file, but the
`server` value from the command line arguments would take precedence.
Running with arguments like `--bin-path` would, however, would throw an
error as `--bin-path` makes sense only in a context of a specific
module, thus this wouldn't work: `spacetime publish --bin-path
spacetimedb/target/debug/bitcraft.wasm`. I will throw an error unless
there is only one entry to process, thus `spacetime publish --bin-path
spacetimedb/target/debug/bitcraft.wasm bitcraft` would work, as it
filters the publish targets to one entry.
# API and ABI breaking changes
None
# Expected complexity level and risk
3
The config file in itself is not overly complex, but when coupled with
the CLI it is somewhat tricky to get right. There are also some changes
that I had to make to how clap arguments are validated - because the
values can now come from both the config file and the clap config, we
can't use some of the built-in validations like `required`, or at least
I haven't found a clean way to do so.
# Testing
I've added some automated tests, but more tests and manual testing is
coming.
---------
Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: bradleyshep <148254416+bradleyshep@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: = <cloutiertyler@gmail.com>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
# Description of Changes
Adds a Node.js quickstart template and documentation for SpacetimeDB.
## Template (`templates/nodejs-ts/`)
- SpacetimeDB module with TypeScript (`spacetimedb/src/index.ts`)
- Node.js client with interactive CLI (`src/main.ts`)
- File-based token persistence (`.spacetimedb-token`) instead of
localStorage
- Table change callbacks (`onInsert`, `onDelete`)
- Graceful shutdown handlers for `SIGINT`/`SIGTERM`
- Pre-generated module bindings in `src/module_bindings/`
## Documentation
(`docs/docs/00100-intro/00200-quickstarts/00300-nodejs.md`)
- Step-by-step quickstart guide following existing pattern
- Covers project creation with `spacetime dev --template nodejs-ts`
- Explains project structure and client code
- Documents interactive CLI commands (`list`, `hello`, `<name>`)
- Covers Node.js-specific considerations (WebSocket support, token
storage)
- Documents environment variable configuration (`SPACETIMEDB_HOST`,
`SPACETIMEDB_DB_NAME`)
## Consistency
- Environment variables follow the same `HOST`/`DB_NAME` naming
convention as other quickstarts
- Documentation structure mirrors React and Next.js quickstarts
# API and ABI breaking changes
None.
# Expected complexity level and risk
1 - Additive change only. New template and documentation, no
modifications to existing functionality.
# Testing
- [ ] Run `spacetime dev --template nodejs-ts` and verify project
initializes
- [ ] Run `npm run dev` and verify connection to SpacetimeDB
- [ ] Test adding a person by typing a name
- [ ] Test `list` command shows all people
- [ ] Test `hello` command calls reducer (check server logs)
- [ ] Verify token persistence works across restarts
- [ ] Test graceful shutdown with Ctrl+C
- [ ] Check documentation renders correctly