Back
Parallel Company Enrichment

Parallel Company Enrichment

Parallel Company Enrichment
Parallel Company Enrichment

Overview

Data Enrichment with Supabase + Parallel

Build a real-time data enrichment pipeline using Supabase Edge Functions and Parallel's Task API.

This cookbook demonstrates how to create a data enrichment experience where users input minimal data (e.g., company names) and get back enriched information automatically.

Screenshot

Why Supabase + Parallel?

FeatureBenefit
Zero infrastructureSupabase Edge Functions + Parallel = no servers to manage
Real-time updatesSupabase Realtime pushes enrichment results to the UI instantly
Flexible schemaJSONB storage adapts to any enrichment fields without migrations
Cost-effectivePay only for what you use on both platforms
Global edgeEdge Functions run close to users, Parallel handles web research

Architecture


_16
┌─────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
_16
│ Web App │────▶│ API Routes │────▶│ Edge Function │────▶│ Parallel API │
_16
│ (Next.js) │ │ (Next.js) │ │ (Supabase) │◀────│ (Task API) │
_16
└─────────────┘ └─────────────────┘ └─────────────────┘ └─────────────────┘
_16
│ │ │ │
_16
│ realtime │ secret key │ writes │ researches
_16
▼ ▼ ▼ ▼
_16
┌─────────────────────────────────────────────────────────────────────────────────────┐
_16
│ Supabase Database │
_16
│ ┌─────────────┐ ┌──────────────────────────────────────┐ │
_16
│ │ companies │ │ enrichment fields (JSONB) │ │
_16
│ │ - name │ │ - industry, funding, employees... │ │
_16
│ │ - website │ │ - custom fields you define │ │
_16
│ │ - status │ │ │ │
_16
│ └─────────────┘ └──────────────────────────────────────┘ │
_16
└─────────────────────────────────────────────────────────────────────────────────────┘

How It Works

  1. User submits a company name (and optional website)
  2. Frontend inserts a record with status: pending
  3. Frontend calls a Next.js API route
  4. API route invokes the Edge Function using the secret key (server-side)
  5. Edge Function calls Parallel's Task API with a structured output schema
  6. Parallel searches the web and returns structured data
  7. Edge Function saves results to the database
  8. Supabase Realtime pushes the update to the frontend
  9. UI updates automatically with enriched data

Quick Start

Prerequisites

1. Clone and Set Up


_10
# Navigate to the cookbook
_10
cd typescript-recipes/parallel-supabase-enrichment
_10
_10
# Link to your Supabase project (config.toml is already provided)
_10
# Find your project ref in: Dashboard > Project Settings > General > Reference ID
_10
# Or from your project URL: https://supabase.com/dashboard/project/<project-ref>
_10
supabase link --project-ref your-project-ref

2. Create the Database Tables

Run the SQL files in your Supabase SQL Editor (Dashboard > SQL Editor > New Query):

  1. Copy and run sql/01_create_companies.sql (required)
  2. Copy and run sql/02_create_enrichment_columns.sql (optional - for dynamic columns)

3. Set Up Secrets


_10
# Set your Parallel API key as a secret
_10
supabase secrets set PARALLEL_API_KEY=your-parallel-api-key

4. Deploy Edge Functions


_10
supabase functions deploy enrich-company
_10
supabase functions deploy poll-enrichment

5. Set Up the Web App


_10
cd web
_10
_10
# Install dependencies
_10
npm install
_10
_10
# Create environment file
_10
cp .env.example .env.local

Edit .env.local with your Supabase credentials (Dashboard > Project Settings):


_10
# From Data API > Project URL
_10
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
_10
# From API Keys > publishable key (client-side)
_10
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-publishable-key
_10
# From API Keys > secret key (server-side only)
_10
SUPABASE_SECRET_KEY=your-secret-key

6. Run the App


_10
npm run dev

Open http://localhost:3000 and start enriching!

Project Structure


