Documentation source
New Product
Step-by-step guide to creating a new product on the Sprinter Platform -- fork, customize, seed, brand, and deploy.
# New Product
The Sprinter Platform is designed for reusability. Creating a new product (like Ember, Cabby v2, or any new venture) means forking the repo and replacing the product-specific layer while keeping the entire platform engine intact.
## What stays, what changes
### Platform code (100% reused)
Everything in `features/` except `features/custom/` is domain-agnostic and carries over unchanged:
| Module | What it provides |
|--------|-----------------|
| `features/entities/` | Entity CRUD, views (bento/list/grid/kanban), scoring, extraction, tags |
| `features/agents/` | Agent registry, delegation, heartbeat, org chart, config versioning |
| `features/tools/` | Tool registry, execution engine, AI bridge, generic UI, sessions |
| `features/chat/` | AI chat system, persistence, history, agent selection |
| `features/tenant/` | Multi-tenant context, switching, member management |
| `features/blocks/` | 20 block types, BlockGrid layout, bridge functions |
| `features/views/` | Config-driven views (list, detail, workspace), view editor |
| `features/navigation/` | Sidebar customization, sections, dynamic sources |
| `features/documents/` | Document storage, upload, processing, chunking |
| `features/capture/` | AI-powered quick capture |
| `features/charts/` | Recharts wrappers (radar, bubble) |
| `features/context/` | Shared corrections and learnings |
| `features/analytics/` | Event tracking |
| `features/api-keys/` | API key management |
| `features/inngest/` | Background job orchestration |
| `features/comments/` | Threaded comments |
| `features/actions/`, `features/sessions/`, `features/responses/` | Work definition, runtime execution, and reviewed outputs |
Also unchanged: `components/ui/` (shadcn/ui), `components/app-shell/` (sidebar, command palette), `lib/` (utilities, Supabase clients), `app/` (route handlers).
### Product code (replaced per fork)
Only `features/custom/` changes:
| Directory | What to replace |
|-----------|----------------|
| `features/custom/components/` | Entity type UI overrides (cards, detail views) |
| `features/custom/tools/` | Product-specific tool definitions + optional custom UI |
| `features/custom/lib/` | Shared product utilities (formatters, constants) |
| `features/custom/server/` | Product-specific server actions (dashboard data) |
## Step-by-step guide
### 1. Fork the repository
```bash
git clone https://github.com/your-org/sprinter-platform.git my-product
cd my-product
git remote rename origin upstream
git remote add origin https://github.com/your-org/my-product.git
```
Keep the `upstream` remote to pull platform updates later.
### 2. Clear product-specific code
Remove the Amble-specific custom code:
```bash
rm -rf features/custom/components/*
rm -rf features/custom/tools/*
rm -rf features/custom/lib/*
rm -rf features/custom/server/*
```
Keep the directory structure and barrel files (`index.ts`) -- they should export empty or have no imports until you add your own product code.
### 3. Define entity types
Create a seed script for your product's entity types. Entity types are the core data model -- they define what your product tracks.
Create `scripts/seed-my-product-types.mjs`:
```javascript
import { createClient } from '@supabase/supabase-js'
import { randomUUID } from 'crypto'
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.SUPABASE_SECRET_KEY ?? process.env.SUPABASE_SERVICE_ROLE_KEY
)
const entityTypes = [
{
id: randomUUID(),
slug: 'project',
name: 'Project',
json_schema: {
type: 'object',
properties: {
description: { type: 'string' },
status: {
type: 'string',
enum: ['planning', 'active', 'review', 'completed'],
},
priority: {
type: 'string',
enum: ['low', 'medium', 'high', 'critical'],
},
due_date: { type: 'string', format: 'date' },
budget: { type: 'number' },
},
required: ['description', 'status'],
},
config: {
ui: {
icon: 'folder',
color: 'blue',
description: 'A project being tracked',
cardFields: ['status', 'priority', 'due_date'],
},
fields: {
description: {
extraction: {
instructions: 'Write a concise project description.',
required: true,
},
},
},
},
},
// Add more entity types...
]
for (const type of entityTypes) {
const { error } = await supabase
.from('entity_types')
.upsert(type, { onConflict: 'slug' })
if (error) console.error(`Failed: ${type.slug}`, error.message)
else console.log(`Seeded: ${type.slug}`)
}
```
Add an npm script:
```json
{
"seed:types": "node --env-file=.env.local scripts/seed-my-product-types.mjs"
}
```
Run it:
```bash
pnpm seed:types
```
### 4. Update branding
#### CSS variables
Edit the CSS variables in your global stylesheet (typically `app/globals.css`). The key variable is `--primary`:
```css
:root {
/* Change the primary color from deep navy to your brand */
--primary: oklch(0.35 0.05 260); /* Deep navy (default) */
/* Example alternatives: */
/* --primary: oklch(0.45 0.12 145); Green */
/* --primary: oklch(0.40 0.10 25); Warm red */
}
```
All neutral chrome colors must remain zero-chroma (`oklch(X 0 0)`) -- only `--primary` should carry hue.
#### Logo and app name
Update the sidebar logo in `components/app-shell/app-sidebar.tsx`. The sidebar displays the product name as text -- find the logo/title section and replace it.
#### Page titles
Update the site metadata in `app/layout.tsx` -- title, description, and any Open Graph metadata.
### 5. Create product-specific tools (optional)
If your product needs custom calculators or analysis tools:
```bash
mkdir -p features/custom/tools/my-tool
```
Create the tool definition:
```typescript
// features/custom/tools/my-tool/definition.ts
import { registerTool } from "@/features/tools/registry";
import { z } from "zod/v4";
registerTool({
slug: "my-tool",
name: "My Tool",
description: "Does something useful",
category: "analysis",
inputSchema: z.object({
input: z.string(),
}),
execute: async (input) => {
return { result: `Processed: ${input.input}` };
},
});
```
Create a test file, import in `features/custom/tools/index.ts`, and optionally create custom UI components.
### 6. Create product-specific components (optional)
If you need custom entity type cards or detail views:
```bash
mkdir -p features/custom/components/project
```
The platform renders everything generically from `json_schema` by default. Custom components are optional overrides for when the generic rendering is not sufficient.
### 7. Set up the database
```bash
# Start local Supabase
pnpm db:start
# Apply all migrations
pnpm db:reset
# Seed your entity types
pnpm seed:types
# Seed agents (for chat and heartbeat)
pnpm seed:agents
# Regenerate TypeScript types
pnpm db:types
```
### 8. Configure agents
Agents are either code-defined (in `features/agents/default-agents.ts`) or DB-managed (via Admin > Agents). For a new product:
- The default agents (Amble, Analyst, Researcher) work as-is since they operate on the generic entity graph
- Customize agent system prompts via the admin UI to reference your product's entity types
- Create new agents for product-specific workflows
### 9. Deploy
Follow the [deploy runbook](/docs/runbooks/deploy):
1. Set environment variables in Vercel
2. Push migrations to production: `pnpm db:push`
3. Seed entity types on production: `pnpm seed:types`
4. Deploy via Git push to main
### 10. Verify
After deployment:
- Navigate to `/dashboard` -- should show empty state
- Navigate to `/admin` -- configure entity types, agents, and members
- Create a test entity via the UI or chat
- Verify extraction works (if field configs have extraction instructions)
- Check that the sidebar shows your entity types
## Pulling platform updates
To incorporate platform improvements from upstream:
```bash
git fetch upstream
git merge upstream/main
```
Resolve any conflicts in `features/custom/` -- platform code changes should merge cleanly since custom code is isolated.
## What not to change
- **Do not modify `features/` (except `features/custom/`)** -- platform code must stay generic
- **Do not hardcode entity type slugs in platform code** -- entity types are DB-driven
- **Do not import from `features/custom/` in platform code** -- the dependency flows one way
- **Do not remove the default tenant** (`00000000-0000-0000-0000-000000000000`) -- it is required for the auth provisioning trigger
## Documentation
The docs system (`content/docs/`) carries over with the platform. Feature docs under `content/docs/features/` document platform capabilities and apply to all products. Product-specific documentation can be added as needed but is not required at fork time.