Files
leopost/.planning/research/STACK.md
Michele dc3ea1cf58 docs: complete domain research
Research dimensions:
- STACK.md: Technology stack recommendations (Next.js 15, Supabase, Vercel AI SDK, BullMQ)
- FEATURES.md: Feature landscape analysis (table stakes vs differentiators)
- ARCHITECTURE.md: System architecture design (headless, multi-tenant, job queue)
- PITFALLS.md: Common mistakes to avoid (rate limits, AI slop, cost control)
- SUMMARY.md: Synthesized findings with roadmap implications

Key findings:
- Stack: Next.js 15 + Supabase Cloud + Vercel AI SDK (multi-provider)
- Architecture: Modular monolith → microservices, headless pattern
- Critical pitfall: API rate limits (Meta reduced by 96%), AI cost explosion

Phase recommendations:
1. Core Scheduling Foundation (6-8 weeks)
2. Reliability & Differentiation (4-6 weeks)
3. Advanced Innovation (8-12 weeks)
4. Scale & Polish (ongoing)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-31 02:08:10 +01:00

26 KiB

Technology Stack

Project: Leopost - AI Social Media Management SaaS Researched: 2026-01-31 Overall Confidence: HIGH

Executive Summary

The 2025/2026 standard stack for AI-powered social media management SaaS centers around Next.js 15+ with React 19, Supabase for backend, Vercel AI SDK for multi-provider AI, and BullMQ for job scheduling. This recommendation is based on verified current versions, ecosystem maturity, and specific requirements for headless architecture and Italian market deployment.


Core Framework

Technology Version Purpose Why
Next.js 15.5+ (or 16.x) Full-stack React framework - Stable Turbopack for fast dev/builds
- Server Actions eliminate API boilerplate
- Built-in API routes for webhooks
- Excellent Vercel deployment
- Ready for headless architecture (separate frontend/backend)
Confidence: HIGH
React 19.2+ UI library - Stable release (Dec 2024)
- Actions API perfect for AI streaming
- Server Components for reduced bundle size
- use API for async data
Confidence: HIGH
TypeScript 5.8+ Type safety - Latest stable (Feb 2025)
- --erasableSyntaxOnly for Node.js compatibility
- Improved performance in watch mode
Confidence: HIGH
Node.js 20 LTS Runtime - LTS support through 2026-04-30
- Native TypeScript support (experimental)
- Required for BullMQ
Confidence: HIGH

Installation:

npx create-next-app@latest leopost --typescript --tailwind --app --use-npm

Database & Backend

Technology Version Purpose Why
Supabase Cloud (latest) PostgreSQL + Auth + Storage - Perfect for Italian SaaS: Free tier supports 50k MAU
- Built-in social auth (Google, Facebook)
- Row-Level Security (RLS) for multi-tenant
- Real-time subscriptions for editorial calendar
- Storage for user-uploaded images/logos
- 4-5x cheaper than Firebase
Confidence: HIGH
Drizzle ORM 0.36+ Type-safe ORM - Faster than Prisma for simple queries
- SQL-like syntax (easier for complex queries)
- Excellent Supabase integration
- Smaller bundle size for edge functions
- Better serverless cold starts
Alternative: Prisma (if DX > performance)
Confidence: MEDIUM
Redis 7.2+ (via Upstash) Job queue storage - Required for BullMQ
- Upstash offers serverless Redis (free tier)
- Sub-10ms latency globally
- No connection management
Confidence: HIGH

Why Supabase over VPS Supabase:

  • Isolation: Each customer gets isolated database (security)
  • Scalability: Auto-scaling, no VPS resource limits
  • Compliance: SOC2 on Team plan ($599/mo when needed)
  • Free tier: 500MB DB, 1GB storage, 2GB bandwidth

AI Integration

Technology Version Purpose Why
Vercel AI SDK 6.0+ Multi-provider AI orchestration - Single API for GPT, Claude, Gemini
- Built-in streaming with React hooks
- Automatic retry/fallback between providers
- Smaller bundle than individual SDKs
- Native Next.js integration
- OpenResponses API support (Jan 2026)
Confidence: HIGH
OpenAI SDK 4.x GPT models (primary) - GPT-4 Turbo for content generation
- DALL-E 3 for image generation ($0.040/image)
- Function calling for structured output
Confidence: HIGH
Anthropic SDK 0.x Claude models (fallback) - Claude 3.5 Sonnet for long-form content
- 200k token context for brand memory
- Lower hallucination rate
Confidence: HIGH
Google AI SDK 0.x Gemini models (budget) - Gemini Pro free tier (60 req/min)
- Multimodal for image + text
- Good for Italian language
Confidence: MEDIUM

