This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is the BuildLoom web application, an AI-powered tech stack recommendation engine. It's an Astro-based application using server-side rendering (SSR) with Anthropic Claude AI integration (via Vercel AI SDK) for intelligent tech stack recommendations. The app uses PostgreSQL with Drizzle ORM for data persistence, SCSS for styling, and is deployed on Vercel.
Run all commands from the project root:
npm install- Install dependenciesnpm run dev- Start development server atlocalhost:4321npm run build- Build production site for deploymentnpm run preview- Preview production build locallynpm run astro ...- Run Astro CLI commands (e.g.,npm run astro add,npm run astro check)
IMPORTANT: This project uses server-side rendering (SSR), not static site generation (SSG). The astro.config.mjs sets output: 'server' with the Vercel adapter. API routes and pages that need dynamic behavior must include export const prerender = false;.
- src/pages/ - File-based routing with two sections:
- Marketing pages:
index.astro,about.astro,contact.astro - App pages:
app/index.astro,app/chat.astro
- Marketing pages:
- src/pages/api/ - API routes for backend functionality
api/message/generate.ts- Main AI chat endpoint (uses Anthropic Claude via Vercel AI SDK)
- src/lib/ - Shared utilities and services
config.ts- Application configuration (model, system prompts, tools)prompt.ts- System prompt for Stack Generator AItypes.ts- TypeScript interfaces (Tool, Category, Mode, etc.)tools.ts- AI tools loader (dynamically imports all tools fromtools/)tools/*.ts- Individual AI tool implementations
- src/db/ - Database layer
schema.ts- Drizzle ORM schema (threads, mega_list, company_info tables)initialize.ts- Database client initialization
- src/layouts/ - Page layouts (dual layout system)
Layout.astro- Marketing site layout (Header + Hero + Footer)App.astro- Application layout (Nav + Footer, no Hero)
- src/components/ - Reusable Astro components
- Global:
Header.astro,Footer.astro,Hero.astro,FancyCard.astro - App-specific:
app/Nav.astro
- Global:
- src/styles/ - SCSS stylesheets organized by type:
reset.scss- CSS resetvariables/- SCSS variables (globals.scss,colors.scss)components/- Component styles (includingapp/subfolder)layouts/- Layout-specific styles (Layout.scss,App.scss)pages/- Page-specific styles
The project has two distinct layouts for different sections:
-
Marketing Layout (
Layout.astro):- Used for: homepage, about, contact pages
- Includes: Header, Hero (homepage only), Footer
- Title format: "BuildLoom" or "{title} | BuildLoom"
- Imports:
reset.scss,Layout.scss - Typography: Montserrat (Google Fonts)
-
App Layout (
App.astro):- Used for:
/app/*pages (app interface) - Includes: Nav, Footer (no Hero)
- Title format: "BuildLoom App" or "{title} | BuildLoom App"
- Imports:
reset.scss,Layout.scss,App.scss - Includes Font Awesome icons via CDN
- Body has
class="app-layout", main hasclass="main app" - Typography: Montserrat (Google Fonts)
- Used for:
The application uses Anthropic's Claude AI for generating tech stack recommendations:
- Model: Claude Sonnet 4.5 (
claude-sonnet-4.5) - SDK: Vercel AI SDK (
aipackage v5.0.81) with Anthropic provider (@ai-sdk/anthropicv2.0.38) - System Prompt: Defined in
src/lib/prompt.ts- guides AI to provide tech stack recommendations - Tools: AI has access to custom tools (search, calculate) for enhanced functionality
Key files:
src/lib/config.ts- Model configuration, system prompt, and toolssrc/lib/prompt.ts- System prompt for BuildLoom assistantsrc/lib/tools.ts- Dynamic tool loadersrc/lib/tools/search.ts- Web search using Exa APIsrc/lib/tools/calculate.ts- Mathematical calculationssrc/pages/api/message/generate.ts- API endpoint handling conversation flow
Environment Requirements:
ANTHROPIC_API_KEY- Anthropic API key for Claude accessEXA_SEARCH_API_KEY- Exa API key for web search functionality- Database credentials (see Database section below)
POST /api/message/generate:
- Accepts:
{ text: string, id?: string, isPublic?: boolean }(user message, optional thread ID, public flag) - Returns:
{ generatedText: string, generatedTitle: boolean, id: string, ...extractedData } - Flow:
- Authenticates user via
locals.auth()(requires authentication) - Generates or retrieves thread ID using
nanoid - Enforces thread limit per user (max 5 threads, configurable in
config.ts) - Fetches conversation history from PostgreSQL (if thread exists)
- Verifies thread ownership (prevents unauthorized access)
- Builds conversation with system message + history + new user message
- Invokes Claude AI using
generateText()with tools and max 25 steps - Generates conversation title on first message using separate AI call
- Saves conversation to PostgreSQL (creates new or updates existing thread)
- Returns AI response with thread ID and title
- Authenticates user via
Key Features:
- Extensive logging with request IDs for debugging
- Thread ownership verification
- Per-user thread limits
- Public/private thread support
- Development mode tracking (
isDevflag)
Database: PostgreSQL (hosted on Vercel Postgres)
ORM: Drizzle ORM v0.44.7 with drizzle-kit v0.31.6
Key files:
src/db/schema.ts- Database schema definitionssrc/db/initialize.ts- Database client initializationdrizzle.config.ts- Drizzle configuration for migrations
Database Schema:
-
threads table:
id(text, primary key) - Thread identifiertitle(text) - Conversation titlethread(jsonb) - Message history:{ messages: [{ role, content }] }cost(numeric) - Cost tracking in dollarsemail(text) - User email (for ownership)isPublic(boolean) - Public accessibility flagisDev(boolean) - Development/test flagcreatedAt(timestamp) - Creation timestampupdatedAt(timestamp) - Last update timestamp
-
mega_list table:
name(text, primary key)type(text) - Technology typesubtype(text) - Technology subtype- Timestamps
-
company_info table:
name(text, primary key) - Product nameprovider(text)subcategory(text)description(text)keyfeature(text)documentation(text)- Timestamps
Environment Variables:
POSTGRES_URL- PostgreSQL connection string (pooled)DATABASE_URL- Alternative connection stringDATABASE_URL_UNPOOLED- Direct connection (without pgbouncer)- Individual parameters:
PGHOST,PGUSER,PGDATABASE,PGPASSWORD
The application has an extensible AI tools system located in src/lib/tools/:
Tool Loading:
src/lib/tools.tsdynamically imports all tools fromtools/*.ts(except files starting with_)- Tools use Vercel AI SDK's
tool()function with Zod schemas - Tools are automatically registered and available to the AI
Available Tools:
-
search (
tools/search.ts):- Web search using Exa API
- Input:
query(string) - Returns: Search results with content
-
calculate (
tools/calculate.ts):- Mathematical calculations
- Operations: add, subtract, multiply, divide, power, sqrt, modulo, abs, ceil, floor, round
- Input:
operation,a, optionalb - Returns: Calculation result
-
updateThreadCost (
tools/updateThreadCost.ts):- Updates thread cost tracking (implementation not shown)
Adding New Tools:
- Create a new file in
src/lib/tools/*.ts - Export a
tool()using Vercel AI SDK format with Zod schema - File will be automatically loaded by
tools.ts
- SCSS with modular organization
- Variables:
src/styles/variables/globals.scssandcolors.scss - Component-specific styles in matching file structure
- Typography: Montserrat (Google Fonts) for both layouts
- Icons: Font Awesome (via CDN) for app layout only
- astro.config.mjs - SSR mode with Vercel adapter (
output: 'server') - drizzle.config.ts - Drizzle ORM configuration (PostgreSQL dialect, migrations in
src/db/migrations) - tsconfig.json - TypeScript strict mode (extends
astro/tsconfigs/strict) - package.json - Project name: "build-loom", version 0.0.1, uses ES modules
- .gitignore - Excludes
dist/,.astro/,.vercel/,node_modules/,.env*
- Astro v5.15.1 (SSR framework with Vercel adapter)
- Anthropic Claude AI via Vercel AI SDK:
aiv5.0.81 (Vercel AI SDK)@ai-sdk/anthropicv2.0.38
- PostgreSQL with Drizzle ORM:
drizzle-ormv0.44.7@vercel/postgresv0.10.0drizzle-kitv0.31.6 (dev)
- Exa Search API (
exa-jsv1.10.2) for web search - SCSS/Sass v1.93.2 (styling)
- TypeScript with strict configuration
- nanoid v5.1.6 (unique ID generation)
- marked v16.4.1 (Markdown parsing)
- Deployment: Vercel
- Install dependencies:
npm install - Configure environment variables: Create
.envfile with:ANTHROPIC_API_KEY- Anthropic API keyEXA_SEARCH_API_KEY- Exa search API keyPOSTGRES_URL- PostgreSQL connection string (or individualPGHOST,PGUSER,PGDATABASE,PGPASSWORD)- See
.env.neededfor template
- Set up database: Ensure PostgreSQL database is created and accessible
- Run migrations (if needed): Use drizzle-kit to run migrations
- Start development server:
npm run dev