guias·18 min de lectura

Construye tu Micro-SaaS con Next.js: De la Idea al Primer Cliente

Guia completa para construir un micro-SaaS con Next.js. Stack recomendado, autenticacion, pagos con Stripe, base de datos, deployment y estrategia de lanzamiento.

Construye tu Micro-SaaS con Next.js: De la Idea al Primer Cliente

Construir un micro-SaaS con Next.js es una de las rutas mas directas que tiene un desarrollador para generar ingresos recurrentes. No necesitas un equipo de 20 personas, no necesitas levantar capital, y no necesitas tres anos de desarrollo. Un micro-SaaS resuelve un problema concreto para un nicho especifico, y con el stack correcto puedes ir de la idea al primer cliente en semanas.

El mercado de SaaS esta proyectado a superar los $344 mil millones para 2028. Pero lo interesante no son las empresas grandes. Es el espacio de los micro-SaaS: productos manejados por una a cinco personas que generan entre $50K y $3M+ al ano con costos operativos minimos. Desarrolladores que construyen herramientas, las lanzan, y las mantienen como side projects que eventualmente superan su salario.

Esta guia cubre el proceso completo. Desde encontrar la idea correcta hasta cobrar tu primera suscripcion.

Que es un micro-SaaS

Un micro-SaaS es un producto de software como servicio con estas caracteristicas:

  • Equipo minimo: una a cinco personas, frecuentemente una sola
  • Nicho definido: resuelve un problema especifico, no intenta ser todo para todos
  • Ingresos recurrentes: modelo de suscripcion mensual o anual
  • Costos operativos bajos: infraestructura cloud, sin oficinas, sin empleados
  • Crecimiento sostenible: no necesita venture capital para funcionar

Ejemplos reales de micro-SaaS exitosos:

ProductoQue haceIngresos estimados
Plausible AnalyticsAnalytics web privado$1M+ ARR
ButtondownNewsletter simple$500K+ ARR
BannerbearGeneracion automatica de imagenes$600K+ ARR
LogsnagMonitoreo de eventos para devs$100K+ ARR

La mayoria de estos productos empezaron como side projects de un solo desarrollador. Todos resuelven un problema concreto y cobran una suscripcion mensual.

Por que los desarrolladores estan perfectamente posicionados

Si sabes construir software, ya tienes la ventaja mas importante. La mayoria de emprendedores necesitan contratar un equipo de desarrollo. Tu eres el equipo de desarrollo. Tu costo de creacion es tu tiempo, no $50K-$200K en un equipo externo.

Ademas, los problemas que enfrentas como desarrollador son los mismos que enfrentan miles de desarrolladores mas. Eso es un mercado.

El stack recomendado

Despues de evaluar muchas combinaciones, este es el stack que mejor funciona para un micro-SaaS construido por una o pocas personas:

ComponenteHerramientaPor que
FrameworkNext.js (App Router)Full-stack en un solo proyecto, SSR, API routes, Server Actions
Base de datosSupabase (PostgreSQL)Tier gratuito generoso, auth integrado, real-time, RLS
AutenticacionAuth.js v5 o ClerkIntegracion directa con Next.js, multiples providers
PagosStripeEstandar de la industria, excelente API, webhooks confiables
HostingVercelZero config para Next.js, preview deployments, edge network
EmailResendAPI moderna, tier gratuito, templates con React
EstilosTailwind CSSProductividad, sin context switching
ℹ️
Por que este stack?

Cada herramienta tiene un tier gratuito funcional. Puedes lanzar tu MVP sin gastar un centavo en infraestructura. Los costos aparecen cuando ya tienes usuarios pagando, que es exactamente cuando puedes permitirtelos.

La clave del stack es que Next.js con App Router unifica frontend y backend. No necesitas un proyecto separado para la API. Server Components hacen queries directas a la base de datos. Server Actions manejan mutaciones. API Routes manejan webhooks de Stripe. Todo en un solo repositorio.