Image Generation Strategy:

  • Primary: DALL-E 3 via OpenAI API ($0.040/image standard quality)
  • Alternative: Stable Diffusion via Replicate API ($0.002/image) for budget tier
  • Why not Midjourney: No API access, Discord-only workflow

Multi-Provider Strategy:

// Vercel AI SDK handles provider switching automatically
import { openai, anthropic, google } from '@ai-sdk/openai'
import { streamText } from 'ai'

// Automatic fallback: OpenAI → Claude → Gemini
const result = await streamText({
  model: openai('gpt-4-turbo'),
  prompt: userInput,
  fallbacks: [anthropic('claude-3-5-sonnet'), google('gemini-pro')]
})

Job Scheduling & Queue

Technology Version Purpose Why
BullMQ 5.66+ Background job processing - Industry standard for social media scheduling
- Redis-backed persistence
- Cron expressions for recurring posts
- Timezone-aware scheduling
- Automatic retries on API failures
- Horizontal scaling support
- 854 dependent packages (proven)
Confidence: HIGH
Upstash Redis - Queue storage - Serverless Redis (no connection pooling)
- Free tier: 10k commands/day
- Global edge network
- REST API (works with serverless)
Confidence: HIGH

Why BullMQ over alternatives:

  • vs Agenda: BullMQ has Redis persistence (Agenda uses MongoDB)
  • vs node-cron: BullMQ handles job failures, retries, distributed systems
  • vs Inngest: BullMQ is open-source, no vendor lock-in

Installation:

npm install bullmq ioredis

Social Media APIs

Platform API Purpose Why
Facebook + Instagram Meta Graph API Post to Pages/Business accounts - Unified API for both platforms
- Supports Photos, Videos, Carousels, Reels, Stories
- Built-in scheduling (publish_time)
- Free (no API costs)
- Requires Business/Creator account
Confidence: HIGH
LinkedIn LinkedIn Developer API Post to personal/company pages - Marketing Developer Platform
- Supports images, videos, articles
- UGC (User Generated Content) API
- Free (rate limits apply)
Confidence: MEDIUM

Social Media API Wrapper (Recommended):

  • Build custom wrapper around Meta Graph API + LinkedIn API
  • Why not unified API services (Late, Ayrshare):
    • Added cost ($50-200/mo)
    • Rate limits on top of platform limits
    • Not needed for 3 platforms
    • Custom wrapper = full control + no middleman

Meta Graph API Setup:

# Requires:
# 1. Facebook App (developers.facebook.com)
# 2. Business account verification
# 3. Instagram Professional account linked
# 4. App Review for instagram_content_publish permission

Messaging Integration

Technology Version Purpose Why
Telegraf 4.16+ Telegram Bot framework - TypeScript-native (built-in types)
- Modern API (better than node-telegram-bot-api)
- Webhook + long polling support
- Scene-based conversations
- Middleware architecture
Confidence: HIGH
WhatsApp Business API Cloud API WhatsApp integration - Official Meta Cloud API (free tier)
- Webhook-based message handling
- Template messages for notifications
- Requires Business verification
Alternative: Baileys (unofficial, risky)
Confidence: MEDIUM

Recommendation:

  • Phase 1: Telegram only (easier, no verification)
  • Phase 2: WhatsApp (requires Meta Business verification, 2-4 weeks)

UI & Styling

Technology Version Purpose Why
shadcn/ui Latest Component library - Copy-paste components (you own the code)
- Built on Radix UI (accessibility)
- TailwindCSS styling
- 130M+ monthly Radix downloads
- Used by Vercel, Linear, Supabase
- 5 visual styles (Vega, Nova, Maia, Lyra, Mira)
- Radix OR Base UI choice
Confidence: HIGH
TailwindCSS 4.0+ Utility-first CSS - Industry standard for SaaS
- JIT compilation (small bundles)
- Dark mode built-in
- Responsive design utilities
Confidence: HIGH
Lucide React Latest Icon library - Modern fork of Feather Icons
- Tree-shakeable (small bundle)
- Consistent 24x24 grid
- Default for shadcn/ui
Confidence: HIGH
Radix UI Latest Headless primitives - Best-in-class accessibility
- ARIA attributes built-in
- Keyboard navigation
- Focus management
- Underlying tech for shadcn/ui
Confidence: HIGH

UI Setup:

npx shadcn@latest init
npx shadcn@latest add button dialog calendar

State Management

