A complete AI-powered startup hypothesis canvas using the Pivot Pyramid framework. Built with Next.js, Convex, and OpenRouter.
- Two-tab workflow: Describe your startup → Generate AI hypotheses
- AI Canvas Generation: Gemini 2.5 Flash generates structured hypotheses from your description
- AI Chat Advisor: Real-time streaming chat with an AI startup advisor
- Auto-save: All changes saved automatically to Convex
- Anonymous sessions: Works without auth (localStorage-based sessions)
- Responsive design: Mobile-first with desktop chat panel
Before starting, you'll need:
- Node.js 18+ installed
- Convex account — Sign up free
- OpenRouter API key — Get one here
# Create new project
npx create-next-app@latest pivot-pyramid --typescript --tailwind --eslint --app --src-dir
# Navigate to project
cd pivot-pyramidnpm install convex @convex-dev/persistent-text-streaming @openrouter/ai-sdk-provider ai zod lucide-react use-debounce# Initialize Convex (will prompt you to login/signup)
npx convex dev
# This creates:
# - convex/ folder
# - .env.local with CONVEX_DEPLOYMENT and NEXT_PUBLIC_CONVEX_URLKeep this terminal running during development. It syncs your Convex functions.
Copy the entire contents of this export folder:
pivot-pyramid-export/
├── convex/ → your-project/convex/
│ ├── schema.ts
│ ├── convex.config.ts
│ ├── canvases.ts
│ ├── canvasMessages.ts
│ ├── canvasStream.ts
│ └── http.ts
├── src/
│ ├── app/canvas/ → your-project/src/app/canvas/
│ │ └── page.tsx
│ ├── components/
│ │ ├── canvas/ → your-project/src/components/canvas/
│ │ │ ├── canvas-provider.tsx
│ │ │ ├── canvas-tabs.tsx
│ │ │ ├── canvas-form.tsx
│ │ │ ├── canvas-header.tsx
│ │ │ ├── startup-profile-form.tsx
│ │ │ ├── layer-input.tsx
│ │ │ ├── confidence-slider.tsx
│ │ │ ├── chat-panel.tsx
│ │ │ ├── chat-input.tsx
│ │ │ └── chat-message.tsx
│ │ └── providers/ → your-project/src/components/providers/
│ │ └── convex-provider.tsx
│ ├── hooks/ → your-project/src/hooks/
│ │ ├── use-canvas-session.ts
│ │ └── use-driven-streams.ts
│ └── lib/ → your-project/src/lib/
│ └── pivot-pyramid-data.ts
Update your root layout to include the Convex provider:
src/app/layout.tsx:
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { ConvexClientProvider } from "@/components/providers/convex-provider";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Pivot Pyramid Canvas",
description: "AI-powered startup hypothesis tool",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<ConvexClientProvider>
{children}
</ConvexClientProvider>
</body>
</html>
);
}Ensure your tsconfig.json has the @/ path alias:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}Add your OpenRouter API key to Convex environment:
# Via Convex dashboard (recommended)
# Go to: https://dashboard.convex.dev → Your Project → Settings → Environment Variables
# Add: OPENROUTER_API_KEY = your-key-here
# Or via CLI
npx convex env set OPENROUTER_API_KEY your-key-hereCreate a simple homepage that links to the canvas:
src/app/page.tsx:
import Link from "next/link";
export default function Home() {
return (
<main className="min-h-screen bg-stone-50 flex items-center justify-center">
<div className="text-center">
<h1 className="text-3xl font-bold text-stone-800 mb-4">
Pivot Pyramid Canvas
</h1>
<p className="text-stone-600 mb-8 max-w-md">
Document your startup hypotheses with AI-powered guidance
</p>
<Link
href="/canvas"
className="inline-flex items-center gap-2 px-6 py-3 rounded-xl bg-gradient-to-br from-amber-400 to-orange-500 text-white font-semibold shadow-md hover:shadow-lg transition-all"
>
Start Your Canvas
</Link>
</div>
</main>
);
}# Terminal 1: Convex dev server (if not already running)
npx convex dev
# Terminal 2: Next.js dev server
npm run devVisit http://localhost:3000/canvas to see your canvas!
Your .env.local should have (automatically created by npx convex dev):
# Convex (auto-generated)
CONVEX_DEPLOYMENT=your-deployment-name
NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloudYour Convex dashboard should have:
OPENROUTER_API_KEY=sk-or-v1-xxxxxxxx
| File | Purpose |
|---|---|
schema.ts |
Database schema (canvases + messages tables) |
convex.config.ts |
Component configuration (streaming) |
canvases.ts |
CRUD operations + AI generation action |
canvasMessages.ts |
Chat message operations + streaming |
canvasStream.ts |
HTTP action for AI streaming |
http.ts |
HTTP router for streaming endpoint |
| Component | Purpose |
|---|---|
canvas-provider.tsx |
React Context for canvas state |
canvas-tabs.tsx |
Profile / Canvas tab switcher |
startup-profile-form.tsx |
Freeform startup description input |
canvas-form.tsx |
Five-layer hypothesis form |
layer-input.tsx |
Individual layer with confidence slider |
chat-panel.tsx |
AI advisor chat interface |
chat-message.tsx |
Message component with streaming |
| Hook | Purpose |
|---|---|
use-canvas-session.ts |
Anonymous session management |
use-driven-streams.ts |
Track client-initiated streams |
Edit convex/canvasStream.ts and convex/canvases.ts:
// Current
model: openrouter.chat("google/gemini-2.5-flash")
// Alternatives
model: openrouter.chat("anthropic/claude-3.5-sonnet")
model: openrouter.chat("openai/gpt-4o")The AI advisor's behavior is defined in convex/canvasStream.ts:
const PIVOT_PYRAMID_SYSTEM_PROMPT = `...`;Replace the anonymous session system in use-canvas-session.ts with your auth provider (Clerk, Auth0, etc.) and update canvas-provider.tsx to use user IDs instead of session IDs.
The project uses Tailwind CSS. Main colors:
- Primary:
amber-400toorange-500gradient - Background:
stone-50 - Text:
stone-700,stone-800
Make sure npx convex dev is running and .env.local has the correct URLs.
- Check OpenRouter API key is set in Convex dashboard
- Check browser console for errors
- Verify the model ID is valid on OpenRouter
The streaming uses HTTP actions. Make sure:
convex/http.tsexports the routerconvex/convex.config.tsincludes the streaming component- CORS is properly configured (already done in the files)
Run npx convex dev to regenerate types in convex/_generated/.
npx convex deployThis deploys your Convex backend to production. Don't forget to set OPENROUTER_API_KEY in the production environment variables.
# Install Vercel CLI
npm i -g vercel
# Deploy
vercelSet environment variables in Vercel dashboard:
NEXT_PUBLIC_CONVEX_URL— Your production Convex URL
MIT License — Feel free to use this for your own projects!
The Pivot Pyramid framework was created by Selçuk Atlı (YC W14, 500 Startups Venture Partner).
Learn more at selcukatli.com/pivot-pyramid