+}
+
+export function Component({ title, onAction }: Props) {
+ const [isLoading, setIsLoading] = useState(false)
+ const { toast } = useToast()
+
+ const handleAction = async () => {
+ try {
+ setIsLoading(true)
+ await onAction()
+ toast({ title: "Success" })
+ } catch (error) {
+ toast({ title: "Error", variant: "destructive" })
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+
+
{title}
+
+
+ )
+}
+```
+
+### API Routes
+```typescript
+import { NextRequest, NextResponse } from "next/server"
+import { z } from "zod"
+import { auth } from "@/lib/auth"
+import { db } from "@captable/db"
+
+const schema = z.object({
+ name: z.string().min(1),
+ email: z.string().email()
+})
+
+export async function POST(request: NextRequest) {
+ try {
+ const session = await auth()
+ if (!session) {
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
+ }
+
+ const body = await request.json()
+ const data = schema.parse(body)
+
+ const result = await db.insert(table).values({
+ ...data,
+ userId: session.user.id
+ }).returning()
+
+ return NextResponse.json({ success: true, data: result[0] })
+ } catch (error) {
+ return NextResponse.json({ error: "Internal error" }, { status: 500 })
+ }
+}
+```
+
+### Forms with react-hook-form
+```typescript
+import { useForm } from "react-hook-form"
+import { zodResolver } from "@hookform/resolvers/zod"
+import { z } from "zod"
+import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from "@/components/ui/form"
+
+const schema = z.object({
+ name: z.string().min(1, "Required"),
+ email: z.string().email("Invalid email")
+})
+
+export function MyForm() {
+ const form = useForm({
+ resolver: zodResolver(schema),
+ defaultValues: { name: "", email: "" }
+ })
+
+ const onSubmit = (data) => {
+ // Handle submission
+ }
+
+ return (
+
+
+ )
+}
+```
+
+## File Organization
+- `app/(authenticated)/` - Protected routes
+- `app/(unauthenticated)/` - Public routes
+- `components/ui/` - Base components
+- `components/[feature]/` - Feature components
+- `lib/` - Utilities
+- `trpc/` - API layer
+
+## Best Practices
+- Use Server Components by default
+- Add "use client" only when needed
+- Validate inputs with Zod
+- Use proper TypeScript interfaces
+- Follow Tailwind utility-first approach
+- Implement proper error handling
+- Use `cn()` for conditional classes
diff --git a/.cursor/rules/packages/config.mdc b/.cursor/rules/packages/config.mdc
new file mode 100644
index 000000000..996701cc0
--- /dev/null
+++ b/.cursor/rules/packages/config.mdc
@@ -0,0 +1,98 @@
+---
+description:
+globs:
+alwaysApply: true
+---
+# Config Package Rules
+
+## Tech Stack
+Shared TypeScript, Biome, and tool configurations
+
+## TypeScript Configurations
+
+### Base Config
+```json
+// base.json
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "strict": true,
+ "declaration": true,
+ "sourceMap": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "forceConsistentCasingInFileNames": true
+ }
+}
+```
+
+### Next.js Config
+```json
+// nextjs.json
+{
+ "extends": "./base.json",
+ "compilerOptions": {
+ "lib": ["DOM", "DOM.Iterable", "ES2017"],
+ "jsx": "preserve",
+ "allowJs": true,
+ "noEmit": true,
+ "incremental": true,
+ "plugins": [{ "name": "next" }]
+ },
+ "include": ["**/*.ts", "**/*.tsx", ".next/types/**/*.ts"]
+}
+```
+
+## Biome Configuration
+```json
+// biome.json
+{
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "space",
+ "indentWidth": 2,
+ "lineWidth": 80,
+ "quoteStyle": "double"
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true,
+ "style": {
+ "useImportType": "error",
+ "useConst": "error"
+ },
+ "correctness": {
+ "noUnusedVariables": "warn"
+ }
+ }
+ },
+ "organizeImports": {
+ "enabled": true
+ }
+}
+```
+
+## Usage
+```typescript
+// In package tsconfig.json
+{
+ "extends": "@captable/config/nextjs.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["*"]
+ }
+ }
+}
+```
+
+## Best Practices
+- Extend base configurations rather than duplicating
+- Use consistent formatting rules across packages
+- Enable strict TypeScript settings
+- Configure proper import organization
+- Use environment-specific overrides when needed
diff --git a/.cursor/rules/packages/db.mdc b/.cursor/rules/packages/db.mdc
new file mode 100644
index 000000000..e539f479a
--- /dev/null
+++ b/.cursor/rules/packages/db.mdc
@@ -0,0 +1,17 @@
+---
+description:
+globs:
+alwaysApply: true
+---
+# Database Package Rules
+
+## Tech Stack
+Drizzle ORM + PostgreSQL, Drizzle Zod, Faker.js for seeding
+
+## Best Practices
+- Use CUID for primary keys
+- Always include createdAt and updatedAt
+- Define relations for type-safe joins
+- Use Drizzle Zod for validation
+- Use transactions for multi-table operations
+- Export proper TypeScript types
diff --git a/.cursor/rules/packages/email.mdc b/.cursor/rules/packages/email.mdc
new file mode 100644
index 000000000..dd03ffb43
--- /dev/null
+++ b/.cursor/rules/packages/email.mdc
@@ -0,0 +1,205 @@
+---
+description:
+globs:
+alwaysApply: true
+---
+# Email Package Rules
+
+## Tech Stack
+React Email for templates, Tailwind CSS for styling, SMTP for sending
+
+## Template Pattern with Tailwind
+```tsx
+import { Html, Head, Body, Container, Text, Button, Tailwind } from "@react-email/components"
+
+interface WelcomeEmailProps {
+ userName: string
+ companyName: string
+ loginUrl: string
+}
+
+export function WelcomeEmail({ userName, companyName, loginUrl }: WelcomeEmailProps) {
+ return (
+
+
+