xiaohongshu
xiaohongshu
Rapidly build and launch micro-SaaS applications with best practices, monetization, and deployment
Full skill instructions
Rapidly build, launch, and scale micro-SaaS applications following proven patterns and best practices.
A micro-SaaS is a small, focused Software-as-a-Service business that:
Next.js 14+ (App Router)
+ TypeScript
+ Tailwind CSS
+ shadcn/ui components
+ Framer Motion (animations)
Supabase
+ PostgreSQL (database)
+ Auth (built-in)
+ Row Level Security (RLS)
+ Realtime subscriptions
+ Storage (files)
Stripe or LemonSqueezy
+ Checkout sessions
+ Webhooks
+ Subscription management
+ Customer portal
Vercel (frontend + API routes)
+ Automatic deployments
+ Preview environments
+ Edge functions
+ Analytics
Day 1-2: Project Setup
- Initialize Next.js 14 project
- Configure Supabase project
- Set up database schema
- Configure authentication
Day 3-4: Core Feature
- Implement main value proposition
- Build essential UI components
- Connect frontend to backend
- Add basic error handling
Day 5-7: User Flow
- Landing page
- Sign up/sign in
- Onboarding flow
- Dashboard layout
Day 8-10: Monetization
- Stripe integration
- Subscription plans
- Payment webhooks
- Customer portal
Day 11-13: Essential Features
- Usage limits enforcement
- Email notifications
- User settings
- Basic analytics
Day 14: Launch Prep
- Production deployment
- Domain setup
- Basic documentation
- Launch checklist completion
-- Users (managed by Supabase Auth)
-- Just extend with profile data
-- User profiles
CREATE TABLE profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id),
email TEXT,
full_name TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Subscriptions
CREATE TABLE subscriptions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES auth.users(id),
stripe_customer_id TEXT UNIQUE,
stripe_subscription_id TEXT UNIQUE,
status TEXT NOT NULL, -- 'active', 'canceled', 'past_due'
plan_id TEXT NOT NULL, -- 'free', 'pro', 'enterprise'
current_period_end TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Usage tracking
CREATE TABLE usage (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES auth.users(id),
resource_type TEXT NOT NULL,
amount INTEGER DEFAULT 1,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Main resource (replace with your core entity)
CREATE TABLE resources (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES auth.users(id),
title TEXT NOT NULL,
content JSONB,
status TEXT DEFAULT 'active',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Enable RLS on ALL tables
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY;
ALTER TABLE usage ENABLE ROW LEVEL SECURITY;
ALTER TABLE resources ENABLE ROW LEVEL SECURITY;
-- Basic RLS policies
CREATE POLICY "Users can view own profile"
ON profiles FOR SELECT
USING (auth.uid() = id);
CREATE POLICY "Users can update own profile"
ON profiles FOR UPDATE
USING (auth.uid() = id);
-- Repeat for other tables...
// lib/supabase.ts
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
export const supabase = createClientComponentClient()
// Protected route middleware
// middleware.ts
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
export async function middleware(req) {
const res = NextResponse.next()
const supabase = createMiddlewareClient({ req, res })
const { data: { session } } = await supabase.auth.getSession()
if (!session && req.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', req.url))
}
return res
}
// lib/stripe.ts
import Stripe from 'stripe'
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16',
})
// API route: /api/create-checkout
export async function POST(req: Request) {
const { priceId, userId } = await req.json()
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
payment_method_types: ['card'],
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${process.env.NEXT_PUBLIC_URL}/dashboard?success=true`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing?canceled=true`,
client_reference_id: userId,
})
return Response.json({ url: session.url })
}
// API route: /api/webhooks/stripe
export async function POST(req: Request) {
const sig = req.headers.get('stripe-signature')!
const body = await req.text()
const event = stripe.webhooks.constructEvent(
body,
sig,
process.env.STRIPE_WEBHOOK_SECRET!
)
switch (event.type) {
case 'checkout.session.completed':
// Create subscription record
break
case 'customer.subscription.updated':
// Update subscription status
break
case 'customer.subscription.deleted':
// Cancel subscription
break
}
return Response.json({ received: true })
}
// lib/usage-limits.ts
const PLAN_LIMITS = {
free: { resources: 5, api_calls: 100 },
pro: { resources: 100, api_calls: 10000 },
enterprise: { resources: -1, api_calls: -1 }, // unlimited
}
export async function checkUsageLimit(
userId: string,
resourceType: string
) {
// Get user's current plan
const { data: subscription } = await supabase
.from('subscriptions')
.select('plan_id')
.eq('user_id', userId)
.single()
const plan = subscription?.plan_id || 'free'
// Count current usage
const { count } = await supabase
.from('usage')
.select('*', { count: 'exact', head: true })
.eq('user_id', userId)
.eq('resource_type', resourceType)
const limit = PLAN_LIMITS[plan][resourceType]
if (limit === -1) return true // unlimited
return count < limit
}
// Usage in API routes
export async function POST(req: Request) {
const { userId } = await getSession(req)
const canCreate = await checkUsageLimit(userId, 'resources')
if (!canCreate) {
return Response.json(
{ error: 'Usage limit reached. Upgrade to create more.' },
{ status: 403 }
)
}
// Create resource...
}
// app/page.tsx
export default function LandingPage() {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
<h1 className="text-5xl font-bold text-center">
{/* Clear, benefit-focused headline */}
Transform X into Y in Minutes
</h1>
<p className="text-xl text-gray-600 mt-4 max-w-2xl text-center">
{/* One-sentence explanation of what it does */}
The fastest way to [achieve outcome] without [pain point]
</p>
<div className="flex gap-4 mt-8">
<button className="px-8 py-3 bg-blue-600 text-white rounded-lg">
Start Free Trial
</button>
<button className="px-8 py-3 border border-gray-300 rounded-lg">
View Demo
</button>
</div>
{/* Social proof */}
<p className="text-sm text-gray-500 mt-8">
Join 1,000+ users who love [Product]
</p>
</div>
)
}
const PLANS = [
{
name: 'Free',
price: '$0',
features: [
'5 resources',
'100 API calls/month',
'Basic support',
],
},
{
name: 'Pro',
price: '$19',
features: [
'100 resources',
'10,000 API calls/month',
'Priority support',
'Advanced features',
],
popular: true,
},
{
name: 'Enterprise',
price: 'Custom',
features: [
'Unlimited resources',
'Unlimited API calls',
'Dedicated support',
'Custom integrations',
],
},
]
// lib/email.ts
import { Resend } from 'resend'
const resend = new Resend(process.env.RESEND_API_KEY)
export async function sendWelcomeEmail(email: string, name: string) {
await resend.emails.send({
from: '[email protected]',
to: email,
subject: 'Welcome to [Product]!',
html: `
<h1>Welcome, ${name}!</h1>
<p>Thanks for signing up. Here's how to get started...</p>
`,
})
}
// Trigger on user signup
// Trigger on subscription created
// Trigger on usage limit reached
// Track these events:
- User signups
- Trial starts
- Trial to paid conversions
- Feature usage
- Churn events
- Support requests
- Error rates
// Use:
- Vercel Analytics (built-in)
- PostHog (self-hosted)
- Plausible (privacy-focused)
Free Plan → Limited features/usage
↓
Pro Plan → Unlock full features
↓
Enterprise → Custom pricing/support
Track usage → Calculate bill
↓
Charge per unit (API calls, storage, etc.)
↓
Real-time usage display
Per user pricing
↓
Team management
↓
Invitation system
// 1. Image optimization
import Image from 'next/image'
<Image src={url} alt="..." width={500} height={300} />
// 2. Database query optimization
// Use indexes on frequently queried columns
CREATE INDEX idx_user_id ON resources(user_id);
// 3. API response caching
export const revalidate = 60 // Cache for 60 seconds
// 4. Use React Server Components
// Keep client components minimal
// 5. Lazy load heavy components
const HeavyComponent = dynamic(() => import('./HeavyComponent'))
# 1. Install Vercel CLI
npm i -g vercel
# 2. Link project
vercel link
# 3. Set environment variables
vercel env add SUPABASE_URL
vercel env add SUPABASE_ANON_KEY
vercel env add STRIPE_SECRET_KEY
vercel env add STRIPE_WEBHOOK_SECRET
# 4. Deploy
vercel --prod
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
# Stripe
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# App
NEXT_PUBLIC_URL=https://yourdomain.com
# Email (optional)
RESEND_API_KEY=
< 1,000 users: Don't optimize, just ship
1K - 10K users: Basic optimization (caching, indexes)
10K - 100K users: Database optimization, CDN
100K+ users: Consider dedicated infrastructure
Free Tiers to Use:
- Vercel: 100GB bandwidth
- Supabase: 500MB database, 2GB bandwidth
- Stripe: No monthly fee, just transaction %
- Resend: 3,000 emails/month
Expected Costs (at 1,000 users):
- Hosting: $0-20/month
- Database: $0-25/month
- Email: $0-10/month
- Total: $0-55/month
Week 1: Launch announcement
Week 2-4: Tutorial content, use cases
Month 2+: SEO content, case studies
Remember: Ship fast, iterate based on feedback, and focus on solving ONE problem extremely well!
Motto: "Working software > Perfect software"
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience