Your First Project

Build a complete feature with Bootspring in 10 minutes. This hands-on tutorial shows you how to use agents, skills, and quality gates together.

What We'll Build#

A user authentication system with:

  • Sign up and login pages
  • Database schema for users
  • API endpoints for auth
  • Form validation
  • Security best practices

Prerequisites#

  • Node.js 18+ installed
  • A Next.js project (or create one: npx create-next-app@latest my-app)
  • An MCP-compatible AI assistant (Claude Code, Cursor, etc.)

Step 1: Authenticate and Initialize#

Open your terminal in your project directory:

# Authenticate and link to a project bootspring auth login

This opens your browser to:

  1. Sign in to your Bootspring account
  2. Select an existing project or create a new one
  3. Link this directory to your project

Then initialize Bootspring:

bootspring init

You'll see:

✓ Created bootspring.config.js ✓ Created .mcp.json ✓ Generated CLAUDE.md Bootspring is ready! Open your AI assistant to get started.

Step 2: Open Your AI Assistant#

Open Claude Code, Cursor, or your preferred AI assistant in your project directory. The MCP connection will be established automatically.

Verify it's working by asking:

What Bootspring tools are available?

You should see a list including bootspring_agent, bootspring_skill, bootspring_quality, and more.

Step 3: Plan the Architecture#

Let's start by getting architectural guidance. Ask your AI assistant:

Use the architecture-expert agent to help me plan a user authentication system for this Next.js app. I want email/password login with JWT tokens.

The architecture-expert will respond with:

  • Recommended approach (e.g., NextAuth vs custom)
  • Component structure
  • API route design
  • Security considerations
  • Database schema suggestions

Example response:

For a Next.js app with JWT authentication, I recommend:

Architecture:

  • Use NextAuth.js for session management (or custom JWT if you need more control)
  • Store users in PostgreSQL with Prisma
  • Hash passwords with bcrypt
  • Use HTTP-only cookies for tokens

Files to create:

app/ ├── (auth)/ │ ├── login/page.tsx │ └── signup/page.tsx ├── api/ │ └── auth/ │ ├── login/route.ts │ ├── signup/route.ts │ └── me/route.ts lib/ ├── auth.ts └── db.ts prisma/ └── schema.prisma

Step 4: Design the Database Schema#

Now let's design the user schema. Ask:

Use the database-expert agent to create a Prisma schema for user authentication with email verification and password reset support.

The database-expert will provide:

1// prisma/schema.prisma 2 3model User { 4 id String @id @default(cuid()) 5 email String @unique 6 passwordHash String 7 name String? 8 emailVerified DateTime? 9 createdAt DateTime @default(now()) 10 updatedAt DateTime @updatedAt 11 12 sessions Session[] 13 tokens VerificationToken[] 14} 15 16model Session { 17 id String @id @default(cuid()) 18 userId String 19 token String @unique 20 expiresAt DateTime 21 createdAt DateTime @default(now()) 22 23 user User @relation(fields: [userId], references: [id], onDelete: Cascade) 24 25 @@index([userId]) 26} 27 28model VerificationToken { 29 id String @id @default(cuid()) 30 userId String 31 token String @unique 32 type String // "email_verification" | "password_reset" 33 expiresAt DateTime 34 createdAt DateTime @default(now()) 35 36 user User @relation(fields: [userId], references: [id], onDelete: Cascade) 37 38 @@index([userId]) 39 @@index([token]) 40}

Apply the schema:

npx prisma db push

Step 5: Build the API Endpoints#

Use skills to generate production-ready API code:

Use the api-endpoint skill to create a POST /api/auth/signup endpoint that creates a new user with email and password.

The skill generates:

1// app/api/auth/signup/route.ts 2 3import { NextRequest, NextResponse } from 'next/server'; 4import { z } from 'zod'; 5import bcrypt from 'bcryptjs'; 6import { prisma } from '@/lib/db'; 7 8const signupSchema = z.object({ 9 email: z.string().email('Invalid email address'), 10 password: z.string().min(8, 'Password must be at least 8 characters'), 11 name: z.string().min(1, 'Name is required').optional(), 12}); 13 14export async function POST(request: NextRequest) { 15 try { 16 const body = await request.json(); 17 const { email, password, name } = signupSchema.parse(body); 18 19 // Check if user exists 20 const existingUser = await prisma.user.findUnique({ 21 where: { email }, 22 }); 23 24 if (existingUser) { 25 return NextResponse.json( 26 { error: 'Email already registered' }, 27 { status: 400 } 28 ); 29 } 30 31 // Hash password 32 const passwordHash = await bcrypt.hash(password, 12); 33 34 // Create user 35 const user = await prisma.user.create({ 36 data: { 37 email, 38 passwordHash, 39 name, 40 }, 41 select: { 42 id: true, 43 email: true, 44 name: true, 45 createdAt: true, 46 }, 47 }); 48 49 return NextResponse.json(user, { status: 201 }); 50 } catch (error) { 51 if (error instanceof z.ZodError) { 52 return NextResponse.json( 53 { error: 'Validation failed', details: error.errors }, 54 { status: 400 } 55 ); 56 } 57 58 console.error('Signup error:', error); 59 return NextResponse.json( 60 { error: 'Internal server error' }, 61 { status: 500 } 62 ); 63 } 64}

Now create the login endpoint:

Use the api-endpoint skill to create a POST /api/auth/login endpoint that authenticates a user and returns a JWT token.

Step 6: Build the Frontend#

Ask the frontend-expert to create the login form:

Use the frontend-expert agent to create a login form component with React Hook Form, Zod validation, loading states, and error handling. Use Tailwind CSS for styling.

Generated component:

1// components/auth/LoginForm.tsx 2 3'use client'; 4 5import { useState } from 'react'; 6import { useForm } from 'react-hook-form'; 7import { zodResolver } from '@hookform/resolvers/zod'; 8import { z } from 'zod'; 9import { useRouter } from 'next/navigation'; 10 11const loginSchema = z.object({ 12 email: z.string().email('Please enter a valid email'), 13 password: z.string().min(1, 'Password is required'), 14}); 15 16type LoginFormData = z.infer<typeof loginSchema>; 17 18export function LoginForm() { 19 const router = useRouter(); 20 const [error, setError] = useState<string | null>(null); 21 22 const { 23 register, 24 handleSubmit, 25 formState: { errors, isSubmitting }, 26 } = useForm<LoginFormData>({ 27 resolver: zodResolver(loginSchema), 28 }); 29 30 const onSubmit = async (data: LoginFormData) => { 31 setError(null); 32 33 try { 34 const response = await fetch('/api/auth/login', { 35 method: 'POST', 36 headers: { 'Content-Type': 'application/json' }, 37 body: JSON.stringify(data), 38 }); 39 40 if (!response.ok) { 41 const result = await response.json(); 42 throw new Error(result.error || 'Login failed'); 43 } 44 45 router.push('/dashboard'); 46 router.refresh(); 47 } catch (err) { 48 setError(err instanceof Error ? err.message : 'An error occurred'); 49 } 50 }; 51 52 return ( 53 <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> 54 {error && ( 55 <div className="p-3 text-sm text-red-600 bg-red-50 border border-red-200 rounded-lg"> 56 {error} 57 </div> 58 )} 59 60 <div> 61 <label htmlFor="email" className="block text-sm font-medium text-gray-700"> 62 Email 63 </label> 64 <input 65 {...register('email')} 66 type="email" 67 id="email" 68 autoComplete="email" 69 className="mt-1 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" 70 /> 71 {errors.email && ( 72 <p className="mt-1 text-sm text-red-600">{errors.email.message}</p> 73 )} 74 </div> 75 76 <div> 77 <label htmlFor="password" className="block text-sm font-medium text-gray-700"> 78 Password 79 </label> 80 <input 81 {...register('password')} 82 type="password" 83 id="password" 84 autoComplete="current-password" 85 className="mt-1 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" 86 /> 87 {errors.password && ( 88 <p className="mt-1 text-sm text-red-600">{errors.password.message}</p> 89 )} 90 </div> 91 92 <button 93 type="submit" 94 disabled={isSubmitting} 95 className="w-full rounded-lg bg-blue-600 px-4 py-2 text-white font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed" 96 > 97 {isSubmitting ? 'Signing in...' : 'Sign in'} 98 </button> 99 </form> 100 ); 101}

Step 7: Security Review#

Before deploying, get a security review:

Use the security-expert agent to review the authentication code we just created and identify any security issues.

The security-expert will check for:

  • Password hashing strength
  • SQL injection vulnerabilities
  • XSS prevention
  • CSRF protection
  • Rate limiting recommendations
  • Secure cookie settings

Example findings:

Security Review Results:

✅ Password hashing with bcrypt (cost factor 12) - Good ✅ Input validation with Zod - Good ✅ Parameterized queries via Prisma - Good

⚠️ Recommendations:

  1. Add rate limiting to prevent brute force attacks
  2. Use HTTP-only, Secure, SameSite cookies for tokens
  3. Add CSRF protection for form submissions
  4. Implement account lockout after failed attempts

Step 8: Run Quality Gates#

Before committing, run quality checks:

Run the pre-commit quality gate on the auth files.

Bootspring will:

  • Run TypeScript type checking
  • Execute linting rules
  • Check for security issues
  • Verify code formatting
Quality Gate: pre-commit ======================== ✓ TypeScript: No errors ✓ ESLint: 0 errors, 2 warnings ✓ Security: No vulnerabilities ✓ Format: All files formatted Result: PASSED

Step 9: Commit Your Changes#

Now you can safely commit:

git add . git commit -m "feat: add user authentication system"

What We Accomplished#

In 10 minutes, we:

  1. Initialized Bootspring with context generation
  2. Planned architecture with the architecture-expert
  3. Designed database schema with the database-expert
  4. Built API endpoints using the api-endpoint skill
  5. Created frontend components with the frontend-expert
  6. Reviewed security with the security-expert
  7. Validated quality with pre-commit gates

Key Takeaways#

Agent Chaining#

For complex features, chain multiple agents:

  1. architecture-expert - Plan the approach
  2. database-expert - Design the data layer
  3. backend-expert - Implement server logic
  4. frontend-expert - Build the UI
  5. security-expert - Review for vulnerabilities
  6. testing-expert - Write tests

Skills for Speed#

Use skills for common patterns:

  • api-endpoint - RESTful endpoints
  • react-component - React components
  • prisma-crud - Database operations
  • auth-flow - Authentication patterns

Quality Gates for Confidence#

Always run quality gates before committing:

  • pre-commit - Quick checks (lint, types)
  • pre-push - Thorough checks (tests, build)
  • pre-deploy - Full audit (security, performance)

Next Steps#