Skip to content

Workshop: SaaS MVP (4 hours) ​

Commercial License Required

This workshop uses MakerKit, which requires a commercial license. While Orchestre can help you build with it, you must obtain a valid license from MakerKit for commercial use.

Build a complete SaaS minimum viable product with user authentication, team management, subscription billing, and a functional application. Perfect for entrepreneurs and developers looking to launch quickly.

Workshop Overview ​

Duration: 4 hours Difficulty: Intermediate-Advanced Result: Launch-ready SaaS application

You'll build TeamTask - a project management SaaS with:

  • πŸ” User authentication with team invites
  • πŸ’³ Subscription billing (Free/Pro/Enterprise)
  • πŸ“Š Kanban board for task management
  • πŸ‘₯ Team collaboration features
  • πŸ“ˆ Analytics dashboard
  • πŸš€ Production deployment

Prerequisites ​

  • Orchestre installed
  • Stripe account (free test mode)
  • Basic understanding of SaaS concepts
  • 4 hours of focused time

Part 1: Foundation (45 minutes) ​

Project Setup ​

bash
/orchestre:create (MCP) teamtask makerkit-nextjs
cd teamtask

Strategic Planning ​

bash
/orchestre:orchestrate (MCP) "Build a project management SaaS MVP with:
- Kanban boards for visual task management
- Team workspaces with role-based permissions
- Three pricing tiers: Free (1 project), Pro ($29/mo, 10 projects), Enterprise ($99/mo, unlimited)
- Real-time collaboration
- Activity tracking and notifications
- API for integrations"

Environment Configuration ​

bash
# Setup environment
cp .env.example .env.local

# Configure essential services
/setup-stripe
/setup-oauth "Google and GitHub providers"

Update .env.local:

bash
# Database (Supabase recommended for quick start)
DATABASE_URL=postgresql://...

# Stripe
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PUBLISHABLE_KEY=pk_test_...

# OAuth
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

Part 2: Core Data Model (30 minutes) ​

Design the Schema ​

bash
/orchestre:execute-task (MCP) "Create data model for projects, boards, tasks, and team members with proper relationships"

Core models created:

prisma
model Organization {
  id           String    @id @default(cuid())
  name         String
  slug         String    @unique
  subscription Subscription?
  projects     Project[]
  members      Member[]
  invitations  Invitation[]
  createdAt    DateTime  @default(now())
}

model Project {
  id             String    @id @default(cuid())
  name           String
  description    String?
  organizationId String
  organization   Organization @relation(...)
  boards         Board[]
  activities     Activity[]
  createdAt      DateTime  @default(now())
}

model Board {
  id        String    @id @default(cuid())
  name      String
  position  Int
  projectId String
  project   Project   @relation(...)
  tasks     Task[]
}

model Task {
  id          String    @id @default(cuid())
  title       String
  description String?
  position    Int
  boardId     String
  board       Board     @relation(...)
  assigneeId  String?
  assignee    User?     @relation(...)
  dueDate     DateTime?
  priority    Priority  @default(MEDIUM)
  labels      Label[]
  comments    Comment[]
  activities  Activity[]
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
}

enum Priority {
  LOW
  MEDIUM
  HIGH
  URGENT
}

Run Migrations ​

bash
npm run db:migrate
npm run db:seed # Optional: seed with demo data

Part 3: Subscription System (45 minutes) ​

Configure Pricing Tiers ​

bash
/add-subscription-plan "Free tier: 1 project, 2 members, basic features"
/add-subscription-plan "Pro tier: 10 projects, 10 members, advanced features, $29/month"
/add-subscription-plan "Enterprise tier: Unlimited everything, priority support, $99/month"

Implement Feature Gates ​

bash
/execute-task "Add subscription-based feature gates and limits enforcement"

Feature gating example:

typescript
// lib/subscription-limits.ts
export const PLAN_LIMITS = {
  free: {
    projects: 1,
    members: 2,
    storage: 100, // MB
    features: ['basic_boards', 'basic_tasks']
  },
  pro: {
    projects: 10,
    members: 10,
    storage: 10000, // MB
    features: ['basic_boards', 'basic_tasks', 'advanced_analytics', 'api_access', 'integrations']
  },
  enterprise: {
    projects: -1, // unlimited
    members: -1,
    storage: -1,
    features: ['all']
  }
}

// Enforcement hook
export function useFeatureGate(feature: string) {
  const { subscription } = useSubscription()
  const plan = PLAN_LIMITS[subscription.plan]
  
  return {
    hasAccess: plan.features.includes(feature) || plan.features.includes('all'),
    limit: plan,
    showUpgrade: !plan.features.includes(feature)
  }
}

Billing Portal ​

bash
/execute-task "Create billing portal with subscription management"

Part 4: Core Application (1 hour) ​

Kanban Board ​

bash
/execute-task "Create drag-and-drop Kanban board with real-time updates"

Key implementation:

typescript
// components/KanbanBoard.tsx
'use client'

import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'
import { useOptimistic } from 'react'

