MDX Limo
🦧 The Orangutan Kit

🦧 The Orangutan Kit

A dead-simple guide to setting up a modern dev toolkit. Next.js · Supabase or Convex · Resend · Mastra · Claude Code


What Is This?

This is a no-fluff setup guide for a full-stack TypeScript project with AI tooling baked in. Every tool here was picked because it's well-documented, has a generous free tier, and plays nicely with the others.

The stack at a glance:

LayerToolOne-liner
Frontend + APINext.js 15React framework with file-based routing and server rendering
DatabaseSupabase or ConvexPick one. Supabase = Postgres + auth. Convex = real-time NoSQL
EmailResendSend emails using React components as templates
AI FrameworkMastraBuild AI agents, workflows, and RAG in TypeScript
Coding AgentClaude CodeAI pair programmer in your terminal and IDE
Glue LayerMCP ServersLet Claude talk directly to your database and docs

Before You Start

You need these installed:

  • Node.js 20+nodejs.org
  • Git → configured with your GitHub account
  • Cursor IDE (recommended) or VS Code

You need these accounts (all have free tiers):


Step 1 → Create Your Next.js Project

This is your foundation. Everything else plugs into this.

1npx create-next-app@latest orangutan-app

Accept all the defaults (TypeScript, Tailwind, App Router, Turbopack). Then:

1cd orangutan-app 2npm run dev

Open http://localhost:3000. You should see the welcome page. That's it — you have a working app.

What you need to know:

  • src/app/page.tsx → your homepage
  • src/app/layout.tsx → wraps every page (put providers here)
  • src/app/api/ → your API routes (serverless functions)
  • .env.local → secrets go here (gitignored automatically)
  • Components are Server Components by default. Only add "use client" when you need browser stuff (hooks, click handlers, etc.)

Step 2 → Pick Your Database

Option A: Supabase (Postgres, built-in auth)

Best if: you want SQL, row-level security, and built-in authentication.

1npm install @supabase/supabase-js @supabase/ssr

Add to .env.local:

1NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co 2NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

(Find these in your Supabase dashboard → Settings → API, or the Connect dialog.)

Create src/lib/supabase/client.ts (for browser/client components):

1import { createBrowserClient } from "@supabase/ssr"; 2 3export function createClient() { 4 return createBrowserClient( 5 process.env.NEXT_PUBLIC_SUPABASE_URL!, 6 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! 7 ); 8}

Create src/lib/supabase/server.ts (for server components and API routes):

1import { createServerClient } from "@supabase/ssr"; 2import { cookies } from "next/headers"; 3 4export async function createClient() { 5 const cookieStore = await cookies(); 6 return createServerClient( 7 process.env.NEXT_PUBLIC_SUPABASE_URL!, 8 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, 9 { cookies: { /* see Supabase SSR docs for cookie handlers */ } } 10 ); 11}

Shortcut: Run npx create-next-app -e with-supabase to get a pre-wired starter with auth, middleware, and both clients already configured.


Option B: Convex (real-time NoSQL, TypeScript-native)

Best if: you want reactive queries, zero SQL, and everything in TypeScript.

1npm install convex 2npx convex dev

This logs you in via GitHub, creates your project, and generates a convex/ folder. Keep this terminal running — it live-syncs your backend.

Create src/app/ConvexClientProvider.tsx:

1"use client"; 2import { ConvexProvider, ConvexReactClient } from "convex/react"; 3 4const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!); 5 6export default function ConvexClientProvider({ 7 children, 8}: { 9 children: React.ReactNode; 10}) { 11 return <ConvexProvider client={convex}>{children}</ConvexProvider>; 12}

Wrap your app in layout.tsx with this provider. Write queries in convex/ and use them with useQuery() from convex/react.


Step 3 → Email with Resend

1npm install resend @react-email/components

Add to .env.local:

1RESEND_API_KEY=re_your_api_key_here

Create a template — src/components/email-template.tsx:

1export function WelcomeEmail({ name }: { name: string }) { 2 return ( 3 <div> 4 <h1>Welcome, {name}!</h1> 5 <p>Thanks for joining.</p> 6 </div> 7 ); 8}