Si no tienes experiencia con Supabase, revisa la guia completa de Supabase con Next.js antes de continuar. Para deploy, la guia de Vercel para Next.js cubre todo el proceso.

Fase 1: Validacion de la idea

Este es el paso que la mayoria de desarrolladores se salta. Y es el mas importante.

Construir algo que nadie necesita es la forma mas comun de perder meses de trabajo. Antes de escribir una sola linea de codigo, necesitas evidencia de que alguien pagaria por tu solucion.

Como encontrar el problema correcto

Los mejores micro-SaaS nacen de una frustracion real. Preguntate:

  • Que tarea repetitiva hago cada semana que podria automatizar?
  • Que herramienta uso que me frustra por lo que le falta?
  • Que problema veo en Twitter, Reddit o foros de dev que no tiene buena solucion?
  • Que pregunta respondo constantemente en Discord o Slack?

No busques ideas revolucionarias. Busca problemas aburridos que la gente ya tiene y que ya esta intentando resolver con soluciones mediocres.

Tecnicas de validacion (antes de programar)

1. Busca competencia

Si nadie cobra por algo similar, probablemente no hay mercado. La competencia es buena senal. Significa que la gente ya paga por resolver ese problema.

2. Pregunta en publico

Publica en Twitter, Reddit (r/SaaS, r/indiehackers), y comunidades de Discord. No preguntes "les gustaria una herramienta que...?" sino "como resuelven actualmente el problema de...?". Las respuestas te dicen si el dolor es real.

3. Crea una landing page de prueba

Antes de construir el producto, construye una landing page que describa la solucion y tenga un formulario de email para "acceso anticipado". Si nadie se registra, probablemente nadie pagaria.

4. Pre-venta

El nivel maximo de validacion. Ofrece el producto con descuento antes de construirlo. Si cinco personas pagan antes de que exista, ya tienes validacion y motivacion real para construirlo.

⚠️
La trampa del desarrollador

Tu cerebro de dev quiere empezar a programar. Resistirlo es la habilidad mas valiosa que puedes desarrollar como fundador de un micro-SaaS. Dos semanas de validacion te ahorran meses de desarrollo en la direccion equivocada.

Fase 2: Arquitectura del MVP

Ya validaste la idea. Ahora si, vamos al codigo. Pero con una regla clara: construye lo minimo que funcione y cobra por ello.

Estructura del proyecto

Estructura de archivos

mi-saas/ ├── app/ │ ├── (marketing)/ │ │ ├── page.tsx (landing page) │ │ ├── pricing/page.tsx (precios) │ │ └── layout.tsx │ ├── (app)/ │ │ ├── dashboard/page.tsx (panel principal) │ │ ├── settings/page.tsx (configuracion) │ │ └── layout.tsx (layout con sidebar autenticado) │ ├── (auth)/ │ │ ├── login/page.tsx │ │ ├── register/page.tsx │ │ └── layout.tsx │ ├── api/ │ │ ├── webhooks/stripe/route.ts │ │ └── cron/route.ts │ ├── layout.tsx │ └── sitemap.ts ├── components/ │ ├── marketing/ │ ├── dashboard/ │ └── shared/ ├── lib/ │ ├── supabase/ │ │ ├── client.ts │ │ ├── server.ts │ │ └── middleware.ts │ ├── stripe/ │ │ ├── client.ts │ │ └── webhooks.ts │ ├── auth.ts │ └── utils.ts ├── .env.local ├── middleware.ts ├── next.config.ts └── package.json

La estructura usa route groups de Next.js para separar tres contextos: marketing (paginas publicas), app (dashboard autenticado) y auth (login y registro). Cada grupo tiene su propio layout, lo que evita cargar componentes innecesarios.

Schema de base de datos

Para un micro-SaaS tipico, necesitas cuatro tablas fundamentales. Este SQL es para Supabase (PostgreSQL):

sql
-- Tabla de usuarios (extiende el auth de Supabase)
create table public.profiles (
  id uuid references auth.users on delete cascade primary key,
  email text not null,
  full_name text,
  avatar_url text,
  created_at timestamp with time zone default now(),
  updated_at timestamp with time zone default now()
);
 