export function KanbanBoard({ project }) {
  const [boards, setBoards] = useOptimistic(project.boards)
  
  const handleDragEnd = async (result) => {
    if (!result.destination) return
    
    // Optimistic update
    const newBoards = reorderTasks(boards, result)
    setBoards(newBoards)
    
    // Persist to database
    await updateTaskPosition({
      taskId: result.draggableId,
      boardId: result.destination.droppableId,
      position: result.destination.index
    })
  }
  
  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <div className="kanban-container">
        {boards.map(board => (
          <Droppable key={board.id} droppableId={board.id}>
            {(provided) => (
              <div
                ref={provided.innerRef}
                {...provided.droppableProps}
                className="board-column"
              >
                <h3>{board.name}</h3>
                {board.tasks.map((task, index) => (
                  <Draggable
                    key={task.id}
                    draggableId={task.id}
                    index={index}
                  >
                    {(provided) => (
                      <TaskCard
                        ref={provided.innerRef}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        task={task}
                      />
                    )}
                  </Draggable>
                ))}
                {provided.placeholder}
              </div>
            )}
          </Droppable>
        ))}
      </div>
    </DragDropContext>
  )
}

Task Management ​

bash
/execute-task "Implement task creation, editing, and assignment with notifications"

Team Features ​

bash
/execute-task "Create member invitation system with email notifications"
/execute-task "Implement role-based permissions (Owner, Admin, Member)"

Part 5: Real-time Collaboration (45 minutes) ​

WebSocket Setup ​

bash
/execute-task "Implement WebSocket server for real-time updates"

Live Cursors ​

bash
/execute-task "Add live cursor tracking for collaborative editing"

Implementation:

typescript
// hooks/useCollaboration.ts
export function useCollaboration(projectId: string) {
  const [collaborators, setCollaborators] = useState<Collaborator[]>([])
  const ws = useRef<WebSocket>()
  
  useEffect(() => {
    ws.current = new WebSocket(`${WS_URL}/project/${projectId}`)
    
    ws.current.on('user:joined', (user) => {
      setCollaborators(prev => [...prev, user])
    })
    
    ws.current.on('cursor:move', ({ userId, position }) => {
      setCollaborators(prev => 
        prev.map(c => c.id === userId 
          ? { ...c, cursor: position } 
          : c
        )
      )
    })
    
    ws.current.on('task:update', (task) => {
      // Update local state
      updateTask(task)
    })
    
    return () => ws.current?.close()
  }, [projectId])
  
  const broadcastCursor = (position: Position) => {
    ws.current?.send('cursor:move', position)
  }
  
  return { collaborators, broadcastCursor }
}

Activity Feed ​

bash
/execute-task "Create real-time activity feed with notifications"

Part 6: Analytics & Insights (30 minutes) ​

Analytics Dashboard ​

bash
/execute-task "Build analytics dashboard showing project metrics and team productivity"

Dashboard components:

typescript
// components/Analytics.tsx
export function AnalyticsDashboard({ organizationId }) {
  const { data: metrics } = useMetrics(organizationId)
  
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
      <MetricCard
        title="Active Projects"
        value={metrics.activeProjects}
        change={metrics.projectsChange}
        icon={<ProjectIcon />}
      />
      
      <MetricCard
        title="Tasks Completed"
        value={metrics.tasksCompleted}
        change={metrics.tasksChange}
        period="This week"
      />
      
      <MetricCard
        title="Team Velocity"
        value={`${metrics.velocity} tasks/week`}
        chart={<VelocityChart data={metrics.velocityHistory} />}
      />
      
      <MetricCard
        title="Avg Resolution Time"
        value={`${metrics.avgResolutionTime}h`}
        change={metrics.resolutionChange}
      />
    </div>
  )
}

Reports ​

bash
/execute-task "Generate weekly team productivity reports"

Part 7: API & Integrations (30 minutes) ​

REST API ​

bash
/add-api-endpoint "GET /api/v1/projects"
/add-api-endpoint "POST /api/v1/tasks"
/add-api-endpoint "PUT /api/v1/tasks/:id"
/add-api-endpoint "POST /api/v1/webhooks"

API Authentication ​

bash
/execute-task "Implement API key authentication for external integrations"

Webhook System ​

bash
/add-webhook "Task status changes"
/add-webhook "New team member added"
/add-webhook "Project completed"

Part 8: Launch Preparation (30 minutes) ​

Pre-launch Checklist ​

bash
/validate-implementation "SaaS MVP production readiness"

Checklist includes:

  • [ ] Authentication working
  • [ ] Billing integration tested
  • [ ] Email notifications configured
  • [ ] Error tracking setup
  • [ ] Performance optimized
  • [ ] Security audit passed
  • [ ] Legal pages added
  • [ ] Analytics configured

Add Essential Pages ​

bash
/execute-task "Create landing page with pricing"
/execute-task "Add terms of service and privacy policy"
/execute-task "Create help documentation"

Production Deployment ​

bash
/deploy-production

Testing Your SaaS ​