Technology Version Purpose Why
Zustand 5.0+ Global state (AI providers, user settings) - Smallest bundle (1.2KB)
- No boilerplate (vs Redux)
- Perfect for chat state, AI config
- Redux DevTools support
- Middleware for persistence
Confidence: HIGH
Jotai 2.x+ Atomic state (form fields, calendar) - Fine-grained reactivity
- Perfect for editorial calendar cells
- Suspense support (async atoms)
- Minimal re-renders
- Works alongside Zustand
Confidence: MEDIUM

When to use each:

  • Zustand: AI provider selection, brand context, global settings
  • Jotai: Editorial calendar state, form validation, derived computations

Payment Processing

Technology Version Purpose Why
Stripe Latest Payment processor - Dominant in Italy (supports SEPA, cards)
- Native Italian invoicing (fatturazione elettronica)
- Subscription management built-in
- Strong fraud prevention
- 2.9% + €0.25 per transaction
- Customer Portal for self-service
Confidence: HIGH

Why Stripe over alternatives:

  • vs Paddle: Paddle 5% + $0.50 (more expensive), US-focused
  • vs Lemon Squeezy: Acquired by Stripe (unstable), server issues reported
  • Stripe = standard for EU SaaS billing compliance

Italian Requirements:

  • Enable Stripe Tax for Italian VAT (22%)
  • Issue invoices via Stripe Invoicing
  • SDI (Sistema di Interscambio) integration for e-invoicing

Supporting Libraries

Essential

Library Version Purpose When to Use
zod 3.x Schema validation All API routes, form validation, AI outputs
date-fns 3.x Date manipulation Scheduling, timezone conversion, calendar
react-hook-form 7.x Form management Post composer, settings forms
@tanstack/react-query 5.x Server state Cache social media posts, user data
clsx + tailwind-merge Latest Conditional CSS Dynamic component styling
sonner Latest Toast notifications Success/error messages, post confirmations
cmdk Latest Command palette Chat UI, keyboard shortcuts

AI-Specific

Library Version Purpose When to Use
ai (Vercel) 6.x AI streaming hooks useChat(), useCompletion() for chat UI
openai 4.x Direct OpenAI access Image generation, embeddings
@anthropic-ai/sdk 0.x Direct Claude access Long-form content, low hallucination
@google/generative-ai 0.x Direct Gemini access Free tier for budget users
langchain 0.3.x AI agent orchestration Future: multi-step workflows, RAG

Utilities

Library Version Purpose When to Use
axios 1.x HTTP client Social media API calls (better than fetch)
sharp 0.33+ Image processing Resize uploads, optimize for platforms
uuid 10.x Unique IDs Job IDs, session tracking
jose 5.x JWT handling Supabase JWT verification
winston 3.x Logging Production error tracking

Alternatives Considered

Category Recommended Alternative Why Not Alternative
Framework Next.js Remix, Astro Next.js has better AI SDK integration, larger ecosystem, Vercel deployment
Backend Supabase Firebase, PlanetScale Supabase cheaper, PostgreSQL > Firestore for relational data, RLS built-in
ORM Drizzle Prisma Drizzle faster runtime, better edge support. Prisma better DX, slower cold starts
AI SDK Vercel AI SDK Individual SDKs Vercel SDK provides unified API, automatic fallbacks, smaller bundle
Queue BullMQ Inngest, Trigger.dev BullMQ open-source, self-hosted, no vendor lock-in, proven at scale
State Zustand Redux, Recoil Zustand 1.2KB, zero boilerplate, easier learning curve for freelancers
UI shadcn/ui Chakra, MUI shadcn = you own code, no runtime overhead, Tailwind-native
Payment Stripe Paddle, PayPal Stripe best Italian compliance, e-invoicing support, most reliable
Image Gen DALL-E 3 Midjourney Midjourney has no API, DALL-E has predictable pricing, better prompt adherence

Architecture Decisions

Headless Architecture

Frontend (Next.js App Router):

/app
  /api              # API routes for webhooks (Meta, Stripe)
  /(auth)           # Auth pages (login, signup)
  /(dashboard)      # Protected dashboard routes
  /chat             # AI chat interface
  /calendar         # Editorial calendar
  /settings         # User settings

Backend (Next.js Server Actions + API Routes):

/actions            # Server Actions for mutations
  /posts.ts         # Create, update, delete posts
  /ai.ts            # AI generation actions
  /social.ts        # Social media API calls

/lib
  /queue            # BullMQ job definitions
  /supabase         # Supabase client, queries
  /ai               # AI provider wrappers
  /social           # Meta Graph API, LinkedIn API

Why Server Actions over API Routes:

  • For internal mutations: Server Actions (simpler, type-safe, auto-revalidation)
  • For webhooks/public endpoints: API Routes (Meta webhooks, Stripe webhooks)

