Development Workflow
Commands, patterns, and AI-assisted development.
VelocityKit is designed for rapid, AI-assisted development.
Essential Commands
pnpm dev # Start development server
pnpm build # Build for production
pnpm check # Run all checks (lint, typecheck, format, test)
pnpm test # Run unit tests
pnpm test:e2e # Run end-to-end tests
Database Commands
pnpm supabase:start # Start local Supabase
pnpm supabase:stop # Stop local Supabase
pnpm supabase:reset # Reset and run migrations
pnpm supabase:push # Push to remote database
pnpm supabase:types # Generate TypeScript types
pnpm supabase:migration:new # Create new migration
Git Workflow
pnpm commit # Stage all, AI commit message, push
pnpm commit -m "message" # Stage all, use your message, push
pnpm commit --no-ai # Stage all, open editor, push
pnpm ship # Release: version bump, changelog, tag, deploy
AI Commit Messages
The pnpm commit command can generate commit messages using AI:
# Add an API key to .env.local
OPENAI_API_KEY=sk-...
# or
ANTHROPIC_API_KEY=sk-ant-...
AI_PROVIDER=anthropic
Without an API key, it falls back to opening your editor.
Project Structure
src/
├── app/ # Next.js App Router
│ ├── (auth)/ # Auth pages
│ ├── (marketing)/ # Public pages
│ ├── dashboard/ # Protected pages
│ └── api/ # API routes
├── components/
│ ├── ui/ # shadcn/ui components
│ └── [feature]/ # Feature components
├── lib/
│ ├── supabase/ # Database clients
│ ├── stripe/ # Billing utilities
│ └── [feature]/ # Feature actions
├── config/ # Site configuration
└── hooks/ # React hooks
Adding Features
Follow this pattern when adding new features:
1. Database Migration
Create a new migration:
pnpm supabase:migration:new add_items_table
Add your table with RLS:
CREATE TABLE items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
account_id UUID REFERENCES accounts(id) NOT NULL,
created_by UUID REFERENCES auth.users(id) NOT NULL,
title TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
ALTER TABLE items ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can manage their account items"
ON items FOR ALL
USING (account_id IN (
SELECT account_id FROM account_users WHERE user_id = auth.uid()
));
2. Server Actions
Create src/lib/items/actions.ts:
"use server";
import { createClient } from "@/lib/supabase/server";
import { getCurrentAccountId } from "@/lib/account/actions";
import { z } from "zod";
const schema = z.object({
title: z.string().min(1).max(200),
});
export async function createItem(
_prevState: { error?: string } | null,
formData: FormData
) {
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) return { error: "Not authenticated" };
const accountId = await getCurrentAccountId();
if (!accountId) return { error: "No account found" };
const parsed = schema.safeParse({
title: formData.get("title"),
});
if (!parsed.success) {
return { error: parsed.error.issues[0].message };
}
const { error } = await supabase.from("items").insert({
account_id: accountId,
created_by: user.id,
...parsed.data,
});
if (error) return { error: "Failed to create item" };
return { success: true };
}
3. Components
Create form with useActionState:
"use client";
import { useActionState } from "react";
import { createItem } from "@/lib/items/actions";
export function CreateItemForm() {
const [state, formAction, isPending] = useActionState(createItem, null);
return (
<form action={formAction}>
{state?.error && <p className="text-destructive">{state.error}</p>}
<input name="title" required />
<button disabled={isPending}>
{isPending ? "Creating..." : "Create"}
</button>
</form>
);
}
4. Page
Create src/app/dashboard/items/page.tsx and add to sidebar navigation.
AI-Assisted Development
VelocityKit is optimized for AI tools like Claude Code:
- CLAUDE.md — Project context for AI assistants
- docs/prompts/ — Templates for common tasks
- Consistent patterns — Makes AI suggestions reliable
Tips for AI-assisted development:
- Reference existing patterns (e.g., "like the todos feature")
- Be specific about requirements
- Ask for one thing at a time
- Review generated code before committing