-- Tabla de suscripciones (vinculada a Stripe)
create table public.subscriptions (
  id text primary key, -- ID de Stripe (sub_xxx)
  user_id uuid references public.profiles on delete cascade not null,
  status text not null, -- active, canceled, past_due, trialing
  price_id text not null, -- ID del precio en Stripe
  current_period_start timestamp with time zone,
  current_period_end timestamp with time zone,
  cancel_at_period_end boolean default false,
  created_at timestamp with time zone default now()
);
 
-- Tabla de planes (sincronizada con Stripe)
create table public.plans (
  id text primary key, -- ID del precio en Stripe (price_xxx)
  name text not null,
  description text,
  price integer not null, -- Precio en centavos
  interval text not null, -- month, year
  features jsonb default '[]'::jsonb,
  active boolean default true
);
 
-- Habilitar Row Level Security
alter table public.profiles enable row level security;
alter table public.subscriptions enable row level security;
 
-- Politicas: cada usuario solo ve sus datos
create policy "Usuarios ven su propio perfil"
  on public.profiles for select
  using (auth.uid() = id);
 
create policy "Usuarios ven sus suscripciones"
  on public.subscriptions for select
  using (auth.uid() = user_id);
💡
Row Level Security es obligatorio

Si usas Supabase, activa RLS en todas las tablas que contengan datos de usuarios. Sin RLS, cualquier persona con tu anon key puede leer toda la base de datos. La guia de Supabase explica como configurar politicas correctamente.

Tipos de TypeScript para el schema

typescript
// lib/types.ts -- tipos que reflejan tu schema de base de datos
 
interface Profile {
  id: string
  email: string
  full_name: string | null
  avatar_url: string | null
  created_at: string
  updated_at: string
}
 
interface Subscription {
  id: string
  user_id: string
  status: 'active' | 'canceled' | 'past_due' | 'trialing'
  price_id: string
  current_period_start: string
  current_period_end: string
  cancel_at_period_end: boolean
  created_at: string
}
 
type SubscriptionStatus = Subscription['status']

Fase 3: Autenticacion

La autenticacion es el primer feature que necesitas porque todo lo demas depende de ella. Con Next.js tienes dos opciones solidas: Auth.js v5 (antes NextAuth) o Clerk.

Auth.js v5: open source y flexible

Auth.js se configura en tu proyecto y maneja sesiones con cookies httpOnly. Soporta OAuth (Google, GitHub), magic links y credenciales.

typescript
// lib/auth.ts -- configuracion de Auth.js v5
import NextAuth from 'next-auth'
import Google from 'next-auth/providers/google'
import GitHub from 'next-auth/providers/github'
import { SupabaseAdapter } from '@auth/supabase-adapter'
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  adapter: SupabaseAdapter({
    url: process.env.SUPABASE_URL!,
    secret: process.env.SUPABASE_SERVICE_ROLE_KEY!,
  }),
  providers: [
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
    GitHub({
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    }),
  ],
  pages: {
    signIn: '/login',  // Pagina de login personalizada
  },
})
typescript
// middleware.ts -- proteger rutas del dashboard
import { auth } from '@/lib/auth'
import { NextResponse } from 'next/server'
 
export default auth((req) => {
  const isLoggedIn = !!req.auth
  const isAppRoute = req.nextUrl.pathname.startsWith('/dashboard')
 
  // Redirigir a login si no esta autenticado
  if (isAppRoute && !isLoggedIn) {
    return NextResponse.redirect(new URL('/login', req.url))
  }
 
  // Redirigir al dashboard si ya tiene sesion
  if (req.nextUrl.pathname === '/login' && isLoggedIn) {
    return NextResponse.redirect(new URL('/dashboard', req.url))
  }
})
 
export const config = {
  matcher: ['/dashboard/:path*', '/settings/:path*', '/login'],
}

Clerk: mas rapido, menos control