Database Schema Strategy

Multi-Tenancy with RLS:

-- Supabase Row-Level Security
CREATE POLICY "Users can only see their own posts"
  ON posts FOR SELECT
  USING (auth.uid() = user_id);

-- Indexes for performance
CREATE INDEX posts_user_scheduled_idx
  ON posts(user_id, scheduled_at)
  WHERE status = 'scheduled';

Key Tables:

  • users (Supabase Auth managed)
  • posts (content, platforms, scheduled_at, status)
  • brand_contexts (logos, colors, company info, embeddings)
  • ai_provider_configs (API keys per user)
  • social_accounts (connected FB/IG/LinkedIn accounts)
  • usage_tracking (tier limits, AI token usage)

Development Workflow

Local Development

# 1. Install dependencies
npm install

# 2. Setup environment variables
cp .env.example .env.local
# Add: NEXT_PUBLIC_SUPABASE_URL, SUPABASE_SERVICE_KEY
#      OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_AI_KEY
#      UPSTASH_REDIS_URL, STRIPE_SECRET_KEY

# 3. Run Supabase locally (optional)
npx supabase start

# 4. Run dev server
npm run dev

# 5. Run queue worker (separate terminal)
npm run queue:dev

Deployment

Recommended: Vercel + Upstash + Supabase Cloud

# 1. Deploy Next.js to Vercel
vercel deploy --prod

# 2. Setup Upstash Redis (serverless)
# Free tier: 10k commands/day

# 3. Setup Supabase Cloud
# Free tier: 500MB DB, 50k MAU

# 4. Deploy BullMQ worker
# Option A: Vercel Serverless Function (cron-triggered)
# Option B: Separate Node.js process on VPS (24/7)

VPS Deployment (Alternative):

  • Deploy Next.js on VPS (Docker container)
  • BullMQ worker as separate container
  • Redis on VPS or Upstash
  • Lower cost, more control, complex setup

Cost Analysis

Free Tier Limits (MVP)

Service Free Tier Monthly Cost at 100 Users Notes
Vercel 100GB bandwidth, 1k serverless hours $0 (likely within free tier) Upgrade to Pro at $20/mo if needed
Supabase 500MB DB, 50k MAU, 1GB storage $0 Upgrade to Pro at $25/mo at 100k MAU
Upstash Redis 10k commands/day $0 ~$10/mo if exceeding (100k commands)
OpenAI Pay-per-use ~$50-150 GPT-4 Turbo: $0.01/1k tokens, DALL-E: $0.04/image
Anthropic Pay-per-use ~$30-100 Claude 3.5 Sonnet: $0.003/1k in, $0.015/1k out
Gemini 60 req/min free $0 Free tier generous for fallback
Stripe Pay-per-transaction 2.9% + €0.25 per transaction No monthly fee
Meta APIs Free $0 Facebook + Instagram + WhatsApp Cloud API
LinkedIn API Free (rate limited) $0 -
Telegram API Free $0 -

Total MVP Cost: $50-150/mo (mostly AI tokens) Total at 100 Paying Users ($20/mo avg): $200-300/mo (AI scales with usage)


Security Considerations

API Key Management

// NEVER expose API keys client-side
// ❌ DON'T:
// process.env.NEXT_PUBLIC_OPENAI_API_KEY

// ✅ DO: Use Server Actions or API Routes
'use server'
export async function generateContent(prompt: string) {
  const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
  // ...
}

Supabase RLS

-- Enable RLS on ALL tables
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- Create policies for CRUD
CREATE POLICY "Users CRUD own posts"
  ON posts FOR ALL
  USING (auth.uid() = user_id);

Rate Limiting

// Use Upstash Rate Limit
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, '1 m'), // 10 requests per minute
})

// In API route or Server Action
const { success } = await ratelimit.limit(userId)
if (!success) throw new Error('Rate limit exceeded')

Performance Optimization

Next.js Optimizations

// 1. Enable Turbopack (default in Next.js 16)
// next.config.js
module.exports = {
  experimental: {
    turbo: true,
  },
}

// 2. Optimize images
import Image from 'next/image'
<Image src="/logo.png" width={200} height={200} alt="Logo" />

// 3. Use Server Components by default
// Only add 'use client' when needed (interactivity)

// 4. Dynamic imports for heavy components
const Editor = dynamic(() => import('./Editor'), { ssr: false })

Database Optimizations

-- Indexes for common queries
CREATE INDEX posts_user_status_idx ON posts(user_id, status);
CREATE INDEX posts_scheduled_at_idx ON posts(scheduled_at) WHERE status = 'scheduled';

