Skip to main content
RapidDev - Software Development Agency

How to Build Integration hub with V0

Build a Zapier-style integration hub with V0 using Next.js, Supabase for connection and flow data, and AES-256-GCM encryption for OAuth tokens. You'll create a connector marketplace, visual flow builder, webhook endpoints, and execution logging — all in about 2-4 hours without touching a terminal.

What you'll build

  • Connector marketplace grid showing available third-party services with search and auth type badges
  • OAuth2 connection flow with callback handling, token encryption, and automatic refresh
  • Visual flow builder where users select triggers, add action steps, and configure data transforms
  • Webhook endpoints that receive external events and trigger flow executions automatically
  • Flow execution engine that runs steps sequentially with per-step logging and error handling
  • Execution history dashboard with step-by-step results, timing, and error details
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced11 min read2-4 hoursV0 PremiumApril 2026RapidDev Engineering Team
TL;DR

Build a Zapier-style integration hub with V0 using Next.js, Supabase for connection and flow data, and AES-256-GCM encryption for OAuth tokens. You'll create a connector marketplace, visual flow builder, webhook endpoints, and execution logging — all in about 2-4 hours without touching a terminal.

What you're building

An integration hub lets users connect third-party services and create automated data flows between them. Users connect services like Slack, GitHub, and Stripe, then build flows that trigger on events and execute actions across connected services.

V0 generates the connector marketplace, flow builder UI, and execution dashboard from prompts. Supabase stores connector configurations, encrypted credentials, flow definitions, and execution logs.

The architecture uses Next.js App Router with API routes for OAuth callbacks and webhook endpoints, a client component for the interactive flow builder, Server Actions for flow management, AES-256-GCM encryption for third-party tokens stored in Supabase, and a sequential execution engine with per-step logging.

Final result

An integration hub with connector marketplace, OAuth connection management, visual flow builder, webhook triggers, sequential execution engine, and detailed execution logging.

Tech stack

V0AI Code Generator
Next.jsFull-Stack Framework
Tailwind CSSStyling
shadcn/uiComponent Library
SupabaseDatabase & Auth

Prerequisites

  • A V0 account (Premium recommended for the complex multi-route app)
  • A Supabase project for storing connections, flows, and execution logs
  • OAuth credentials for at least one service (e.g., GitHub or Slack) for testing
  • Understanding of API integrations (OAuth, webhooks, API keys)

Build steps

1

Set up the project and integration schema

Open V0 and create a new project. Connect Supabase via the Connect panel. Create the schema for connectors, connections, flows, steps, executions, and webhooks.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Build an integration hub. Create a Supabase schema with:
3// 1. connectors: id (uuid PK), name (text), slug (text unique), description (text), icon_url (text), auth_type (text check in 'oauth2','api_key','webhook'), oauth_config (jsonb), base_url (text), is_active (boolean default true)
4// 2. user_connections: id (uuid PK), user_id (uuid FK to auth.users), connector_id (uuid FK to connectors), credentials_encrypted (text), status (text default 'active' check in 'active','expired','revoked'), metadata (jsonb), connected_at (timestamptz), expires_at (timestamptz)
5// 3. flows: id (uuid PK), user_id (uuid FK to auth.users), name (text), description (text), is_active (boolean default false), trigger_connection_id (uuid FK to user_connections), trigger_config (jsonb), created_at (timestamptz), updated_at (timestamptz)
6// 4. flow_steps: id (uuid PK), flow_id (uuid FK to flows), position (int), connection_id (uuid FK to user_connections), action_type (text), action_config (jsonb), transform_code (text)
7// 5. flow_executions: id (uuid PK), flow_id (uuid FK to flows), status (text check in 'running','completed','failed'), started_at (timestamptz), completed_at (timestamptz), steps_log (jsonb), error_message (text)
8// 6. webhook_endpoints: id (uuid PK), flow_id (uuid FK to flows), token (text unique), is_active (boolean default true), last_triggered_at (timestamptz)
9// Seed connectors table with 5 entries: GitHub, Slack, Stripe, Gmail, Notion with their base_urls and auth_types
10// Add RLS: users see only their own connections, flows, and executions.

