Skip to main content

What you’ll build

A project management SaaS where teams can create workspaces, organize tasks on Kanban boards, invite collaborators, and upgrade to a paid plan. The finished product includes user authentication, a free tier with limits, a Pro subscription via Stripe checkout, transactional email notifications, and one-click deployment to Netlify. By the end of this recipe you will have a production-ready app that you can customize, rebrand, and launch as your own product.

Tech stack

ServiceRole
Next.js + TypeScriptFrontend framework and API routes
SupabaseUser authentication, PostgreSQL database, file storage
StripeSubscription billing (free and Pro plans)
ResendTransactional emails (welcome, invites, receipts)
NetlifyProduction deployment and hosting

Architecture overview

Here is how the pieces connect:
  1. A visitor signs up using Supabase Auth (email/password or social login).
  2. After signup, they land on a dashboard where they can create a workspace and start adding tasks (stored in Supabase).
  3. The workspace owner can invite team members by email. Resend delivers the invitation.
  4. When the team is ready to unlock higher limits, the owner opens the pricing page and completes a Stripe Checkout session to subscribe to the Pro plan.
  5. Stripe webhooks update the subscription status in Supabase, and Resend sends a receipt email.
  6. The entire app is deployed to Netlify with environment variables configured for each service.

How long does it take?

PhaseWhat you’re buildingEstimated time
SetupProject, Supabase, auth5-10 minutes
Core featuresWorkspaces, tasks, teams10-15 minutes
MonetizationStripe, pricing, billing5-10 minutes
CommunicationEmail notifications5 minutes
LaunchDeploy, go live5 minutes
TotalComplete SaaS app30-45 minutes

Step-by-step build

1

Start a new project

Open rocket.new and create a new project. Give Rocket a detailed description of the app so it scaffolds the right pages, layout, and navigation from the start.
Build a project management SaaS called "Taskflow" using Next.js and TypeScript.
Include these pages: landing page with hero and feature sections, pricing page
with Free and Pro tiers, login page, signup page, dashboard with a sidebar,
workspace settings page, and a Kanban task board. Use a clean, modern design
with a blue and white color scheme. Add a responsive navbar with logo, navigation
links, and login/signup buttons.
Be specific about the pages and layout you want in your first prompt. The more detail you give, the less back-and-forth you will need later.
2

Connect Supabase

Go to Integrations in your Rocket project and connect your Supabase account via OAuth. Create a new Supabase project (or select an existing one), then ask Rocket to set up the database schema.
Connect Supabase and create the following database tables:

1. "profiles" - id (uuid, references auth.users), display_name (text),
   avatar_url (text), created_at (timestamp)
2. "workspaces" - id (uuid), name (text), owner_id (uuid, references profiles),
   plan (text, default 'free'), created_at (timestamp)
3. "workspace_members" - id (uuid), workspace_id (uuid, references workspaces),
   user_id (uuid, references profiles), role (text, either 'owner', 'admin',
   or 'member'), invited_at (timestamp), joined_at (timestamp)
4. "tasks" - id (uuid), workspace_id (uuid, references workspaces), title (text),
   description (text), status (text, either 'todo', 'in_progress', or 'done'),
   assignee_id (uuid, references profiles), created_by (uuid, references profiles),
   position (integer), created_at (timestamp), updated_at (timestamp)

Add row-level security policies so users can only access data in workspaces
they belong to. Create a trigger that automatically inserts a profile row
when a new user signs up.
Rocket handles the Supabase connection through OAuth, so you never need to copy API keys manually. Your credentials are encrypted and stored securely.
3

Build the signup and login flow

Now wire up authentication so users can create accounts and sign in. This prompt connects Supabase Auth to the signup and login pages that Rocket already scaffolded.
Implement user authentication using Supabase Auth:

- On the signup page, add email/password registration. After successful signup,
  redirect to the dashboard and show a welcome message.
- On the login page, add email/password login with a "Remember me" checkbox.
  Redirect to the dashboard after login.
- Add a "Forgot password" link on the login page that sends a password reset
  email via Supabase.
- Add Google sign-in as a social login option on both pages.
- Protect the dashboard, workspace, and settings pages so only logged-in users
  can access them. Redirect unauthenticated visitors to the login page.
- Add a user menu in the top-right corner of the dashboard with the user's
  name, avatar, and a sign-out button.
After Rocket builds the auth flow, preview the app and create a test account. Check the Supabase dashboard to confirm the user appeared in the auth.users table and that the profiles trigger fired.
4

Create workspaces and task boards

This is the core of the product. Users create a workspace, then manage tasks on a drag-and-drop Kanban board.
Build the workspace and task board features:

- After login, show a "My Workspaces" list on the dashboard. Include a
  "Create Workspace" button that opens a modal with a name field.