Si prefieres no configurar auth tu mismo, Clerk te da componentes pre-construidos, un dashboard de usuarios, y manejo de sesiones listo para usar. El tradeoff es que dependes de un servicio externo y los precios suben con los usuarios.

Para una guia paso a paso de autenticacion en Next.js, revisa la guia de autenticacion con Auth.js v5.

ℹ️
Cual elegir?

Para un micro-SaaS que vas a mantener tu solo, Auth.js te da control total sin costos adicionales. Clerk tiene sentido si quieres velocidad de implementacion y estas dispuesto a pagar por usuario activo.

Fase 4: La funcionalidad core

Este es el momento de construir la razon por la que tu producto existe. Una sola funcionalidad, bien ejecutada.

La regla es simple: tu MVP debe tener exactamente un feature que resuelve el problema principal. Todo lo demas (configuracion de cuenta, notificaciones, integraciones, reportes avanzados) viene despues.

Ejemplo: un dashboard de metricas para tiendas Shopify

Si tu micro-SaaS es un dashboard de metricas, el MVP es:

  1. Conectar con la API de Shopify (OAuth)
  2. Traer las ventas de los ultimos 30 dias
  3. Mostrar un grafico y numeros clave

Eso es todo. No necesitas exportar a CSV, no necesitas alertas, no necesitas comparacion con periodos anteriores. Eso viene en la version 2.

typescript
// app/(app)/dashboard/page.tsx -- Server Component con datos reales
import { auth } from '@/lib/auth'
import { createSupabaseServer } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
 
export default async function DashboardPage() {
  const session = await auth()
  if (!session?.user) redirect('/login')
 
  const supabase = await createSupabaseServer()
 
  // Traer metricas del usuario autenticado
  const { data: metrics } = await supabase
    .from('metrics')
    .select('*')
    .eq('user_id', session.user.id)
    .gte('date', new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString())
    .order('date', { ascending: true })
 
  return (
    <div>
      <h1>Tu Dashboard</h1>
      <MetricsChart data={metrics ?? []} />
      <KeyNumbers data={metrics ?? []} />
    </div>
  )
}
💡
Ship ugly, iterate later

Tu primera version no necesita ser bonita. Necesita funcionar y resolver el problema. Los primeros usuarios pagan por la solucion, no por los bordes redondeados. Puedes pulir el diseno despues, cuando tengas feedback real.

Server Actions para mutaciones

Cuando el usuario necesita crear o modificar datos, usa Server Actions. Son funciones del servidor que se invocan desde formularios o handlers del cliente:

typescript
// app/(app)/actions.ts
'use server'
 
import { auth } from '@/lib/auth'
import { createSupabaseServer } from '@/lib/supabase/server'
import { revalidatePath } from 'next/cache'
import { z } from 'zod'
 
const ProjectSchema = z.object({
  name: z.string().min(1).max(100).trim(),
  url: z.string().url(),
})
 
export async function createProject(formData: FormData) {
  const session = await auth()
  if (!session?.user) throw new Error('No autenticado')
 
  const parsed = ProjectSchema.safeParse({
    name: formData.get('name'),
    url: formData.get('url'),
  })
 
  if (!parsed.success) {
    return { error: parsed.error.flatten().fieldErrors }
  }
 
  const supabase = await createSupabaseServer()
 
  const { error } = await supabase
    .from('projects')
    .insert({
      user_id: session.user.id,
      name: parsed.data.name,
      url: parsed.data.url,
    })
 
  if (error) {
    return { error: { server: ['Error al crear el proyecto'] } }
  }
 
  revalidatePath('/dashboard')
  return { success: true }
}

Fase 5: Pagos con Stripe

Sin pagos, no tienes un negocio. Stripe es el estandar para SaaS por una razon: la API es excelente, los webhooks son confiables, y Checkout te da una pagina de pago lista para usar.

Estrategia de precios

Antes del codigo, define tu modelo de precios. Para un micro-SaaS, estas son las opciones mas comunes:

ModeloCuando usarloEjemplo
Flat rateProducto simple con un solo nivel$15/mes por todo
TieredFeatures diferentes por nivelFree, Pro ($19), Team ($49)
Usage-basedEl valor escala con el uso$0.01 por API call
Per-seatEquipos que crecen$10/mes por usuario

Para tu MVP, empieza con dos niveles: gratuito (limitado) y de pago (completo). Un solo precio reduce la complejidad y la friccion de decision del usuario.

Configurar Stripe

Terminal
$
typescript
// lib/stripe/client.ts -- cliente de Stripe para el servidor
import Stripe from 'stripe'
 
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-02-24.acacia',
  typescript: true,
})

Crear una sesion de Checkout

Stripe Checkout es una pagina de pago hosted que maneja tarjetas, validacion, 3D Secure, y cumplimiento PCI. No necesitas construir tu propio formulario de pago.

typescript
// app/api/checkout/route.ts
import { auth } from '@/lib/auth'
import { stripe } from '@/lib/stripe/client'
import { NextResponse } from 'next/server'
 
export async function POST() {
  const session = await auth()
  if (!session?.user?.email) {
    return NextResponse.json({ error: 'No autenticado' }, { status: 401 })
  }
 
  const checkoutSession = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    customer_email: session.user.email,
    line_items: [
      {
        price: process.env.STRIPE_PRICE_ID!, // ID del precio en Stripe
        quantity: 1,
      },
    ],
    success_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard?upgraded=true`,
    cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/pricing`,
    metadata: {
      userId: session.user.id!, // Para vincular la suscripcion al usuario
    },
  })
 
  return NextResponse.json({ url: checkoutSession.url })
}

Webhooks: la parte critica

Los webhooks de Stripe te notifican cuando algo pasa con una suscripcion. Esta es la parte que no puedes omitir, porque Checkout redirige al usuario a tu app antes de que el pago se confirme.

typescript
// app/api/webhooks/stripe/route.ts
import { stripe } from '@/lib/stripe/client'
import { createSupabaseServer } from '@/lib/supabase/server'
import { headers } from 'next/headers'
import { NextResponse } from 'next/server'
 
export async function POST(request: Request) {
  const body = await request.text()
  const headersList = await headers()
  const signature = headersList.get('stripe-signature')!
 
  let event
 
  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      process.env.STRIPE_WEBHOOK_SECRET!
    )
  } catch {
    return NextResponse.json(
      { error: 'Firma de webhook invalida' },
      { status: 400 }
    )
  }
 
  const supabase = await createSupabaseServer()
 
  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object
      const subscription = await stripe.subscriptions.retrieve(
        session.subscription as string
      )
 
      // Guardar la suscripcion en tu base de datos
      await supabase.from('subscriptions').upsert({
        id: subscription.id,
        user_id: session.metadata?.userId,
        status: subscription.status,
        price_id: subscription.items.data[0].price.id,
        current_period_start: new Date(
          subscription.current_period_start * 1000
        ).toISOString(),
        current_period_end: new Date(
          subscription.current_period_end * 1000
        ).toISOString(),
      })
      break
    }
 
    case 'customer.subscription.updated':
    case 'customer.subscription.deleted': {
      const subscription = event.data.object
 
      await supabase
        .from('subscriptions')
        .update({
          status: subscription.status,
          cancel_at_period_end: subscription.cancel_at_period_end,
          current_period_end: new Date(
            subscription.current_period_end * 1000
          ).toISOString(),
        })
        .eq('id', subscription.id)
      break
    }
  }
 
  return NextResponse.json({ received: true })
}
⚠️
Testa los webhooks en local

Usa stripe listen --forward-to localhost:3000/api/webhooks/stripe para recibir webhooks durante desarrollo. Nunca hagas deploy sin verificar que tus webhooks funcionan correctamente. Un webhook roto significa suscripciones que no se registran.

Para una integracion mas detallada con Stripe Checkout y suscripciones, revisa la guia de Stripe con Next.js.

Verificar la suscripcion en tu app