Pro tip: Connect to GitHub via the Git panel immediately — this system has 10+ API routes and benefits from version-controlled incremental development with automatic branching.

Expected result: Database schema created with 6 tables, seeded connectors, and RLS policies. The schema supports OAuth2, API key, and webhook authentication types.

2

Build the connector marketplace and OAuth flow

Create the connector marketplace page and the OAuth2 callback handler that securely exchanges codes for tokens and encrypts them before storage.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Build connector marketplace and OAuth:
3// 1. app/connectors/page.tsx — marketplace:
4// - Grid of Card components showing each connector with icon, name, description, auth_type Badge
5// - Search Input filtering by name
6// - "Connect" Button per connector that either:
7// - Opens OAuth2 authorization URL (for oauth2 type)
8// - Opens Dialog with API key Input (for api_key type)
9// - Already-connected services show a green "Connected" Badge and "Disconnect" Button
10//
11// 2. app/api/oauth/[connector]/callback/route.ts:
12// - Receives code and state from OAuth provider
13// - Exchanges authorization code for access_token and refresh_token
14// - Encrypts tokens using AES-256-GCM with ENCRYPTION_KEY from env vars
15// - Stores encrypted tokens in user_connections.credentials_encrypted
16// - Sets expires_at based on token expiry
17// - Redirects to /connections with success message
18//
19// 3. app/connections/page.tsx — my connections:
20// - Card per connected service showing connector icon, name, status Badge, connected_at
21// - "Refresh" Button for expired OAuth tokens
22// - AlertDialog for disconnection confirmation
23// - Server Action to revoke connection (set status='revoked')

Expected result: Users browse available connectors, initiate OAuth flows, and manage their connections. Tokens are encrypted with AES-256-GCM before storage.

3

Build the visual flow builder

Create the flow builder page where users select a trigger, add action steps with connected services, configure data transforms, and activate the flow.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Build a flow builder at app/flows/new/page.tsx as a 'use client' component.
3// Requirements:
4// - Flow name Input at the top
5// - Trigger selection: Select a connected service as trigger, configure trigger event (e.g., GitHub: push, Slack: message, Stripe: payment_intent.succeeded) via Select
6// - Steps list below trigger, each step as a Card showing:
7// - Step number and connection icon
8// - Select for connected service
9// - Select for action type (e.g., Slack: send_message, GitHub: create_issue)
10// - Action config: Textarea for JSON template with {{trigger.data.field}} placeholders
11// - Optional transform_code: Textarea for JavaScript transform
12// - Remove step Button (trash icon)
13// - "+ Add Step" Button to append a new step
14// - Sheet sidebar for step configuration details
15// - "Save & Activate" Button that creates the flow, flow_steps, and if trigger is webhook, creates a webhook_endpoint with a unique token
16// - Switch for flow active/inactive toggle
17// - Use Card for steps, Sheet for config sidebar, Select for dropdowns, Accordion for advanced settings

Pro tip: Use the {{trigger.data.field}} placeholder syntax to pass data between steps — the execution engine replaces these with actual values at runtime.

Expected result: Users can build multi-step flows by selecting triggers and actions from their connected services, with data transform configuration per step.

4

Build the execution engine and webhook handler