Create an API route — src/app/api/send/route.ts:

1import { Resend } from "resend"; 2import { WelcomeEmail } from "@/components/email-template"; 3 4const resend = new Resend(process.env.RESEND_API_KEY); 5 6export async function POST() { 7 const { data, error } = await resend.emails.send({ 8 from: "Orangutan Kit <onboarding@resend.dev>", 9 to: ["your@email.com"], 10 subject: "Welcome!", 11 react: WelcomeEmail({ name: "Friend" }), 12 }); 13 if (error) return Response.json({ error }, { status: 500 }); 14 return Response.json(data); 15}

Note: On the free tier, you can send to your own email from onboarding@resend.dev — no domain setup needed for testing.


Step 4 → AI with Mastra

Mastra is a TypeScript framework for AI agents. Built on Vercel's AI SDK, supports 40+ providers.

Standalone project:

1npm create mastra@latest

Or add to your existing Next.js app:

1npm install @mastra/core @ai-sdk/anthropic

Create your first agent — src/mastra/agents/index.ts:

1import { Agent } from "@mastra/core/agent"; 2import { anthropic } from "@ai-sdk/anthropic"; 3 4export const myAgent = new Agent({ 5 name: "Orangutan Assistant", 6 instructions: "You are a helpful assistant for the Orangutan Kit project.", 7 model: anthropic("claude-sonnet-4-20250514"), 8});

Test it locally:

1npx mastra dev

This starts a playground at http://localhost:4111 where you can chat with your agent before wiring it into your app.

To use in Next.js: Mastra provides handleChatStream() for API routes and works with Vercel AI SDK's useChat() hook on the frontend.


Step 5 → Install Claude Code

Claude Code is an AI coding agent that lives in your terminal. It reads your codebase, edits files, runs commands, and manages git.

Terminal install

1npm install -g @anthropic-ai/claude-code 2cd orangutan-app 3claude

First run opens a browser to authenticate. After that, you're in.

In Cursor IDE

Easiest way: Open the Extensions panel → search "Claude Code" → install the official Anthropic extension → click the Claude icon to log in.

If that fails: Install manually:

1cursor --install-extension ~/.claude/local/node_modules/@anthropic-ai/claude-code/vendor/claude-code.vsix

Or just use the terminal: Open Cursor's integrated terminal and run claude. Type /ide if it doesn't auto-detect Cursor.

Commands you'll actually use

CommandWhat it does
/initGenerate a CLAUDE.md for your project
/compactCompress context when conversation gets long
/clearHard reset for a new task
/modelSwitch models (Sonnet, Opus, Haiku)
/ideConnect to your IDE from external terminal
/costCheck token usage

Step 6 → Set Up MCP Servers

MCP (Model Context Protocol) lets Claude talk directly to your tools. Instead of copy-pasting database schemas or reading docs yourself, Claude can just look things up.

Supabase MCP

1claude mcp add supabase --url "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF"

It opens a browser for auth. No tokens to manage.

Mastra Docs MCP

1claude mcp add mastra-docs -- npx -y @mastra/mcp-docs-server@latest

Now Claude has Mastra's entire documentation available in every session.

For Cursor / VS Code

Create .cursor/mcp.json (or .mcp.json) in your project root:

1{ 2 "mcpServers": { 3 "supabase": { 4 "type": "url", 5 "url": "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF" 6 }, 7 "mastra": { 8 "command": "npx", 9 "args": ["-y", "@mastra/mcp-docs-server@latest"] 10 } 11 } 12}

⚠️ Only use the Supabase MCP with dev projects. Never connect it to production data.


Step 7 → Write Your CLAUDE.md

This is the single biggest productivity lever. Claude reads this file at the start of every session.

Run /init inside Claude Code to generate a starter, then trim it down to what matters. Here's a template:

1# Orangutan Kit 2Next.js 15 app with Supabase, Resend email, and Mastra AI agents. 3 4## Commands 5- `npm run dev` — dev server (port 3000) 6- `npm run build` — production build 7- `npm run lint` — ESLint 8- `npx mastra dev` — Mastra playground (port 4111) 9 10## Architecture 11- /src/app — Pages, layouts, API routes 12- /src/components — Reusable React components 13- /src/lib/supabase — Supabase client utilities 14- /src/mastra — AI agents, tools, workflows 15 16## Code Style 17- TypeScript strict, no `any` 18- ES module imports 19- Tailwind only, no custom CSS files 20- Server Components by default 21 22## Rules 23- NEVER commit .env.local 24- Agent definitions go in /src/mastra/agents/ 25- Use @supabase/ssr for server-side clients

Keep it under 200 lines. If it's longer, Claude starts ignoring rules uniformly. Put domain-specific knowledge in .claude/skills/ instead.


ToolDocs
Next.jsnextjs.org/docs
Supabasesupabase.com/docs
Convexdocs.convex.dev
Resendresend.com/docs
Mastramastra.ai/docs
Claude Codecode.claude.com/docs
Supabase MCPsupabase.com/docs/guides/getting-started/mcp
Mastra MCPmastra.ai/docs/build-with-ai/mcp-docs-server


📋 COPY-PASTE SECTION: Feed This to an AI Agent

Everything below is a self-contained prompt. Copy the entire block and paste it into Claude Code, Cursor, or any AI coding agent to have it set up the Orangutan Kit for you.