- When a user creates a workspace, automatically add them as the owner in
  the workspace_members table.
- Inside each workspace, show a Kanban board with three columns: To Do,
  In Progress, and Done.
- Users can create new tasks with a title and optional description.
  New tasks start in the "To Do" column.
- Support drag-and-drop to move tasks between columns. Save the new status
  and position to Supabase on drop.
- Each task card should show the title, assignee avatar, and a colored
  status badge.
- Clicking a task card opens a detail panel where users can edit the title,
  description, status, and assignee.
5

Add team member invitations

Let workspace owners invite collaborators by email. This step introduces the team collaboration flow.
Add team invitation functionality:

- In the workspace settings page, add a "Members" section that lists current
  members with their role (owner, admin, member).
- Add an "Invite Member" button that opens a modal with an email field and
  a role selector (admin or member).
- When the owner sends an invite, create a pending record in workspace_members
  with the invited email and role.
- If the invited person already has an account, show the workspace in their
  dashboard immediately. If not, they will see it after they sign up with
  that email address.
- The workspace owner can remove members or change their role from the
  members list.
- Limit the Free plan to 3 members per workspace. Show an upgrade prompt
  when the owner tries to invite a 4th member.
The email notification for invitations will be connected in Step 8 when we add Resend. For now, the invitation logic works through the database.
6

Connect Stripe for billing

Go to Integrations and connect Stripe using your test mode API keys. Then ask Rocket to build the subscription backend.
Connect Stripe and set up subscription billing:

- Create two Stripe products: "Taskflow Free" (free, no Stripe subscription
  needed) and "Taskflow Pro" at $19/month.
- Add a webhook handler that listens for checkout.session.completed,
  customer.subscription.updated, and customer.subscription.deleted events.
- When a user completes checkout, update their workspace's plan column
  in Supabase from 'free' to 'pro'.
- When a subscription is canceled or expires, revert the plan to 'free'.
- Store the Stripe customer ID and subscription ID in a new
  "subscriptions" table linked to the workspace.
- Add a billing page inside workspace settings that shows the current plan,
  next billing date, and a "Manage Subscription" button that opens the
  Stripe Customer Portal.
Use Stripe test mode keys during development. The test card number 4242 4242 4242 4242 with any future expiration and any CVC will simulate a successful payment.
7

Create the pricing page

Build a public-facing pricing page that drives conversions and handles the checkout redirect.
Build the pricing page:

- Show two plan cards side by side: Free and Pro ($19/month).
- Free plan features: up to 3 members, 1 workspace, 50 tasks, basic
  Kanban board.
- Pro plan features: unlimited members, unlimited workspaces, unlimited
  tasks, priority support, advanced analytics (coming soon).
- Highlight the Pro plan as "Most Popular" with a colored border.
- Add a monthly/yearly toggle. Yearly pricing is $15/month billed
  annually ($180/year), showing a "Save 21%" badge.
- The "Get Started" button on the Free plan links to the signup page.
- The "Upgrade to Pro" button initiates a Stripe Checkout session.
  If the user is logged in, prefill their email. If not, redirect
  to signup first.
- After successful checkout, redirect to the dashboard with a success
  toast notification.
8

Add email notifications with Resend

Go to Integrations and connect Resend by pasting your API key. Then set up transactional emails for key user actions.
Connect Resend and add email notifications:

- Send a welcome email when a new user signs up. Include the app name,
  a greeting with their name, and a "Go to Dashboard" button linking
  to the app.
- Send an invitation email when a workspace owner invites a new member.
  Include the workspace name, the inviter's name, their assigned role,
  and a "Join Workspace" button.
- Send a payment receipt email after a successful Stripe subscription.
  Include the plan name, amount, billing period, and a link to the
  billing page.
- Send a subscription cancellation confirmation email when a user cancels
  their Pro plan.
- Use a clean, minimal email template with the Taskflow logo, a white
  background, and blue accent buttons.
Resend provides a free tier of 100 emails per day, which is plenty for development and early launch. You can upgrade later as your user base grows.
9

Deploy to Netlify

Go to Integrations and connect Netlify, then deploy your app to the web.
Deploy the app to Netlify:

- Set up the build configuration for Next.js with the correct build
  command and output directory.
- Add all required environment variables: Supabase URL, Supabase anon key,
  Stripe publishable key, Stripe secret key, Stripe webhook secret,
  and Resend API key.
- Enable automatic deploys so the app redeploys when I push changes.
- Set up a custom subdomain like taskflow.netlify.app.
After deploying, update your Supabase redirect URLs to include your Netlify domain. Go to your Supabase dashboard, navigate to Authentication > URL Configuration, and add https://your-app.netlify.app to the allowed redirect URLs.
10

Go live

Before sharing your app with real users, swap out all test credentials for production keys.
Prepare the app for production:

- Replace the Stripe test keys with live keys in the Netlify environment
  variables. Update both the publishable key and secret key.
- Create the Stripe products and prices in live mode (they don't carry
  over from test mode).
- Update the Stripe webhook endpoint in the Stripe Dashboard to point
  to the production Netlify URL.
- Verify that Supabase email templates are customized with the Taskflow
  branding.
- Test the full flow on the production URL: sign up, create a workspace,
  add a task, invite a member, and complete a real Stripe checkout with
  a small amount.
- Enable Supabase email confirmations for production to prevent spam
  signups.
Double-check that your Stripe live webhook secret matches the one in your Netlify environment variables. Mismatched secrets are the most common cause of payment processing failures after launch.

Customization ideas

Once the base product is running, here are ways to extend it.
Track user behavior to understand how people use your app. Instrument events like workspace created, task moved, member invited, and plan upgraded. Use Mixpanel funnels to measure your signup-to-paid conversion rate.
Connect Mixpanel and add event tracking for: user_signed_up,
workspace_created, task_created, task_moved, member_invited,
plan_upgraded, and plan_canceled. Add a Mixpanel identify call
after login so events are linked to the user profile.
Let users generate task descriptions, summarize project progress, or get smart suggestions for task assignments using OpenAI.
Connect OpenAI and add an "AI Assistant" button on the task board.
When clicked, open a panel where users can: generate a task description
from a short title, summarize all tasks in a workspace as a progress
report, and get suggestions for which team member to assign a task
to based on their current workload.
Expose a REST API so power users can automate task creation, query workspace data, or integrate with external tools like Zapier.
Create a public REST API with these endpoints:
- GET /api/v1/workspaces - list user's workspaces
- GET /api/v1/workspaces/:id/tasks - list tasks in a workspace
- POST /api/v1/workspaces/:id/tasks - create a new task
- PATCH /api/v1/tasks/:id - update a task
- DELETE /api/v1/tasks/:id - delete a task
Authenticate using Bearer tokens generated from the user settings page.
Return JSON responses with proper error codes and pagination.
Build an internal dashboard for yourself to monitor signups, revenue, and usage metrics without leaving the app.
Create an admin dashboard at /admin that is only accessible to users
with an "admin" role in the profiles table. Show: total users (with a
signup chart over the last 30 days), total workspaces, active
subscriptions and MRR, and a table of recent signups with email,
signup date, and plan status.
Make the app work well on phones and tablets, or generate a standalone mobile app from your Rocket project.
Optimize the entire app for mobile devices. Make the sidebar collapsible
with a hamburger menu, ensure the Kanban board scrolls horizontally on
small screens, and make all modals full-screen on mobile. Add touch-friendly
drag-and-drop for task cards.

Troubleshooting

Symptoms: Payments complete in Stripe but the workspace plan does not update in your app.Fix:
  1. Open the Stripe Dashboard > Webhooks and confirm the endpoint URL matches your production Netlify URL (for example, https://your-app.netlify.app/api/webhooks/stripe).
  2. Check that the webhook signing secret in your Netlify environment variables matches the one shown in the Stripe Dashboard.
  3. Click Send test webhook in Stripe to verify the endpoint responds with a 200 status.
  4. If you are still in test mode, make sure you are looking at the test mode webhooks (toggle the mode switch in the Stripe Dashboard).
Symptoms: After login or signup on the deployed site, the user is redirected to localhost:3000 instead of the production URL.Fix:
  1. In your Supabase Dashboard, go to Authentication > URL Configuration.
  2. Set the Site URL to your production URL (for example, https://your-app.netlify.app).
  3. Add your production URL to the Redirect URLs list.
  4. Remove any localhost entries if you no longer need them for local development.
  5. Redeploy the app on Netlify to pick up the changes.
Symptoms: Users do not receive welcome emails, invitations, or receipts.Fix:
  1. Confirm your Resend API key is correct in the Netlify environment variables.
  2. Check the Resend Dashboard > Logs for delivery status and error messages.
  3. If you are using a custom “from” domain, verify that DNS records (SPF, DKIM) are configured correctly in your domain registrar.
  4. During development, Resend only allows sending to the email address associated with your Resend account unless you have verified a custom domain.
Symptoms: The app loads but the task board or workspace list is empty, even though data exists in Supabase.Fix:
  1. Open the Supabase Dashboard and go to Table Editor. Check that the data exists in the relevant tables.
  2. Go to Authentication > Policies and review the RLS policies on the workspaces, workspace_members, and tasks tables.
  3. Make sure the policies reference auth.uid() correctly and that the logged-in user has a matching row in workspace_members.
  4. Use the Supabase SQL Editor to test a query as the authenticated user: select * from tasks where workspace_id = 'your-workspace-id';

What’s next?