-- Partial indexes for active data
CREATE INDEX active_posts_idx ON posts(user_id, created_at)
  WHERE status IN ('draft', 'scheduled');

AI Response Caching

// Cache common AI responses
import { unstable_cache } from 'next/cache'

const getCachedAIResponse = unstable_cache(
  async (prompt: string) => {
    return await generateContent(prompt)
  },
  ['ai-response'],
  { revalidate: 3600 } // 1 hour
)

Testing Strategy

Type Tool Why
Unit Vitest Faster than Jest, ESM support, compatible with Next.js
Integration Playwright E2E testing, headless browser, multi-browser
API MSW (Mock Service Worker) Mock social media APIs, AI APIs for testing
Type TypeScript + Zod Runtime + compile-time validation

Testing Social Media APIs

// Mock Meta Graph API responses
import { http, HttpResponse } from 'msw'

export const handlers = [
  http.post('https://graph.facebook.com/v18.0/me/feed', () => {
    return HttpResponse.json({ id: 'post_123' })
  }),
]

Internationalization (i18n)

Italian Market Specifics

// Use next-intl for i18n
import { useTranslations } from 'next-intl'

const t = useTranslations('Dashboard')
t('welcome') // "Benvenuto"

// Italian date formatting
import { format } from 'date-fns'
import { it } from 'date-fns/locale'

format(new Date(), 'PPP', { locale: it })
// "31 gennaio 2026"

Future Multi-Language

Phase 1: Italian only Phase 2: Add English (for expansion)

Setup:

npm install next-intl

Monitoring & Observability

Category Tool Why
Error Tracking Sentry Best Next.js integration, free tier 5k events/mo
Analytics Vercel Analytics Built-in, privacy-friendly, free on Pro plan
Logging Axiom Serverless-friendly, generous free tier
APM Vercel Speed Insights Built-in performance monitoring
Uptime BetterStack Free tier, status page, incident management

Sources

Framework & Core

AI & Multi-Provider

Database & Backend

Job Queue & Scheduling

Social Media APIs

Messaging Integration

UI & Components

State Management

Payments


Installation Guide

Step 1: Create Next.js Project

npx create-next-app@latest leopost \
  --typescript \
  --tailwind \
  --app \
  --use-npm \
  --import-alias "@/*"

cd leopost

Step 2: Install Core Dependencies

# Framework essentials
npm install zod react-hook-form @hookform/resolvers date-fns clsx tailwind-merge

# Supabase
npm install @supabase/supabase-js @supabase/ssr

# Drizzle ORM
npm install drizzle-orm postgres
npm install -D drizzle-kit

# AI SDKs
npm install ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google openai @anthropic-ai/sdk @google/generative-ai

# Queue
npm install bullmq ioredis

# State management
npm install zustand jotai

# UI components
npx shadcn@latest init
npx shadcn@latest add button dialog calendar form input textarea select

# Social media + messaging
npm install telegraf axios

# Payment
npm install stripe @stripe/stripe-js

# Utilities
npm install sonner cmdk sharp uuid jose winston

Step 3: Setup Environment Variables

# .env.local
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=xxx
SUPABASE_SERVICE_ROLE_KEY=xxx

# AI Providers
OPENAI_API_KEY=sk-xxx
ANTHROPIC_API_KEY=sk-ant-xxx
GOOGLE_AI_API_KEY=xxx

# Redis (Upstash)
UPSTASH_REDIS_REST_URL=https://xxx.upstash.io
UPSTASH_REDIS_REST_TOKEN=xxx

# Stripe
STRIPE_SECRET_KEY=sk_test_xxx
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

# Social Media
META_APP_ID=xxx
META_APP_SECRET=xxx
LINKEDIN_CLIENT_ID=xxx
LINKEDIN_CLIENT_SECRET=xxx

# Telegram
TELEGRAM_BOT_TOKEN=xxx

# App
NEXT_PUBLIC_APP_URL=http://localhost:3000

Step 4: Initialize Supabase

npx supabase init
npx supabase db push

Step 5: Run Development

# Terminal 1: Next.js dev server
npm run dev

# Terminal 2: BullMQ worker (create worker.ts first)
npm run queue:dev

Next Steps

  1. Setup Supabase schema (users, posts, brand_contexts)
  2. Configure Drizzle ORM with Supabase connection
  3. Implement Vercel AI SDK chat interface
  4. Setup BullMQ job queue for scheduling
  5. Integrate Meta Graph API for Facebook/Instagram
  6. Add Stripe subscription management
  7. Deploy to Vercel with environment variables

Ready for Roadmap Creation: This stack is production-ready, cost-effective for MVP, and scales to thousands of users.