@gobuildlabs/saas-starter-kit
v0.1.0
Published
SaaS Starter Kit - Reusable utilities for building SaaS applications (Stripe helpers, Supabase auth, SEO utilities and Database, Utils)
Downloads
38
Readme
SaaS Starter Kit
Reusable utilities and helpers for building SaaS applications with Stripe, Supabase, Next.js, and Prisma.
Overview
This package contains extracted, framework-agnostic utilities from the LaunchKit SaaS boilerplate. It uses dependency injection to eliminate hard-coded configuration imports, making it suitable for distribution as an npm package.
Installation
# As workspace package (current setup)
pnpm add @gobuildlabs/saas-starter-kit@workspace:*
# Future: As published npm package
npm install @gobuildlabs/saas-starter-kitModules
🔐 Authentication (Supabase)
Create Supabase clients and authentication helpers.
import { createSupabaseAuth, createAuthHelpers } from '@gobuildlabs/saas-starter-kit/auth';
// Server-side authentication
const supabaseAuth = createSupabaseAuth({
url: process.env.NEXT_PUBLIC_SUPABASE_URL!,
anonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
serviceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY,
});
export async function createServerClient() {
const cookieStore = await cookies();
return supabaseAuth.createServerClient(cookieStore);
}
export const supabaseAdmin = supabaseAuth.getAdminClient();
// Auth helpers
const authHelpers = createAuthHelpers({
defaultRedirect: '/dashboard',
appUrl: process.env.NEXT_PUBLIC_APP_URL!,
});
const callbackUrl = authHelpers.getValidCallbackUrl('/pricing');
const user = await authHelpers.getUser(supabase);
const isAuth = await authHelpers.isAuthenticated(supabase);Available Functions:
createSupabaseAuth(config)- Create server-side Supabase client factorycreateSupabaseClientFactory(config)- Create client-side Supabase singletoncreateAuthHelpers(config)- Create auth helper functionsgetValidCallbackUrl(url)- Validate callback URLs (prevent open redirects)getUser(supabase)- Get current authenticated usergetSession(supabase)- Get current sessionisAuthenticated(supabase)- Check if user is authenticated
💳 Stripe Integration
Stripe pricing and subscription management utilities.
import { createStripeHelpers } from '@gobuildlabs/saas-starter-kit/stripe';
import { saasConfig } from './config/saas.config';
const stripe = createStripeHelpers(saasConfig);
// Get plan details
const plan = stripe.getPlan('pro');
const paidPlans = stripe.getPaidPlans();
const hasFeature = stripe.hasPlanFeature('pro', 'hdDownloads');
// Trial management
const trialDays = stripe.getTrialDays('pro');
const trialText = stripe.formatTrialPeriod('pro'); // "14-day free trial"
const isInTrial = stripe.isInTrial(subscription);
const daysRemaining = stripe.getTrialDaysRemaining(subscription);
// Customer portal
const portalUrl = await stripe.createCustomerPortalSession(customerId, returnUrl);
// Webhook helpers
const planType = stripe.getPlanTypeByPriceId(priceId);Available Functions:
getPlan(planType)- Get plan detailsgetPaidPlans()- Get all paid plansgetAllPlans()- Get all plans including freehasPlanFeature(planType, feature)- Check if plan has featuregetPlanLimit(planType, limitKey)- Get feature limit valuehasTrial(planType)- Check if plan has trialgetTrialDays(planType)- Get trial daysformatTrialPeriod(planType)- Format trial for displayisInTrial(subscription)- Check if subscription in trialgetTrialDaysRemaining(subscription)- Get remaining trial dayscreateCustomerPortalSession(customerId, returnUrl)- Create Stripe portal sessiongetPlanTypeByPriceId(priceId)- Get plan type from price ID (for webhooks)
🔍 SEO & Metadata
Next.js metadata and structured data helpers.
import { createSEOHelpers } from '@gobuildlabs/saas-starter-kit/seo';
import { saasConfig } from './config/saas.config';
const seo = createSEOHelpers(saasConfig);
// Generate page metadata
export const metadata = seo.getSEOTags({
title: "Pricing",
description: "Simple, transparent pricing",
canonicalUrlRelative: "/pricing",
keywords: ["SaaS", "pricing"],
twitterCreator: "@yourhandle",
});
// Generate structured data
const orgSchema = seo.getOrganizationSchema();
const websiteSchema = seo.getWebsiteSchema();
const productSchema = seo.getProductSchema({
name: "Pro Plan",
description: "Full features",
price: 19,
currency: "USD",
});
// Render JSON-LD
const jsonLd = seo.renderStructuredData(orgSchema);Available Functions:
getSEOTags(params)- Generate Next.js metadatagetOrganizationSchema()- Generate organization JSON-LDgetWebsiteSchema()- Generate website JSON-LDgetProductSchema(product)- Generate product JSON-LDrenderStructuredData(data)- Convert schema to JSON string
🗄️ Database (Prisma)
Prisma client with singleton pattern.
import { createPrismaClient } from '@gobuildlabs/saas-starter-kit/db';
export const prisma = createPrismaClient({
log: ['query'], // Optional: enable query logging
});
// Use as normal
const users = await prisma.user.findMany();🎨 Utilities
General helper functions.
import { cn } from '@gobuildlabs/saas-starter-kit/utils';
// Merge Tailwind classes (uses clsx + tailwind-merge)
<div className={cn('text-red-500', isActive && 'bg-blue-500')} />Architecture Pattern: Dependency Injection
All utilities use dependency injection instead of hard-coded imports:
Before (tightly coupled):
import { saasConfig } from '@config/saas.config'; // ❌ Hard-coded
export function getPlan(planType) {
return saasConfig.stripe.plans[planType];
}After (dependency injection):
export function createStripeHelpers(config: SaasConfig) {
return {
getPlan: (planType) => config.stripe.plans[planType],
// ... other functions
};
}This allows the same code to work with any configuration.
Project Structure
packages/saas-starter-kit/
├── src/
│ ├── lib/
│ │ ├── stripe/
│ │ │ ├── config.ts # Stripe helpers
│ │ │ └── index.ts
│ │ ├── auth/
│ │ │ ├── supabase-server.ts # Server-side Supabase
│ │ │ ├── supabase-client.ts # Client-side Supabase
│ │ │ ├── helpers.ts # Auth utilities
│ │ │ └── index.ts
│ │ ├── seo/
│ │ │ ├── metadata.ts # SEO & metadata
│ │ │ └── index.ts
│ │ ├── db/
│ │ │ ├── prisma.ts # Prisma client
│ │ │ └── index.ts
│ │ └── utils/
│ │ ├── classnames.ts # cn() utility
│ │ └── index.ts
│ ├── types/
│ │ └── index.ts # TypeScript types
│ └── index.ts # Main entry point
├── dist/ # Compiled JavaScript + declarations
├── package.json
├── tsconfig.json
└── README.mdDevelopment
# Build the package
pnpm build
# Watch mode (rebuild on changes)
pnpm dev
# Type check
pnpm type-check
# Clean build artifacts
pnpm cleanMigration Status
✅ Completed Extractions:
- Stripe utilities -
lib/stripe-config.ts→src/lib/stripe/config.ts - Auth utilities -
lib/supabase.ts,lib/supabase-client.ts,lib/auth-helpers.ts→src/lib/auth/ - SEO utilities -
lib/seo.ts→src/lib/seo/metadata.ts - Database utilities -
lib/prisma.ts→src/lib/db/prisma.ts - General utilities -
lib/utils.ts→src/lib/utils/classnames.ts
🚧 Future Enhancements:
- API route templates (webhooks, checkout)
- Reusable React components (PricingCard, AuthForm, etc.)
- CLI scaffolding tool (
npx @gobuildlabs/saas-init) - Email templates
- Analytics helpers
- Feature flag system
Backward Compatibility
All web app files maintain backward compatibility through wrapper pattern:
// apps/web/lib/stripe-config.ts
import { createStripeHelpers } from '@gobuildlabs/saas-starter-kit/stripe';
import { saasConfig } from '@config/saas.config';
const stripeHelpers = createStripeHelpers(saasConfig);
// Re-export for backward compatibility - existing code keeps working!
export const {
getPlan,
getPaidPlans,
// ... all functions
} = stripeHelpers;Package Exports
The package provides modular exports for tree-shaking:
// Main entry
import { createStripeHelpers, createSEOHelpers } from '@gobuildlabs/saas-starter-kit';
// Subpath exports
import { createStripeHelpers } from '@gobuildlabs/saas-starter-kit/stripe';
import { createSupabaseAuth } from '@gobuildlabs/saas-starter-kit/auth';
import { createSEOHelpers } from '@gobuildlabs/saas-starter-kit/seo';
import { createPrismaClient } from '@gobuildlabs/saas-starter-kit/db';
import { cn } from '@gobuildlabs/saas-starter-kit/utils';
// Types
import type { SaasConfig, PricingPlan } from '@gobuildlabs/saas-starter-kit/types';Type Safety
Full TypeScript support with generated declaration files:
import type {
SaasConfig,
PricingPlan,
PricingPlans,
StripeHelpers,
SEOHelpers,
AuthHelpers,
SupabaseAuthHelpers,
SupabaseClientFactory,
} from '@gobuildlabs/saas-starter-kit';Peer Dependencies
The package lists framework dependencies as optional peers:
@prisma/client(optional) - Only needed if using DB utilities@supabase/ssr(optional) - Only needed if using auth utilities@supabase/supabase-js(optional) - Only needed if using auth utilitiesclsx(optional) - Only needed if usingcn()utilitytailwind-merge(optional) - Only needed if usingcn()utilitynext(optional) - Only needed if using SEO utilities
This allows consumers to only install what they need.
License
MIT
Next Steps
After completing Phase 1 (extraction), the roadmap includes:
Phase 2: CLI Tool - Create npx @gobuildlabs/saas-init command
Phase 3: Template Repository - Minimal starter template
Phase 4: Component Library - Extract React components
Phase 5: API Route Templates - Parameterized API routes
Phase 6: Publishing - Publish to npm registry
Contributing
This package is currently part of a monorepo. To add new utilities:
- Create new module in
src/lib/[module-name]/ - Use dependency injection pattern (accept config as parameter)
- Add barrel export in module's
index.ts - Export from main
src/index.ts - Add subpath export in
package.json - Build and test:
pnpm build && pnpm type-check - Create wrapper in
apps/web/lib/for backward compatibility
Support
For issues and questions, please open an issue on GitHub.