User Journey Test ​

  1. Sign Up Flow:

    • Register new account
    • Create organization
    • Choose plan
    • Complete payment
  2. Team Setup:

    • Invite team members
    • Set permissions
    • Create first project
  3. Core Features:

    • Create boards
    • Add tasks
    • Drag between columns
    • Assign to team
    • Track progress
  4. Subscription:

    • Upgrade plan
    • Add payment method
    • Download invoice

Complete Implementation Examples ​

1. Subscription Enforcement ​

typescript
// middleware/subscription.ts
export async function enforceSubscriptionLimits(
  req: Request,
  { params }: { params: { organizationId: string } }
) {
  const { subscription, usage } = await getSubscriptionAndUsage(params.organizationId)
  const limits = PLAN_LIMITS[subscription.plan]
  
  // Check project limit
  if (req.method === 'POST' && req.url.includes('/projects')) {
    if (limits.projects !== -1 && usage.projects >= limits.projects) {
      return NextResponse.json({
        error: 'Project limit reached',
        limit: limits.projects,
        upgrade_url: '/settings/billing'
      }, { status: 403 })
    }
  }
  
  // Check member limit
  if (req.method === 'POST' && req.url.includes('/invitations')) {
    if (limits.members !== -1 && usage.members >= limits.members) {
      return NextResponse.json({
        error: 'Member limit reached',
        limit: limits.members,
        upgrade_url: '/settings/billing'
      }, { status: 403 })
    }
  }
  
  return NextResponse.next()
}

2. Real-time Sync ​

typescript
// services/realtime.ts
export class RealtimeService {
  private io: Server
  
  broadcastTaskUpdate(task: Task, projectId: string) {
    this.io.to(`project:${projectId}`).emit('task:update', {
      type: 'UPDATE',
      task,
      timestamp: Date.now()
    })
  }
  
  broadcastBoardReorder(
    projectId: string,
    boardId: string,
    tasks: Task[]
  ) {
    this.io.to(`project:${projectId}`).emit('board:reorder', {
      boardId,
      tasks,
      timestamp: Date.now()
    })
  }
  
  notifyUserActivity(
    projectId: string,
    userId: string,
    activity: Activity
  ) {
    this.io.to(`project:${projectId}`).emit('user:activity', {
      userId,
      activity,
      timestamp: Date.now()
    })
  }
}

3. Analytics Tracking ​

typescript
// lib/analytics.ts
export class Analytics {
  async trackTaskCompleted(task: Task, userId: string) {
    const timeToComplete = Date.now() - task.createdAt.getTime()
    
    await this.events.track({
      event: 'task_completed',
      userId,
      properties: {
        taskId: task.id,
        projectId: task.board.projectId,
        timeToComplete,
        priority: task.priority,
        hadDueDate: !!task.dueDate,
        wasOverdue: task.dueDate ? task.dueDate < new Date() : false
      }
    })
    
    // Update team metrics
    await this.updateTeamVelocity(task.board.projectId)
  }
  
  async generateWeeklyReport(organizationId: string) {
    const metrics = await this.calculateMetrics(organizationId, 'week')
    
    return {
      tasksCompleted: metrics.completed,
      tasksCreated: metrics.created,
      velocity: metrics.velocity,
      topPerformers: metrics.topPerformers,
      bottlenecks: metrics.bottlenecks,
      recommendations: this.generateRecommendations(metrics)
    }
  }
}

Monetization Strategies ​

1. Freemium Model ​

  • Free tier to attract users
  • Clear upgrade prompts
  • Value-based pricing

2. Usage-Based Pricing ​

bash
/execute-task "Add usage-based pricing for API calls"

3. Enterprise Features ​

bash
/add-enterprise-feature "SSO authentication"
/add-enterprise-feature "Advanced security controls"
/add-enterprise-feature "Custom integrations"

Marketing & Growth ​

1. SEO Optimization ​

bash
/execute-task "Optimize landing page for search engines"

2. Product Hunt Launch ​

bash
/execute-task "Prepare Product Hunt launch materials"

3. Content Marketing ​

  • Start a blog
  • Create tutorials
  • Build in public

Performance Metrics ​

Target metrics:

  • Page Load: <2s
  • Time to Interactive: <3s
  • API Response: <200ms
  • WebSocket Latency: <50ms
  • Uptime: 99.9%

Scaling Considerations ​

As you grow:

  1. Database: Consider read replicas
  2. Caching: Implement Redis
  3. CDN: Use for global distribution
  4. Queue: Add job processing
  5. Monitoring: Enhanced observability

What You've Built ​

βœ… Complete SaaS MVP βœ… Subscription billing βœ… Team collaboration βœ… Real-time features βœ… Production deployed βœ… Ready to scale

Next Steps ​

Your SaaS is ready to launch! Consider:

  1. Beta Users: Get 10 beta users for feedback
  2. Marketing Site: Enhance landing page
  3. Content: Create onboarding videos
  4. Support: Set up customer support
  5. Analytics: Track user behavior
  6. Iterate: Ship improvements weekly

Resources ​

Congratulations! You've built a production-ready SaaS in 4 hours. Now go find your first customers!

Built with ❀️ for the AI Coding community, by Praney Behl