_24
parallel-supabase-enrichment/
_24
├── README.md # This file
_24
├── sql/
_24
│ ├── 01_create_companies.sql # Main table with enrichment tracking
_24
│ └── 02_create_enrichment_columns.sql # (Optional) Dynamic column config
_24
├── supabase/
_24
│ ├── config.toml # Supabase configuration
_24
│ └── functions/
_24
│ ├── enrich-company/ # Main enrichment function
_24
│ │ └── index.ts
_24
│ └── poll-enrichment/ # Background polling for long tasks
_24
│ └── index.ts
_24
└── web/ # Next.js frontend
_24
├── app/
_24
│ ├── api/
_24
│ │ ├── enrich/route.ts # API route to call enrich-company
_24
│ │ └── poll/route.ts # API route to call poll-enrichment
_24
│ ├── layout.tsx
_24
│ ├── page.tsx # Main UI
_24
│ └── globals.css
_24
├── lib/
_24
│ └── supabase.ts # Supabase client + types
_24
├── package.json
_24
└── .env.example

Customizing Enrichment Fields

The enrichment schema is defined in the Edge Function. To change what data gets enriched:

Important: When you modify outputSchema in the Edge Function, also update ENRICHMENT_FIELDS in web/lib/supabase.ts to display the new columns in the table.

Option 1: Static Schema (Simpler)

Edit supabase/functions/enrich-company/index.ts:


_16
const outputSchema = {
_16
type: "object",
_16
properties: {
_16
industry: { type: "string", description: "Primary industry" },
_16
employee_count: {
_16
type: "string",
_16
enum: ["1-10", "11-50", "51-200", "201-500", "500+"],
_16
description: "Company size range"
_16
},
_16
headquarters: { type: "string", description: "HQ location (City, Country)" },
_16
// Add your custom fields here
_16
ceo_name: { type: "string", description: "Current CEO or founder name" },
_16
tech_stack: { type: "string", description: "Primary technologies used" },
_16
},
_16
required: ["industry", "employee_count", "headquarters"],
_16
};

Option 2: Dynamic Schema (Advanced)

Use the enrichment_columns table to define fields in the database:


_10
INSERT INTO enrichment_columns (name, display_name, column_type, description)
_10
VALUES ('ceo_name', 'CEO Name', 'text', 'The current CEO or chief executive');

The Edge Function will automatically build the schema from these definitions.

Configuration

Parallel Processors

The Edge Function uses base-fast by default. See processor options and pricing to choose the right one for your use case.


_10
const taskRun = await parallel.taskRun.create({
_10
processor: "base", // Change processor here
_10
// ...
_10
});

Environment Variables

Edge Functions (set via supabase secrets set):

  • PARALLEL_API_KEY - Your Parallel API key

Web App (in .env.local):

  • NEXT_PUBLIC_SUPABASE_URL - Your Supabase project URL
  • NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY - Client-side key for database/realtime
  • SUPABASE_SECRET_KEY - Server-side key for calling Edge Functions (never expose to browser)

Handling Long-Running Tasks

The Parallel Task API may take longer than the Edge Function timeout (50s) for complex enrichments. This cookbook handles that with a polling pattern:

  1. enrich-company starts the task and stores the run_id
  2. If the task doesn't complete in time, it returns with status: processing
  3. poll-enrichment runs periodically to check pending tasks
  4. The frontend polls via API route (/api/poll) every 10 seconds

For production, consider using Supabase Cron to run poll-enrichment automatically instead of client-side polling.

Troubleshooting

"PARALLEL_API_KEY not configured"


_10
supabase secrets set PARALLEL_API_KEY=your-key
_10
# Redeploy the function
_10
supabase functions deploy enrich-company

Enrichment stuck on "processing"

Check Edge Function logs in the Supabase Dashboard (Edge Functions > enrich-company > Logs).

Or trigger a manual poll:


_10
curl -X POST https://your-project.supabase.co/functions/v1/poll-enrichment \
_10
-H "Authorization: Bearer your-secret-key"

Real-time updates not working

Ensure the table has realtime enabled:


_10
ALTER PUBLICATION supabase_realtime ADD TABLE companies;

Resources

License

MIT...

Details

DeveloperParallel
DocumentationLearn

Third-party integrations and docs are managed by Supabase partners.

Get started with Parallel Company Enrichment and Supabase.