typescript
// lib/subscription.ts -- helper para verificar acceso
import { auth } from '@/lib/auth'
import { createSupabaseServer } from '@/lib/supabase/server'
 
export async function getUserSubscription() {
  const session = await auth()
  if (!session?.user) return null
 
  const supabase = await createSupabaseServer()
 
  const { data } = await supabase
    .from('subscriptions')
    .select('*')
    .eq('user_id', session.user.id)
    .in('status', ['active', 'trialing'])
    .single()
 
  return data
}
 
export async function isPro(): Promise<boolean> {
  const subscription = await getUserSubscription()
  return !!subscription
}

Fase 6: Landing page que convierte

Tu landing page es tu vendedor 24/7. Si no convierte visitantes en usuarios, nada de lo anterior importa.

Estructura de una landing page SaaS efectiva

Las landing pages que convierten siguen un patron predecible:

  1. Hero: Titulo claro que describe el beneficio principal + CTA
  2. Problema: Describe el dolor que tu producto resuelve
  3. Solucion: Muestra como tu producto elimina ese dolor
  4. Features: 3-4 features principales con capturas de pantalla o demos
  5. Social proof: Testimonios, logos de clientes, numeros de uso
  6. Pricing: Tabla de precios simple y directa
  7. FAQ: Responde las objeciones mas comunes
  8. CTA final: Repite el call to action

Componente de pricing table

tsx
// components/marketing/PricingTable.tsx
interface Plan {
  name: string
  price: string
  interval: string
  description: string
  features: string[]
  cta: string
  href: string
  highlighted: boolean
}
 
const plans: Plan[] = [
  {
    name: 'Starter',
    price: 'Gratis',
    interval: '',
    description: 'Para probar la herramienta',
    features: [
      'Hasta 3 proyectos',
      '100 consultas al mes',
      'Dashboard basico',
      'Soporte por email',
    ],
    cta: 'Empezar gratis',
    href: '/register',
    highlighted: false,
  },
  {
    name: 'Pro',
    price: '$19',
    interval: '/mes',
    description: 'Para profesionales y freelancers',
    features: [
      'Proyectos ilimitados',
      'Consultas ilimitadas',
      'Dashboard avanzado',
      'Exportar a CSV',
      'API access',
      'Soporte prioritario',
    ],
    cta: 'Iniciar prueba gratuita',
    href: '/register?plan=pro',
    highlighted: true,
  },
]
💡
Precio psicologico

$19/mes es el precio sweet spot para micro-SaaS. Es suficientemente bajo para que un freelancer o un equipo pequeno lo pague sin aprobacion, y suficientemente alto para que 200 clientes te generen $3,800/mes. Si tu producto ahorra mas de una hora al mes, $19 es facil de justificar.

El hero section que funciona

Un buen hero tiene tres elementos: un titulo que explica el beneficio (no el feature), un subtitulo que da contexto, y un CTA visible.

tsx
// components/marketing/Hero.tsx
export function Hero() {
  return (
    <section className="py-20 text-center">
      <h1 className="text-5xl font-bold tracking-tight">
        Deja de perder horas en reportes manuales
      </h1>
      <p className="mt-6 text-xl text-gray-400 max-w-2xl mx-auto">
        Conecta tu tienda, y ten un dashboard con las metricas que
        realmente importan. Sin Excel, sin copiar y pegar.
      </p>
      <div className="mt-10 flex justify-center gap-4">
        <a
          href="/register"
          className="rounded-lg bg-white px-8 py-3 text-black font-semibold"
        >
          Empezar gratis
        </a>
        <a
          href="#demo"
          className="rounded-lg border border-gray-600 px-8 py-3 font-semibold"
        >
          Ver demo
        </a>
      </div>
    </section>
  )
}

Nota: "Deja de perder horas en reportes manuales" describe un beneficio. "Dashboard de metricas para e-commerce" describe un feature. El beneficio convierte mejor porque apela al dolor del usuario.

Fase 7: Lanzamiento

Tu producto esta listo. Tiene auth, pagos, la funcionalidad core, y una landing page. Ahora necesitas que alguien lo use.