Create the flow execution API that runs steps sequentially with logging, and the webhook endpoint that triggers flows from external events.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Build the execution engine and webhooks:
3// 1. app/api/flows/[id]/execute/route.ts:
4// - POST handler that creates a flow_execution with status='running'
5// - Iterates through flow_steps ordered by position
6// - For each step: decrypt the connection credentials, call the external API with the action_config (replacing {{}} placeholders with trigger data), log the step result (success/failure, response data, timing) in steps_log jsonb array
7// - If a step fails: set execution status='failed', store error_message, stop execution
8// - On completion: set status='completed', completed_at=now()
9// - Return the execution result
10//
11// 2. app/api/webhooks/[token]/route.ts:
12// - POST handler that receives incoming webhook payloads
13// - Looks up the flow by webhook_endpoint.token
14// - Checks flow.is_active and webhook_endpoint.is_active
15// - Updates webhook_endpoint.last_triggered_at
16// - Calls the execute API with the webhook payload as trigger data
17// - Returns 200 immediately, execution runs in background
18//
19// 3. Create a helper lib/encryption.ts:
20// - encrypt(plaintext: string): string — AES-256-GCM with ENCRYPTION_KEY
21// - decrypt(ciphertext: string): string — decrypts back to plaintext
22// - ENCRYPTION_KEY from process.env (never NEXT_PUBLIC_)

Expected result: The execution engine runs flow steps sequentially with per-step logging. Webhook endpoints receive external events and trigger flow executions automatically.

5

Build the dashboard and execution logs

Create the main dashboard showing active flows and recent executions, and the execution log viewer with step-by-step results.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Build dashboard and logs:
3// 1. app/page.tsx — dashboard:
4// - Stats Cards: active flows count, connected services count, executions today, failure rate
5// - Recent executions Table: flow name, trigger source, status Badge, duration, timestamp
6// - Active flows list with quick toggle Switch per flow
7// - "Create Flow" Button linking to /flows/new
8//
9// 2. app/flows/[id]/page.tsx — flow detail:
10// - Flow name, description, active Switch, trigger info Card
11// - Steps list showing the flow configuration
12// - Execution history Table for this flow with status, timing, started_at
13// - "Run Now" Button that manually triggers execution
14// - Webhook URL display (if trigger type is webhook) with copy Button
15//
16// 3. app/flows/[id]/logs/page.tsx — execution detail:
17// - Execution header: status Badge, duration, started_at → completed_at
18// - Accordion showing each step's result: step name, connection icon, status, response data preview, timing
19// - If failed: error_message highlighted in red Card
20// - JSON viewer for step input/output data
21// - "Re-run" Button to retry the execution

Expected result: The dashboard shows active flows and recent execution status. Flow detail pages show configuration and execution history. Log pages provide step-by-step debugging.

Complete code

lib/encryption.ts
1import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'
2
3const ALGORITHM = 'aes-256-gcm'
4const KEY = Buffer.from(process.env.ENCRYPTION_KEY!, 'hex')
5
6export function encrypt(plaintext: string): string {
7 const iv = randomBytes(16)
8 const cipher = createCipheriv(ALGORITHM, KEY, iv)
9 let encrypted = cipher.update(plaintext, 'utf8', 'hex')
10 encrypted += cipher.final('hex')
11 const authTag = cipher.getAuthTag().toString('hex')
12 return `${iv.toString('hex')}:${authTag}:${encrypted}`
13}
14
15export function decrypt(ciphertext: string): string {
16 const [ivHex, authTagHex, encrypted] = ciphertext.split(':')
17 const iv = Buffer.from(ivHex, 'hex')
18 const authTag = Buffer.from(authTagHex, 'hex')
19 const decipher = createDecipheriv(ALGORITHM, KEY, iv)
20 decipher.setAuthTag(authTag)
21 let decrypted = decipher.update(encrypted, 'hex', 'utf8')
22 decrypted += decipher.final('utf8')
23 return decrypted
24}
25
26export function generateWebhookToken(): string {
27 return randomBytes(32).toString('hex')
28}

Customization ideas

Add conditional branching

Let users add IF/ELSE conditions between steps that route execution based on previous step output values.

Add retry logic

Configure per-step retry policies with exponential backoff for failed API calls, with a maximum retry count.

Add flow templates

Offer pre-built flow templates (GitHub PR to Slack notification, Stripe payment to email) that users can import and customize.

