Skip to content

Commit dea509b

Browse files
Add Astro TypeScript template (#4688)
## Summary - add a new `templates/astro-ts` template based on the existing Astro + SpacetimeDB integration work - include Astro SSR, a React client island for realtime updates, and a small `server:defer` example - add Astro quickstart documentation under `docs/docs/00100-intro/00200-quickstarts/00152-astro.md` ## Validation - `pnpm install` - `pnpm -F spacetimedb build` - `pnpm -F ./templates/astro-ts build` ## Notes - I did not add `astro-ts` to the built-in template listing in `spacetime dev` docs, to match the current `nextjs-ts` pattern. --------- Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
1 parent b1d5c59 commit dea509b

File tree

25 files changed

+1057
-0
lines changed

25 files changed

+1057
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
title: Astro Quickstart
3+
sidebar_label: Astro
4+
slug: /quickstarts/astro
5+
hide_table_of_contents: true
6+
---
7+
8+
import { InstallCardLink } from "@site/src/components/InstallCardLink";
9+
import { StepByStep, Step, StepText, StepCode } from "@site/src/components/Steps";
10+
11+
12+
Get a SpacetimeDB Astro app running in under 5 minutes.
13+
14+
## Prerequisites
15+
16+
- [Node.js](https://nodejs.org/) 18+ installed
17+
- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
18+
19+
<InstallCardLink />
20+
21+
---
22+
23+
<StepByStep>
24+
<Step title="Create your project">
25+
<StepText>
26+
Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Astro client.
27+
28+
This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Astro development server.
29+
</StepText>
30+
<StepCode>
31+
```bash
32+
spacetime dev --template astro-ts
33+
```
34+
</StepCode>
35+
</Step>
36+
37+
<Step title="Open your app">
38+
<StepText>
39+
Navigate to [http://localhost:4321](http://localhost:4321) to see your app running.
40+
41+
The Astro app reads `SPACETIMEDB_*` variables on the server and `PUBLIC_SPACETIMEDB_*` variables in the client, so `.env.local` can configure both sides of the app.
42+
</StepText>
43+
</Step>
44+
45+
<Step title="Explore the project structure">
46+
<StepText>
47+
Your project contains both server and client code using Astro SSR and a live React island for real-time updates.
48+
49+
Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/pages/index.astro` and `src/components/PersonList.tsx` to build your UI.
50+
</StepText>
51+
<StepCode>
52+
```text
53+
my-astro-app/
54+
├── spacetimedb/ # Your SpacetimeDB module
55+
│ └── src/
56+
│ └── index.ts # SpacetimeDB module logic
57+
├── src/
58+
│ ├── components/
59+
│ │ ├── PersonList.tsx
60+
│ │ ├── SpacetimeApp.tsx
61+
│ │ └── DeferredPeopleSnapshot.astro
62+
│ ├── lib/
63+
│ │ └── spacetimedb-server.ts
64+
│ ├── module_bindings/ # Auto-generated types
65+
│ ├── layouts/
66+
│ │ └── Layout.astro
67+
│ ├── pages/
68+
│ │ └── index.astro
69+
│ └── styles/
70+
│ └── global.css
71+
└── package.json
72+
```
73+
</StepCode>
74+
</Step>
75+
76+
<Step title="Understand tables and reducers">
77+
<StepText>
78+
Open `spacetimedb/src/index.ts` to see the module code. The template includes a `person` table and two reducers: `add` to insert a person, and `sayHello` to greet everyone.
79+
80+
Tables store your data. Reducers are functions that modify data and are the only way to write to the database.
81+
</StepText>
82+
<StepCode>
83+
```typescript
84+
import { schema, table, t } from 'spacetimedb/server';
85+
86+
const spacetimedb = schema({
87+
person: table(
88+
{ public: true },
89+
{
90+
name: t.string(),
91+
}
92+
),
93+
});
94+
export default spacetimedb;
95+
96+
export const add = spacetimedb.reducer(
97+
{ name: t.string() },
98+
(ctx, { name }) => {
99+
ctx.db.person.insert({ name });
100+
}
101+
);
102+
103+
export const sayHello = spacetimedb.reducer(ctx => {
104+
for (const person of ctx.db.person.iter()) {
105+
console.info(`Hello, ${person.name}!`);
106+
}
107+
console.info('Hello, World!');
108+
});
109+
```
110+
</StepCode>
111+
</Step>
112+
113+
<Step title="Test with the CLI">
114+
<StepText>
115+
Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
116+
</StepText>
117+
<StepCode>
118+
```bash
119+
cd my-spacetime-app
120+
121+
# Call the add reducer to insert a person
122+
spacetime call add Alice
123+
124+
# Query the person table
125+
spacetime sql "SELECT * FROM person"
126+
name
127+
---------
128+
"Alice"
129+
130+
# Call sayHello to greet everyone
131+
spacetime call say_hello
132+
133+
# View the module logs
134+
spacetime logs
135+
2025-01-13T12:00:00.000000Z INFO: Hello, Alice!
136+
2025-01-13T12:00:00.000000Z INFO: Hello, World!
137+
```
138+
</StepCode>
139+
</Step>
140+
141+
<Step title="Understand Astro SSR and real-time hydration">
142+
<StepText>
143+
The SpacetimeDB SDK works both server-side and client-side. The template uses a hybrid approach:
144+
145+
- **Astro page** (`src/pages/index.astro`): Fetches initial data on the server for a fast first render
146+
- **React island** (`src/components/SpacetimeApp.tsx`): Hydrates on the client and provides the SpacetimeDB connection
147+
- **Live table UI** (`src/components/PersonList.tsx`): Uses `useTable()` and `useReducer()` for real-time updates
148+
</StepText>
149+
<StepCode>
150+
```astro
151+
---
152+
import Layout from '../layouts/Layout.astro';
153+
import SpacetimeApp from '../components/SpacetimeApp';
154+
import { fetchPeople } from '../lib/spacetimedb-server';
155+
156+
const initialPeople = await fetchPeople();
157+
---
158+
159+
<Layout title="astro-ts">
160+
<h1>astro-ts</h1>
161+
<SpacetimeApp client:load initialPeople={initialPeople} />
162+
</Layout>
163+
```
164+
</StepCode>
165+
</Step>
166+
167+
<Step title="Understand Astro server islands">
168+
<StepText>
169+
The template also includes a deferred Astro-only section to demonstrate `server:defer`.
170+
171+
`src/components/DeferredPeopleSnapshot.astro` fetches its own server-rendered snapshot, and `src/pages/index.astro` renders it as a server island without changing the main real-time client flow.
172+
</StepText>
173+
<StepCode>
174+
```astro
175+
<DeferredPeopleSnapshot server:defer>
176+
<div slot="fallback">Loading deferred people snapshot…</div>
177+
</DeferredPeopleSnapshot>
178+
```
179+
</StepCode>
180+
</Step>
181+
</StepByStep>

templates/astro-ts/.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# build output
2+
dist/
3+
spacetimedb/dist/
4+
5+
# generated types
6+
.astro/
7+
8+
# dependencies
9+
node_modules/
10+
11+
# logs
12+
npm-debug.log*
13+
yarn-debug.log*
14+
yarn-error.log*
15+
pnpm-debug.log*
16+
17+
# environment variables
18+
.env
19+
.env.local
20+
.env.*.local
21+
.env.production
22+
23+
# macOS-specific files
24+
.DS_Store
25+
26+
# jetbrains setting folder
27+
.idea/
28+

templates/astro-ts/.template.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"description": "Astro app with a TypeScript server module",
3+
"client_framework": "Astro",
4+
"client_lang": "typescript",
5+
"server_lang": "typescript",
6+
"builtWith": [
7+
"astro",
8+
"react",
9+
"react-dom",
10+
"typescript",
11+
"spacetimedb"
12+
]
13+
}

templates/astro-ts/LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../licenses/apache2.txt

templates/astro-ts/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
Get a SpacetimeDB Astro app running in under 5 minutes.
2+
3+
## Prerequisites
4+
5+
- [Node.js](https://nodejs.org/) 18+ installed
6+
- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
7+
8+
Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
9+
10+
---
11+
12+
## Create your project
13+
14+
Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Astro client.
15+
16+
This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Astro development server.
17+
18+
```bash
19+
spacetime dev --template astro-ts
20+
```
21+
22+
## Open your app
23+
24+
Navigate to [http://localhost:4321](http://localhost:4321) to see your app running.
25+
26+
The Astro app reads `SPACETIMEDB_*` variables on the server and `PUBLIC_SPACETIMEDB_*` variables in the client, so `.env.local` can configure both sides of the app.
27+
28+
## Explore the project structure
29+
30+
Your project contains both server and client code using Astro SSR and a live interactive client for real-time updates.
31+
32+
Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/pages/index.astro` and `src/components/PersonList.tsx` to build your UI.
33+
34+
```text
35+
my-astro-app/
36+
├── spacetimedb/ # Your SpacetimeDB module
37+
│ └── src/
38+
│ └── index.ts # SpacetimeDB module logic
39+
├── src/
40+
│ ├── components/
41+
│ │ ├── PersonList.tsx
42+
│ │ ├── SpacetimeApp.tsx
43+
│ │ └── DeferredPeopleSnapshot.astro
44+
│ ├── lib/
45+
│ │ └── spacetimedb-server.ts
46+
│ ├── module_bindings/ # Auto-generated types
47+
│ ├── layouts/
48+
│ │ └── Layout.astro
49+
│ ├── pages/
50+
│ │ └── index.astro
51+
│ └── styles/
52+
│ └── global.css
53+
└── package.json
54+
```
55+
56+
## Understand tables and reducers
57+
58+
Open `spacetimedb/src/index.ts` to see the module code. The template includes a `person` table and two reducers: `add` to insert a person, and `sayHello` to greet everyone.
59+
60+
Tables store your data. Reducers are functions that modify data and are the only way to write to the database.
61+
62+
```typescript
63+
import { schema, table, t } from 'spacetimedb/server';
64+
65+
const spacetimedb = schema({
66+
person: table(
67+
{ public: true },
68+
{
69+
name: t.string(),
70+
}
71+
),
72+
});
73+
export default spacetimedb;
74+
75+
export const add = spacetimedb.reducer(
76+
{ name: t.string() },
77+
(ctx, { name }) => {
78+
ctx.db.person.insert({ name });
79+
}
80+
);
81+
82+
export const sayHello = spacetimedb.reducer(ctx => {
83+
for (const person of ctx.db.person.iter()) {
84+
console.info(`Hello, ${person.name}!`);
85+
}
86+
console.info('Hello, World!');
87+
});
88+
```
89+
90+
## Understand Astro SSR plus real-time hydration
91+
92+
The template uses a hybrid rendering model:
93+
94+
- `src/pages/index.astro` fetches the initial list of people on the server for a fast first paint.
95+
- `src/components/SpacetimeApp.tsx` hydrates with `client:load` and provides the SpacetimeDB connection.
96+
- `src/components/PersonList.tsx` subscribes to the `person` table with `useTable()` and calls reducers with `useReducer()`.
97+
98+
This gives you server-rendered HTML on the first request and a live WebSocket-backed UI after hydration.
99+
100+
## Understand Astro server islands
101+
102+
The template also includes a deferred Astro-only section to demonstrate `server:defer`.
103+
104+
- `src/components/DeferredPeopleSnapshot.astro` fetches its own server-rendered snapshot.
105+
- `src/pages/index.astro` renders it with `server:defer`, so it loads after the main page shell.
106+
107+
This demonstrates an Astro-specific pattern without affecting the main real-time client flow.
108+
109+
## Test with the CLI
110+
111+
Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
112+
113+
```bash
114+
cd my-spacetime-app
115+
116+
# Call the add reducer to insert a person
117+
spacetime call add Alice
118+
119+
# Query the person table
120+
spacetime sql "SELECT * FROM person"
121+
name
122+
---------
123+
"Alice"
124+
125+
# Call sayHello to greet everyone
126+
spacetime call say_hello
127+
128+
# View the module logs
129+
spacetime logs
130+
2025-01-13T12:00:00.000000Z INFO: Hello, Alice!
131+
2025-01-13T12:00:00.000000Z INFO: Hello, World!
132+
```
133+
134+
## Next steps
135+
136+
- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
137+
- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// @ts-check
2+
import node from '@astrojs/node';
3+
import react from '@astrojs/react';
4+
import { defineConfig } from 'astro/config';
5+
6+
export default defineConfig({
7+
output: 'server',
8+
adapter: node({
9+
mode: 'standalone',
10+
}),
11+
integrations: [react()],
12+
});

0 commit comments

Comments
 (0)