Deploy a Vercel

Si tu proyecto ya esta en un repositorio de GitHub, el deploy a Vercel es directo.

Terminal
$

Configura las variables de entorno en el dashboard de Vercel antes del primer deploy:

bash
# Variables criticas para tu SaaS
STRIPE_SECRET_KEY=sk_live_...
STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRICE_ID=price_...
NEXT_PUBLIC_APP_URL=https://tuapp.com
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
AUTH_SECRET=...  # openssl rand -base64 32
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
Variables de entorno en produccion

Nunca expongas SUPABASE_SERVICE_ROLE_KEY o STRIPE_SECRET_KEY al cliente. Estas variables solo deben existir en el servidor. Verifica que ninguna tenga el prefijo NEXT_PUBLIC_. Si necesitas verificar que tu repo no tiene secrets expuestos, herramientas como datahogo escanean tu repositorio de GitHub y te alertan antes de que sea un problema.

Canales de lanzamiento

No necesitas un presupuesto de marketing. Estos canales son gratuitos y efectivos para micro-SaaS:

Product Hunt

  • Prepara assets: logo, capturas de pantalla, video de 1 minuto
  • Lanza un martes o miercoles (menos competencia que lunes)
  • Pide a tu red que apoye el lanzamiento
  • Responde cada comentario el dia del lanzamiento

Twitter/X

  • Hilo de "building in public": cuenta la historia de como construiste el producto
  • Muestra metricas reales (ingresos, usuarios, costo de infra)
  • Sigue la comunidad de #buildinpublic e #indiehackers

Reddit

  • r/SaaS, r/indiehackers, r/webdev, r/nextjs
  • No hagas spam. Comparte la historia genuina de construccion
  • Responde preguntas. Aporta valor antes de promocionar

Hacker News (Show HN)

  • Titulo: "Show HN: [Nombre] -- [que hace en una linea]"
  • Si tu producto tiene un angulo tecnico interesante, HN puede generar miles de visitas en un dia

Comunidades de nicho

  • Si tu producto es para freelancers, busca comunidades de freelancers
  • Si es para e-commerce, busca foros de Shopify, WooCommerce
  • Las comunidades de nicho convierten mejor que los canales generales

Dominio personalizado

Conecta tu dominio en Vercel. SSL se configura automaticamente. Si necesitas guia, la guia de deploy en Vercel cubre custom domains paso a paso.

Desglose de costos reales

Esto es lo que realmente cuesta operar un micro-SaaS con este stack:

Con 0 usuarios (desarrollo)

ServicioCosto
Vercel (Hobby)$0
Supabase (Free)$0
Stripe$0 (solo cobran por transaccion)
Dominio (.com)~$12/ano
Resend (Free)$0
Total~$1/mes

Con 100 usuarios pagando ($19/mes)

ServicioCosto
Vercel (Pro)$20/mes
Supabase (Pro)$25/mes
Stripe (2.9% + 30c por transaccion)~$85/mes
Dominio~$1/mes
Resend (si envias emails)$0-20/mes
Total~$150/mes
Ingreso$1,900/mes
Margen~92%

Con 500 usuarios pagando

ServicioCosto
Vercel (Pro)$20/mes
Supabase (Pro)$25-75/mes
Stripe~$425/mes
Otros~$50/mes
Total~$570/mes
Ingreso$9,500/mes
Margen~94%

Los margenes de un SaaS son brutalmente buenos comparados con cualquier otro tipo de negocio. La mayoria del costo es Stripe, que es proporcional al ingreso.

Errores comunes (y como evitarlos)

Despues de ver muchos micro-SaaS fallar, estos son los patrones que se repiten:

1. Over-engineering desde el dia uno

No necesitas microservicios. No necesitas Kubernetes. No necesitas event sourcing. No necesitas una arquitectura que soporte un millon de usuarios cuando tienes cero.

Next.js con Supabase y Vercel escala a miles de usuarios sin problema. Optimiza cuando tengas el problema, no antes.

