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
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.gitKeep the upstream remote to pull platform updates later.
2. Clear product-specific code
Remove the Amble-specific custom code:
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:
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:
{
"seed:types": "node --env-file=.env.local scripts/seed-my-product-types.mjs"
}Run it:
pnpm seed:types4. Update branding
CSS variables
Edit the CSS variables in your global stylesheet (typically app/globals.css). The key variable is --primary:
: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:
mkdir -p features/custom/tools/my-toolCreate the tool definition:
// 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:
mkdir -p features/custom/components/projectThe 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
# 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:types8. 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:
- Set environment variables in Vercel
- Push migrations to production:
pnpm db:push - Seed entity types on production:
pnpm seed:types - 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:
git fetch upstream
git merge upstream/mainResolve any conflicts in features/custom/ -- platform code changes should merge cleanly since custom code is isolated.
What not to change
- Do not modify
features/(exceptfeatures/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.