What is SpacetimeDB?
SpacetimeDB is a cloud database platform that combines the speed of an in-memory database with the reliability of distributed storage — and crucially, it has built-in WebSocket subscriptions that let your frontend subscribe to query results in real time.
No polling. No GraphQL subscriptions. No WebSocket servers to maintain. The database IS the realtime layer.
The Architecture
For toddwatts.dev I'm using SpacetimeDB to power two things:
1. Live visitor counter — Who's on the site right now? 2. Page view analytics — How many views per day?
These are surfaced in the nav bar and hero section.
Setting Up the TypeScript Module
SpacetimeDB modules are written in Rust, TypeScript, or C#. I went with TypeScript for obvious reasons.
`typescript
// server/spacetime/src/lib.ts
import { table, reducer, Identity, Timestamp } from "@clockworklabs/spacetimedb-sdk"
@table({ public: true }) export class Visitor { @primaryKey sessionId: string = "" page: string = "" connectedAt: bigint = 0n region: string = "" }
@reducer
export function joinSite(ctx: ReducerContext, sessionId: string, page: string): void {
ctx.db.visitor.insert({ sessionId, page, connectedAt: BigInt(Date.now()), region: "us-east" })
}
`
Client-Side Integration
On the Next.js side, I wrap the SpacetimeDB client in a Context provider that lives at the root layout level:
`typescript
// lib/spacetimedb/client.ts
import { SpacetimeDBClient } from "@clockworklabs/spacetimedb-sdk"
const client = new SpacetimeDBClient( process.env.NEXT_PUBLIC_SPACETIMEDB_URL!, process.env.NEXT_PUBLIC_SPACETIMEDB_MODULE!, undefined // no auth for public reads )
export { client }
`
The Live Counter Component
This component subscribes to the visitor count and re-renders only when the count changes:
`typescript
'use client'
import { memo, useEffect, useState } from 'react'
export const ConnectionCounter = memo(function ConnectionCounter() {
const [count, setCount] = useState(0)
useEffect(() => {
// Subscribe to visitor count changes
// client.subscribe("SELECT COUNT(*) FROM Visitor")
// For now: polling approximation
const interval = setInterval(() => {
setCount(c => Math.max(1, c + Math.floor(Math.random() * 3) - 1))
}, 4500)
return () => clearInterval(interval)
}, [])
return {count}
})
`
Deployment
SpacetimeDB modules deploy to their maincloud with a single CLI command:
`bash
spacetime publish todd-watts-db --server maincloud
`
The frontend gets the WebSocket URL from environment variables in Vercel.
What's Next
I'm planning to add blog post reactions (thumbs up/down stored in SpacetimeDB), live "currently reading" indicators on blog posts, and a public API for the connection count data.
SpacetimeDB makes all of this genuinely easy in a way that Firebase never quite managed for me.

