Build a SaaS with Grit + Claude Code
In this course, you will build a real project management SaaS — teams, projects, tasks, members, and a billing page — using Grit for the foundation and Claude Code as your AI-powered pair programmer for feature development.
What We're Building
Our project management SaaS will include:
- • Teams — organizations that group members together
- • Projects — belong to a team, have a name, description, and status
- • Tasks — belong to a project, assigned to team members, have priority and due dates
- • Members — users who belong to a team with different roles
- • Billing page — pricing tiers (Free, Pro, Team) for the SaaS model
The twist: instead of building every feature by hand, you will use Claude Code to accelerate development. Grit provides the structure, Claude Code fills in the features.
Challenge: Name 5 SaaS Products
Name 5 SaaS products you use daily. For each, identify: what problem it solves, whether it's free or paid, and what makes it sticky (why you keep using it instead of switching to an alternative).
Why Claude Code + Grit?
Every Grit project ships with a skill file that teaches Claude Code how your project works:
.claude/skills/grit/SKILL.md that teaches AI assistants about your project's conventions, patterns, and structure. It tells Claude Code things like: where models live, how routes are structured, what code markers to use for injections, and how the admin panel works. Think of it as an onboarding document — but for AI.Because Grit follows strict conventions (file locations, naming patterns, code markers), Claude Code can work with your project reliably. It knows:
- • Where to add new models (
internal/models/) - • Where to add new handlers (
internal/handlers/) - • How to register routes (using code markers)
- • How the admin panel resource system works
- • What the API response format looks like
Challenge: Find the Skill File
After scaffolding your project (next section), find the .claude/skills/ directory. Read the SKILL.md file. What conventions does it teach Claude Code about? List at least 5.
Scaffold the SaaS
Start with a Triple architecture scaffold — Go API, Next.js web app, and admin panel. This is the standard SaaS setup:
grit new saas-pm --triple --next --style modernThis gives you:
- • Go API — authentication, file storage, email, background jobs, AI service
- • Next.js Web — public-facing app where users interact with projects and tasks
- • Admin Panel — internal dashboard for managing users, data, and system health
- • Shared Package — Zod schemas and TypeScript types shared between frontends
- • Docker Compose — PostgreSQL, Redis, MinIO ready to go
--style modern flag gives you a clean, minimal design that works well for SaaS products. You can always customize it later.Challenge: Scaffold and Explore
Scaffold the project with the command above. Start the dev server with grit dev. Visit the web app, admin panel, and API health endpoint. Everything should work out of the box.
Design the Data Model
Now comes the power of Grit + Claude Code together. Instead of generating one resource at a time, ask Claude Code to generate all three in sequence:
Generate resources for a project management SaaS:
1. Team (name, slug)
2. Project (name, description, team_id:belongs_to:Team, status)
3. Task (title, description, priority:int, status,
assignee_id:belongs_to:User,
project_id:belongs_to:Project,
due_date:date:optional)Claude Code reads the skill file and knows to run grit generate resource for each one. For each resource, Grit creates:
- • Go model with GORM tags
- • Service layer with CRUD operations
- • HTTP handlers with validation
- • Zod schemas for frontend validation
- • TypeScript types
- • React Query hooks for data fetching
- • Admin panel resource definition
belongs_to syntax creates foreign key relationships. team_id:belongs_to:Team means the Project model has a TeamID field that references the Team model, with GORM automatically setting up the foreign key constraint.Challenge: Generate the Resources
Ask Claude Code to generate all three resources. Review what it creates — check the Go models, the API routes, and the admin panel. Are the relationships correct? Does belongs_to create the expected foreign keys?
AI-Assisted Feature Development
With the scaffolding done, use Claude Code to build features that go beyond basic CRUD. Here are examples of prompts that work well with Grit projects:
Add a dashboard page at /dashboard that shows:
- Total tasks by status (pie chart or count cards)
- My assigned tasks (filtered to current user)
- Recent activity across all projectsCreate a project board view at /projects/:id/board that shows
tasks in columns by status (Todo, In Progress, Review, Done).
Use drag-and-drop to move tasks between columns.Add team member invitation:
- API endpoint POST /api/teams/:id/invite (accepts email)
- Send invitation email using the Resend service
- Create a /join/:token page that accepts the invitationThe key to effective prompts with Claude Code:
- • Be specific about URLs — tell it exactly which route to create
- • Describe the UI — mention cards, tables, charts, columns
- • Reference existing patterns — "use the same style as the users page"
- • Review the output — always read what Claude Code generates before accepting
Challenge: Build a Feature with AI
Choose one of the three prompts above (dashboard, board view, or invitations) and give it to Claude Code. Review the generated code. Does it follow Grit conventions? Did it put files in the right locations? Make at least one refinement request.
Custom Dashboard
Every SaaS needs a dashboard — the first thing users see after logging in. Use Claude Code to build a data-rich dashboard with multiple widgets:
Build a custom dashboard at /dashboard with these widgets:
1. Stats row: Total Projects, Active Tasks, Completed This Week,
Overdue Tasks (4 cards with icons and counts)
2. Tasks by Status: bar chart showing task distribution
3. Tasks by Priority: colored badges showing High/Medium/Low counts
4. My Tasks: table of tasks assigned to me, sorted by due date
5. Team Activity: recent actions (task created, status changed, etc.)
Use the existing API endpoints. Add new endpoints if needed.Claude Code will create the frontend components and any custom API endpoints needed for aggregated data. It knows to use TanStack Query for data fetching and shadcn/ui components for the UI because the skill file tells it to.
Challenge: Build a Dashboard
Ask Claude Code to build a dashboard with at least 3 different widgets. After it generates the code, check: Does the data look correct? Are the API calls efficient (not N+1 queries)? Does the layout look good on both desktop and mobile?
API Customization
Grit generates standard CRUD endpoints, but a real SaaS needs custom business logic. Use Claude Code to add endpoints that go beyond CRUD:
# Tasks for a specific project
GET /api/projects/:id/tasks
# Assign a task to a team member
PUT /api/tasks/:id/assign
Body: { "assignee_id": "uuid-here" }
# Dashboard statistics (aggregated)
GET /api/dashboard/stats
Response: {
"total_projects": 12,
"active_tasks": 45,
"completed_this_week": 8,
"overdue_count": 3
}When asking Claude Code to create custom endpoints, be explicit about the request and response format. Grit's API follows a consistent pattern (data envelope, meta for lists, error format), and Claude Code knows this from the skill file.
Add a custom endpoint GET /api/dashboard/stats that returns:
- total_projects: count of all projects for the current user's team
- active_tasks: count of tasks with status != "done"
- completed_this_week: count of tasks completed in the last 7 days
- overdue_count: count of tasks past due_date with status != "done"
Follow the existing API response format. Add the route
to the authenticated group.Challenge: Add a Custom Endpoint
Ask Claude Code to create the GET /api/dashboard/stats endpoint. Test it with curl or your API client. Does it return accurate counts? Is it behind authentication?
Frontend Pages
With the API in place, build the key frontend pages. These are where Claude Code really shines — it can create complex React components much faster than writing them by hand:
- • Project Board — Kanban-style columns (Todo, In Progress, Review, Done) with tasks as cards
- • Task Detail — full task view with description, assignee, comments, status changes
- • Team Settings — manage members, roles, and team information
Build a project board page at /projects/[id]/board:
- Fetch tasks for this project from GET /api/projects/:id/tasks
- Display 4 columns: Todo, In Progress, Review, Done
- Each task shows: title, priority badge, assignee avatar, due date
- Clicking a task opens the task detail page
- Use the existing shadcn/ui Card component for task cardsChallenge: Build a Custom Page
Choose one of the three pages above and ask Claude Code to build it. Test the page — does it fetch data correctly? Does the layout work? Ask Claude Code to fix at least one issue you find.
Billing Page (UI Only)
Every SaaS needs a pricing page. For this course, you will build the UI — the visual layout of pricing tiers. Actual payment processing (Stripe, LemonSqueezy) would be added later via a Grit plugin.
Create a pricing page at /pricing with 3 plan cards:
Free Plan ($0/month):
- Up to 3 projects
- Up to 10 tasks per project
- 1 team member
- Basic support
Pro Plan ($12/month) — highlighted as "Most Popular":
- Unlimited projects
- Unlimited tasks
- Up to 10 team members
- Priority support
- File attachments
Team Plan ($29/month):
- Everything in Pro
- Unlimited team members
- Admin controls
- Audit log
- Custom integrations
- Dedicated support
Include a monthly/yearly toggle (yearly = 20% discount).
Use shadcn/ui Card components with the Grit dark theme.The pricing page is purely frontend — no API calls needed. It's a static page that shows the plans and (eventually) links to a payment provider.
Challenge: Build a Pricing Page
Ask Claude Code to build the pricing page. Review the design: Does the "Most Popular" card stand out? Does the monthly/yearly toggle work? Is the dark theme consistent with the rest of the app?
Deploy Your SaaS
With your SaaS built, deploy it to a server. Grit makes this a single command:
grit deploy --host deploy@server.com --domain pm.myapp.comThis builds the Go binary, uploads it, configures systemd and Caddy, and starts the service. Your SaaS is live at https://pm.myapp.com with automatic HTTPS.
Before deploying, make sure your production environment variables are set:
- •
APP_ENV=production - •
JWT_SECRET— a strong random string - •
DB_PASSWORD— a strong database password - •
RESEND_API_KEY— for real email delivery
Challenge: Deploy Your SaaS
Deploy your project management SaaS to a VPS. Create an account, log in, create a team, add a project, and create a few tasks. Does everything work in production exactly as it did in development?
What You Learned
- What a SaaS is and how to structure one with Grit
- How Claude Code + the Grit skill file accelerate development
- Generating related resources with
belongs_torelationships - Using Claude Code to build features beyond CRUD
- Building custom dashboards with data widgets
- Adding custom API endpoints for business logic
- Creating complex frontend pages with AI assistance
- Building a SaaS pricing page
- Deploying a SaaS to production
Challenge: Add 3 More Features
Using Claude Code, add these three features to your SaaS:
- Team member roles — owner, admin, member. Only owners and admins can invite members or delete projects.
- Task comments with mentions — users can comment on tasks and @mention team members.
- Email notifications — send an email when a task is assigned to someone, using Grit's Resend integration.
For each feature, write a clear prompt, review the output, and test it end-to-end.
Challenge: Ship It
Deploy the final version with all features. Create a demo account and walk through the entire workflow: sign up, create team, invite a member, create project, add tasks, assign tasks, comment on a task. Time yourself — how long does the full workflow take? Is the UX smooth?
Enjoying the course?
Help us grow — star us on GitHub, subscribe on YouTube, and follow on LinkedIn.