2. No validar la idea

El error mas caro. Tres meses construyendo algo que nadie quiere. La validacion descrita en la Fase 1 no es opcional. Es el paso mas importante de todo el proceso.

3. Construir features que nadie pidio

Despues del lanzamiento, vas a tener la tentacion de agregar features que "seria genial tener". No lo hagas. Habla con tus usuarios. Pregunta que les falta. Construye solo lo que piden.

4. No cobrar desde el principio

Si tu producto no tiene precio desde el dia uno, nunca vas a encontrar el momento para empezar a cobrar. Los usuarios que se registran para algo gratis tienen expectativas diferentes a los que pagan. Filtra por calidad desde el inicio.

5. Ignorar la seguridad

Un SaaS maneja datos de usuarios y datos de pago. Las consecuencias de una brecha son reales: perdida de confianza, posibles multas, y clientes que se van para siempre.

Lo basico:

  • Variables de entorno, no secrets en el codigo
  • Validacion de todos los inputs con Zod
  • RLS en Supabase para cada tabla
  • HTTPS obligatorio (Vercel lo maneja automaticamente)
  • Sesiones con expiracion

Para una guia completa de seguridad, revisa seguridad en aplicaciones Next.js.

6. Perfeccionismo

Tu primera version va a ser vergonzosa comparada con lo que imaginas. Eso esta bien. Los usuarios quieren una solucion que funcione, no una obra de arte. Publica, recibe feedback, mejora. El ciclo es mas importante que la perfeccion.

Recapitulacion: el camino de la idea al primer cliente

El proceso completo, resumido:

  1. Encuentra un problema que la gente ya tiene y ya intenta resolver
  2. Valida antes de escribir codigo: landing page, pre-ventas, conversaciones
  3. Define tu stack: Next.js + Supabase + Stripe + Vercel
  4. Construye la funcionalidad core y nada mas
  5. Agrega auth con Auth.js o Clerk
  6. Integra pagos con Stripe Checkout y webhooks
  7. Crea una landing page que explique el beneficio, no el feature
  8. Lanza en Product Hunt, Twitter, Reddit, y comunidades de nicho
  9. Itera basandote en feedback real de usuarios que pagan

El gap entre "quiero construir un SaaS" y "tengo un SaaS que genera ingresos" no es tecnico. Es de ejecucion. Tienes todas las herramientas, el stack es gratuito para empezar, y el mercado es enorme. Lo unico que falta es empezar.


Recursos adicionales

#saas#nextjs#stripe#supabase#typescript#emprendimiento

Preguntas frecuentes

Que es un micro-SaaS?

Un micro-SaaS es un producto de software como servicio manejado por una o pocas personas, enfocado en resolver un problema especifico para un nicho. Generan entre $1K y $50K+ al mes con costos operativos minimos.

Cuanto cuesta crear un micro-SaaS con Next.js?

Con el tier gratuito de Vercel, Supabase y Stripe (sin costo fijo), puedes lanzar un MVP por $0 al mes. Los costos suben cuando tienes usuarios: dominio ($12/ano), Vercel Pro ($20/mes si necesitas), y la comision de Stripe por transaccion.

Cuanto tiempo toma construir un micro-SaaS?

Un MVP funcional con auth, pagos y la funcionalidad core puede estar listo en 2-4 semanas si usas Next.js con las herramientas correctas. El 80% del tiempo se va en iteracion y marketing, no en codigo.

Necesito saber backend para construir un SaaS?

Con Next.js App Router, Server Actions y Supabase, el frontend y backend viven en el mismo proyecto. Si sabes React y TypeScript, tienes lo necesario para construir un SaaS full-stack.

Como encuentro una idea para un micro-SaaS?

Busca problemas que tu mismo tienes como desarrollador. Los mejores micro-SaaS nacen de frustraciones reales: herramientas de productividad, automatizaciones, dashboards para nichos especificos. Valida la idea antes de construir: pregunta en Twitter, Reddit, y busca si la gente ya paga por algo similar.