1You are setting up a project called "The Orangutan Kit" — a full-stack TypeScript development toolkit. Follow these steps exactly. Ask me to choose between Supabase or Convex before starting Step 2. 2 3## STEP 1: SCAFFOLD NEXT.JS 4 5Run: 6 npx create-next-app@latest orangutan-app --yes 7 cd orangutan-app 8 9This creates a Next.js 15 app with TypeScript, Tailwind CSS, ESLint, App Router, and Turbopack. 10 11Create these folders if they don't exist: 12 src/lib/ 13 src/components/ 14 src/mastra/agents/ 15 16## STEP 2A: IF SUPABASE — Install Database 17 18Run: 19 npm install @supabase/supabase-js @supabase/ssr 20 21Create file src/lib/supabase/client.ts: 22 import { createBrowserClient } from "@supabase/ssr"; 23 export function createClient() { 24 return createBrowserClient( 25 process.env.NEXT_PUBLIC_SUPABASE_URL!, 26 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! 27 ); 28 } 29 30Create file src/lib/supabase/server.ts: 31 import { createServerClient } from "@supabase/ssr"; 32 import { cookies } from "next/headers"; 33 export async function createClient() { 34 const cookieStore = await cookies(); 35 return createServerClient( 36 process.env.NEXT_PUBLIC_SUPABASE_URL!, 37 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, 38 { cookies: { getAll() { return cookieStore.getAll(); }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options)); } } } 39 ); 40 } 41 42Add to .env.local: 43 NEXT_PUBLIC_SUPABASE_URL=PLACEHOLDER 44 NEXT_PUBLIC_SUPABASE_ANON_KEY=PLACEHOLDER 45 46Tell me to fill in the real values from my Supabase dashboard. 47 48## STEP 2B: IF CONVEX — Install Database 49 50Run: 51 npm install convex 52 53Create file src/app/ConvexClientProvider.tsx: 54 "use client"; 55 import { ConvexProvider, ConvexReactClient } from "convex/react"; 56 const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!); 57 export default function ConvexClientProvider({ children }: { children: React.ReactNode }) { 58 return <ConvexProvider client={convex}>{children}</ConvexProvider>; 59 } 60 61Wrap the children in src/app/layout.tsx with <ConvexClientProvider>. 62 63Tell me to run `npx convex dev` in a separate terminal to initialize the backend. 64 65## STEP 3: INSTALL EMAIL (RESEND) 66 67Run: 68 npm install resend @react-email/components 69 70Create file src/components/email-template.tsx: 71 import * as React from "react"; 72 export function WelcomeEmail({ name }: { name: string }) { 73 return (<div><h1>Welcome, {name}!</h1><p>Thanks for joining the Orangutan Kit.</p></div>); 74 } 75 76Create file src/app/api/send/route.ts: 77 import { Resend } from "resend"; 78 import { WelcomeEmail } from "@/components/email-template"; 79 const resend = new Resend(process.env.RESEND_API_KEY); 80 export async function POST() { 81 const { data, error } = await resend.emails.send({ 82 from: "Orangutan Kit <onboarding@resend.dev>", 83 to: ["delivered@resend.dev"], 84 subject: "Welcome!", 85 react: WelcomeEmail({ name: "Friend" }), 86 }); 87 if (error) return Response.json({ error }, { status: 500 }); 88 return Response.json(data); 89 } 90 91Add to .env.local: 92 RESEND_API_KEY=PLACEHOLDER 93 94Tell me to fill in my Resend API key. 95 96## STEP 4: INSTALL AI (MASTRA) 97 98Run: 99 npm install @mastra/core @ai-sdk/anthropic 100 101Create file src/mastra/agents/index.ts: 102 import { Agent } from "@mastra/core/agent"; 103 import { anthropic } from "@ai-sdk/anthropic"; 104 export const orangutanAgent = new Agent({ 105 name: "Orangutan Assistant", 106 instructions: "You are a helpful AI assistant for the Orangutan Kit project. Help users with their code, answer questions about the stack, and suggest improvements.", 107 model: anthropic("claude-sonnet-4-20250514"), 108 }); 109 110Add to .env.local: 111 ANTHROPIC_API_KEY=PLACEHOLDER 112 113## STEP 5: CONFIGURE MCP SERVERS 114 115Create file .mcp.json in the project root: 116 { 117 "mcpServers": { 118 "supabase": { 119 "type": "url", 120 "url": "https://mcp.supabase.com/mcp?project_ref=PLACEHOLDER" 121 }, 122 "mastra": { 123 "command": "npx", 124 "args": ["-y", "@mastra/mcp-docs-server@latest"] 125 } 126 } 127 } 128 129If using Convex instead of Supabase, remove the supabase entry from mcpServers. 130 131Also create .cursor/mcp.json with the same content (for Cursor IDE support). 132 133Tell me to run these commands in Claude Code to register the servers: 134 claude mcp add mastra-docs -- npx -y @mastra/mcp-docs-server@latest 135 claude mcp add supabase --url "https://mcp.supabase.com/mcp?project_ref=PLACEHOLDER" 136 137## STEP 6: CREATE CLAUDE.md 138 139Create file CLAUDE.md in the project root: 140 141 # Orangutan Kit 142 Next.js 15 app with [Supabase/Convex], Resend email, and Mastra AI agents. 143 144 ## Commands 145 - `npm run dev` — Start dev server (port 3000) 146 - `npm run build` — Production build 147 - `npm run lint` — ESLint check 148 - `npx mastra dev` — Mastra playground (port 4111) 149 150 ## Architecture 151 - /src/app — Next.js App Router pages, layouts, API routes 152 - /src/components — Reusable React components 153 - /src/lib — Utilities (Supabase clients, helpers) 154 - /src/mastra — AI agents, tools, workflows 155 - /convex — Convex backend functions (if using Convex) 156 157 ## Code Style 158 - TypeScript strict mode, no `any` types 159 - ES module imports (import/export, not require) 160 - Tailwind CSS for all styling, no custom CSS files 161 - Server Components by default, add "use client" only when needed 162 - Named exports preferred over default exports 163 164 ## Important Rules 165 - NEVER commit .env.local 166 - All AI agent definitions go in /src/mastra/agents/ 167 - Use @supabase/ssr for server-side Supabase clients (not @supabase/supabase-js directly) 168 - API routes go in /src/app/api/ 169 - Test email routes with onboarding@resend.dev on free tier 170 171## STEP 7: VERIFY 172 173Run `npm run dev` and confirm the app loads at http://localhost:3000. 174List all files created and summarize what was set up. 175Remind me of all the PLACEHOLDER values I need to fill in.

That's the whole kit. Go build something. 🦧

🦧 The Orangutan Kit | MDX Limo