Add rate limiting

Track API calls per connection and enforce rate limits to prevent exceeding third-party API quotas.

Add scheduled triggers

Let users configure flows to run on a schedule (every hour, daily) using Vercel Cron jobs instead of webhook triggers.

Common pitfalls

Pitfall: Storing OAuth tokens in plain text

How to avoid: Encrypt all credentials with AES-256-GCM using an ENCRYPTION_KEY stored in the Vars tab, never in the database or NEXT_PUBLIC_ variables.

Pitfall: Not handling token expiration

How to avoid: Check expires_at before each API call in the execution engine. If expired, use the stored refresh_token to get a new access token automatically.

Pitfall: Running webhook handlers synchronously

How to avoid: Return 200 immediately from the webhook endpoint and trigger the flow execution asynchronously in the background.

Pitfall: Not logging per-step execution results

How to avoid: Store a steps_log jsonb array in flow_executions with per-step status, response data, timing, and error details.

Best practices

  • Encrypt all third-party credentials with AES-256-GCM before storing in Supabase — use ENCRYPTION_KEY from env vars, never NEXT_PUBLIC_.
  • Implement automatic OAuth token refresh by checking expires_at before each API call in the execution engine.
  • Return 200 immediately from webhook endpoints and process flow executions asynchronously to prevent timeout issues.
  • Log per-step execution results with timing, input/output data, and error details for debugging failed flows.
  • Connect to GitHub via V0's Git panel immediately — the 10+ API routes benefit from version-controlled incremental development.
  • Set Vercel Function timeout to 60s in vercel.json for long-running flow executions that call multiple external APIs.
  • Use RLS policies to ensure users can only see their own connections, flows, and execution logs.

AI prompts to try

Copy these prompts to build this project faster.

ChatGPT Prompt

I'm building an integration hub with Next.js and Supabase. I need to securely store OAuth2 tokens: encrypt with AES-256-GCM before insertion, decrypt only in server-side API routes, and implement automatic token refresh when access tokens expire. Show me the encryption utility, the OAuth callback handler, and the token refresh middleware.

Build Prompt

Build the flow builder interface for an integration hub. Create a 'use client' component where users: 1) Name the flow with an Input. 2) Select a trigger connection and event from Select dropdowns. 3) Add action steps as Card components, each with a connection Select, action_type Select, and Textarea for JSON configuration with {{trigger.data.field}} placeholders. 4) Reorder steps by position. 5) Save with a Server Action that creates flow + flow_steps + webhook_endpoint rows. Include a Switch for active toggle.

Frequently asked questions

Can I build this with the free V0 plan?

The core connector marketplace and flow builder fit within the free tier. V0 Premium is strongly recommended for the complete system with OAuth callbacks, execution engine, and logging.

How are credentials secured?

All OAuth tokens and API keys are encrypted with AES-256-GCM before storage in Supabase. The encryption key lives in the Vars tab (never NEXT_PUBLIC_) and decryption happens only in server-side API routes.

How do webhooks trigger flows?

Each flow with a webhook trigger gets a unique URL with a random token. External services POST to this URL. The handler validates the token, returns 200 immediately, and queues the flow execution.

What happens when a step fails?

The execution engine stops at the failed step, records the error in the steps_log, sets the execution status to failed, and stores the error_message. Users can see exactly which step failed and why in the execution logs.

Can I add more connectors?

Yes. Seed new rows into the connectors table with the service name, OAuth config (if applicable), and base URL. For OAuth2 services, register the callback URL and add the credentials to the Vars tab.

How do I handle token refresh?

The execution engine checks expires_at before each API call. If the token has expired, it uses the stored refresh_token to request a new access_token, re-encrypts, and updates user_connections.

Can RapidDev help build a custom integration platform?

Yes. RapidDev has built 600+ apps including iPaaS platforms with advanced orchestration, error handling, and enterprise-grade security. Book a free consultation to discuss your requirements.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help building your app?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.