Skip to content

shivaram19/growthpilot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ GrowthPilot

AI-Powered Growth Automation for Shopify + Meta Ads

Next.js TypeScript Prisma Tests License

Connect your Shopify store β†’ Sync products & orders β†’ Run AI-optimized Meta Ads β†’ Watch revenue grow

Quick Start Β· Architecture Β· API Reference Β· Testing Β· Deployment


πŸ“‹ What is GrowthPilot?

GrowthPilot is a full-stack platform that connects your Shopify store with Meta (Facebook/Instagram) Ads and uses AI to automate growth decisions β€” ad copy generation, audience targeting, budget optimization, and anomaly detection.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                 β”‚
β”‚    Shopify Store ──sync──▢ GrowthPilot ──optimize──▢ Meta Ads   β”‚
β”‚         β”‚                      β”‚                        β”‚       β”‚
β”‚    Products                 AI Engine               Campaigns   β”‚
β”‚    Orders               (GPT-4o-mini)              Ad Sets      β”‚
β”‚    Customers         Budget Optimization           Audiences    β”‚
β”‚                     Anomaly Detection               Insights    β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Features

Feature Description
πŸ› Shopify Sync Real-time product, order & customer sync with webhook support
πŸ“’ Meta Ads Management Create campaigns, ad sets, audiences via Meta Marketing API
πŸ€– AI Ad Copy GPT-4o-mini generates headlines, primary text, CTAs with tone control
🎯 Audience Suggestions AI analyzes store data to discover untapped customer segments
πŸ’° Budget Optimization Automatically reallocates spend across campaigns for max ROAS
🚨 Anomaly Detection Detects CPA spikes, ROAS drops, creative fatigue in real-time
πŸ“Š Analytics Dashboard Revenue, ROAS, orders, CTR, CPC β€” with period comparisons
⚑ Automation Rules Trigger actions on ROAS drop, budget threshold, inventory low

🧰 Tech Stack

Layer Technology Purpose
Frontend Next.js 15 (App Router + Turbopack) React server components, API routes
Auth Clerk Multi-tenant orgs, OAuth, session management
Database PostgreSQL 16 + Prisma ORM 21 models, type-safe queries
Validation Zod Runtime schema validation for all API inputs
AI OpenAI GPT-4o-mini Ad copy, audience suggestions, budget optimization
Styling Tailwind CSS Custom dark design system
Testing Vitest + Testing Library 60 unit tests across 6 suites
Monorepo Turborepo + npm workspaces Shared packages, parallel builds
Deployment Docker + Railway Multi-stage builds, health checks

⚑ Quick Start

Prerequisites

Tool Version Check Install (Mac)
Node.js β‰₯ 20 node -v brew install node@20
Docker Latest docker --version brew install --cask docker
Git Any git --version brew install git

Option A: Automated Setup (Recommended)

# Clone the repo
git clone <your-repo-url> growthpilot
cd growthpilot

# Run the setup script β€” handles everything
chmod +x start.sh
./start.sh

The script walks through 12 steps with color-coded output:

 βœ” Node.js v24.11.1 (β‰₯20 βœ“)          ← Prerequisites check
 βœ” Docker 29.2.1 (running)
 βœ” Created .env with random CRON_SECRET ← Environment config
 βœ” PostgreSQL container started         ← Database setup
 βœ” All dependencies installed           ← npm install
 βœ” Prisma client generated (20+ models) ← ORM codegen
 βœ” All database tables created          ← Schema push
 βœ” 60 passed (60)                       ← Full test suite
 βœ” Ready in 2.1s                        ← Dev server live

Option B: Manual Setup (Step by Step)

Step 1 β€” Clone & Install

git clone <your-repo-url> growthpilot
cd growthpilot
npm install

What happens: npm resolves 3 workspaces β€” apps/web, packages/database, packages/shared β€” and installs all dependencies including Next.js, Prisma, Vitest, Zod, Clerk SDK, and OpenAI SDK.

Step 2 β€” Configure Environment

cp .env.example .env

Open .env in your editor and fill in API keys (see Configuration below).

Step 3 β€” Start PostgreSQL

# Start Postgres via Docker
docker compose -f docker/docker-compose.yml up -d db

# Verify it's running
docker ps

Port 5432 already in use? See Port Conflicts section.

Step 4 β€” Generate Prisma Client

npx prisma generate --schema=packages/database/prisma/schema.prisma

What happens: Prisma reads the schema (21 models, 9 enums) and generates a fully typed TypeScript client in node_modules/.prisma/client.

Step 5 β€” Push Database Schema

npx prisma db push --schema=packages/database/prisma/schema.prisma

What happens: Creates all 21 tables in PostgreSQL β€” Organization, Product, Order, MetaAdCampaign, AIInsight, etc.

Step 6 β€” Run Tests (Optional)

npm test

Expected output: Tests 60 passed (60) across 6 test suites.

Step 7 β€” Start Development Server

npm run dev

What happens: Next.js 15 starts with Turbopack on port 3000. Compiles middleware, mounts all API routes, and serves the React app.


🌐 Open in Browser

Once the dev server is running, you'll have access to:

URL What You'll See
localhost:3000 🏠 Marketing landing page
localhost:3000/sign-in πŸ”‘ Clerk authentication (sign up / sign in)
localhost:3000/dashboard πŸ“Š Dashboard with metrics, charts, AI insights
localhost:3000/api/health ❀️ {"status":"ok","timestamp":"..."}

πŸ”‘ Configuration

πŸ”— Quick Reference β€” Where to Get Every Token

Token Get it from Required?
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY dashboard.clerk.com β†’ API Keys βœ… Yes
CLERK_SECRET_KEY dashboard.clerk.com β†’ API Keys βœ… Yes
OPENAI_API_KEY platform.openai.com/api-keys βœ… Yes (for AI)
SHOPIFY_API_KEY partners.shopify.com/organizations β†’ Apps ⬜ Optional
SHOPIFY_API_SECRET partners.shopify.com/organizations β†’ Apps ⬜ Optional
SHOPIFY_WEBHOOK_SECRET partners.shopify.com/organizations β†’ Apps β†’ Webhooks ⬜ Optional
META_APP_ID developers.facebook.com/apps β†’ Settings β†’ Basic ⬜ Optional
META_APP_SECRET developers.facebook.com/apps β†’ Settings β†’ Basic ⬜ Optional

Step-by-Step: Get Each Token

1. πŸ” Clerk (Authentication) β€” Required

Create Account & Application

  1. Open https://clerk.com/sign-up β†’ Create a free account
  2. After sign-up, you'll land on the dashboard. If not, go to https://dashboard.clerk.com
  3. Click "Create application"
  4. Name it GrowthPilot (or anything you like)
  5. Under Sign-in options, check: Email, Google, GitHub (pick what you want)
  6. Click "Create application"

Copy API Keys

  1. You'll be taken to the Quickstart page β€” skip it
  2. In the left sidebar, click "API Keys"
  3. You'll see two keys:
    • Publishable key β€” starts with pk_test_
    • Secret key β€” click "eye" icon to reveal, starts with sk_test_
  4. Copy both into your .env:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
CLERK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

⚠️ Without these keys, the app will crash on /dashboard with an auth redirect error.

2. πŸ€– OpenAI (AI Features) β€” Required for AI

Create Account

  1. Open https://platform.openai.com/signup β†’ Sign up (or sign in)
  2. You may need to add a payment method at https://platform.openai.com/settings/organization/billing/overview
    • GrowthPilot uses gpt-4o-mini which costs ~$0.15 per 1M input tokens (very cheap)

Create API Key

  1. Go to https://platform.openai.com/api-keys
  2. Click "Create new secret key"
  3. Name it GrowthPilot
  4. Click "Create secret key"
  5. Copy it immediately β€” you won't be able to see it again
  6. Paste into .env:
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxx

πŸ’‘ Without this key, all other features (Shopify sync, dashboard, campaigns) still work β€” only the /api/ai/generate endpoint requires it.

3. πŸ› Shopify (Store Integration) β€” Optional

Create Partner Account & App

  1. Open https://partners.shopify.com/signup β†’ Create a free Partner account
  2. After sign-up, go to https://partners.shopify.com/organizations
  3. Select your organization (or create one)
  4. In the left sidebar, click "Apps"
  5. Click "Create app" β†’ Choose "Create app manually"
  6. Name it GrowthPilot, set the App URL to http://localhost:3000
  7. Click "Create"

Get API Credentials

  1. On the app page, click "Client credentials" tab
  2. You'll see:
    • Client ID β†’ this is your SHOPIFY_API_KEY
    • Client secret β†’ click "Show" β†’ this is your SHOPIFY_API_SECRET
  3. For webhooks, go to "App setup" β†’ scroll to "Event subscriptions"
    • Your webhook signing secret is the SHOPIFY_WEBHOOK_SECRET
SHOPIFY_API_KEY=your_client_id_here
SHOPIFY_API_SECRET=your_client_secret_here
SHOPIFY_WEBHOOK_SECRET=your_webhook_signing_secret

Create a Development Store (for testing)

  1. Back in Partners dashboard β†’ "Stores" in the left sidebar
  2. Click "Add store" β†’ "Create development store"
  3. Choose "Create a store to test and build"
  4. Fill in store name β†’ Click "Create"
  5. In your dev store, go to Settings β†’ Apps and sales channels β†’ Develop apps
  6. Click "Create an app" β†’ Name it β†’ "Create app"
  7. Go to "Configuration" tab β†’ Under Admin API access scopes, select:
    • read_products, write_products
    • read_orders, write_orders
    • read_customers
  8. Click "Save" β†’ then go to "API credentials" tab
  9. Click "Install app" β†’ "Install"
  10. Copy the Admin API access token (starts with shpat_) β€” this is what you'll use when connecting the store via the GrowthPilot UI

πŸ”‘ The shpat_ access token is entered through the GrowthPilot dashboard when you connect a store, NOT in .env. The .env keys are for the app-level OAuth credentials.

4. πŸ“’ Meta / Facebook (Ads Integration) β€” Optional

Create Developer Account & App

  1. Open https://developers.facebook.com β†’ Log in with your Facebook account
  2. If first time, click "Get Started" β†’ agree to terms β†’ verify your account
  3. Go to https://developers.facebook.com/apps/create/
  4. Select use case β†’ "Other" β†’ Click "Next"
  5. Select app type β†’ "Business" β†’ Click "Next"
  6. Name it GrowthPilot, enter your email β†’ Click "Create app"

Get App Credentials

  1. In the app dashboard left sidebar, click "App settings" β†’ "Basic"
  2. You'll see:
    • App ID β†’ this is your META_APP_ID
    • App secret β†’ click "Show", enter password β†’ this is your META_APP_SECRET
META_APP_ID=123456789012345
META_APP_SECRET=abcdef1234567890abcdef1234567890

Enable Marketing API

  1. In the left sidebar β†’ "Add products" (or "Products +")
  2. Find "Marketing API" β†’ Click "Set up"
  3. This gives your app access to create campaigns, ad sets, and audiences

Get an Access Token (for testing)

  1. Go to https://developers.facebook.com/tools/explorer/
    • This is the Graph API Explorer
  2. In the top-right dropdown, select your GrowthPilot app
  3. Click "Generate Access Token"
  4. Grant permissions when prompted:
    • ads_management
    • ads_read
    • business_management
  5. Copy the generated token β€” this is what you'll use when connecting a Meta ad account through the GrowthPilot UI

Find Your Ad Account ID

  1. Go to https://business.facebook.com/settings/ad-accounts
  2. Select your ad account
  3. The Ad Account ID is shown (format: act_123456789)
  4. You'll enter this in GrowthPilot when connecting Meta Ads

πŸ’‘ The access token from Graph API Explorer expires in ~1 hour. For production, you'll need a System User Token which doesn't expire.

Full .env Reference

# ─── Database (auto-configured if using Docker) ────────────
DATABASE_URL="postgresql://growthpilot:growthpilot_dev@localhost:5432/growthpilot"
REDIS_URL="redis://localhost:6379"

# ─── Auth (required) ───────────────────────────────────────
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_..."
CLERK_SECRET_KEY="sk_test_..."
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL="/dashboard"
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL="/onboarding"

# ─── AI (required for AI features) ─────────────────────────
OPENAI_API_KEY="sk-..."

# ─── Shopify (optional) ────────────────────────────────────
SHOPIFY_API_KEY="..."
SHOPIFY_API_SECRET="..."
SHOPIFY_WEBHOOK_SECRET="..."

# ─── Meta Ads (optional) ───────────────────────────────────
META_APP_ID="..."
META_APP_SECRET="..."

# ─── App ────────────────────────────────────────────────────
NEXT_PUBLIC_APP_URL="http://localhost:3000"
CRON_SECRET="auto-generated-by-start-script"

πŸ— Architecture

Project Structure

growthpilot/
β”‚
β”œβ”€β”€ apps/web/                          ← Next.js 15 Application
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ page.tsx                   ← Landing page
β”‚   β”‚   β”œβ”€β”€ layout.tsx                 ← Root layout + Clerk provider
β”‚   β”‚   β”œβ”€β”€ globals.css                ← Dark design system (Tailwind)
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ dashboard/
β”‚   β”‚   β”‚   β”œβ”€β”€ layout.tsx             ← Sidebar (8 nav items)
β”‚   β”‚   β”‚   └── page.tsx               ← Metrics, charts, AI insights
β”‚   β”‚   β”‚
β”‚   β”‚   └── api/
β”‚   β”‚       β”œβ”€β”€ health/route.ts        ← GET  /api/health
β”‚   β”‚       β”œβ”€β”€ shopify/
β”‚   β”‚       β”‚   β”œβ”€β”€ connect/route.ts   ← POST/GET  /api/shopify/connect
β”‚   β”‚       β”‚   └── sync/route.ts      ← POST      /api/shopify/sync
β”‚   β”‚       β”œβ”€β”€ meta/
β”‚   β”‚       β”‚   └── connect/route.ts   ← POST/GET  /api/meta/connect
β”‚   β”‚       β”œβ”€β”€ campaigns/route.ts     ← GET/POST   /api/campaigns
β”‚   β”‚       β”œβ”€β”€ analytics/route.ts     ← GET        /api/analytics
β”‚   β”‚       β”œβ”€β”€ ai/
β”‚   β”‚       β”‚   └── generate/route.ts  ← POST       /api/ai/generate
β”‚   β”‚       β”œβ”€β”€ webhooks/
β”‚   β”‚       β”‚   └── shopify/route.ts   ← POST       /api/webhooks/shopify
β”‚   β”‚       └── cron/route.ts          ← GET        /api/cron
β”‚   β”‚
β”‚   β”œβ”€β”€ lib/                           ← Core business logic
β”‚   β”‚   β”œβ”€β”€ shopify/service.ts         ← Shopify Admin API client
β”‚   β”‚   β”œβ”€β”€ meta/service.ts            ← Meta Marketing API client
β”‚   β”‚   β”œβ”€β”€ ai/service.ts              ← OpenAI-powered AI engine
β”‚   β”‚   β”œβ”€β”€ prisma/client.ts           ← Database client singleton
β”‚   β”‚   └── utils/
β”‚   β”‚       β”œβ”€β”€ auth.ts                ← Clerk auth + API helpers
β”‚   β”‚       └── analytics.ts           ← Metrics aggregation engine
β”‚   β”‚
β”‚   └── __tests__/                     ← 6 test suites, 60 tests
β”‚       β”œβ”€β”€ setup.ts
β”‚       β”œβ”€β”€ schemas.test.ts
β”‚       β”œβ”€β”€ shopify-service.test.ts
β”‚       β”œβ”€β”€ meta-service.test.ts
β”‚       β”œβ”€β”€ ai-service.test.ts
β”‚       β”œβ”€β”€ analytics.test.ts
β”‚       └── api-utils.test.ts
β”‚
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ database/                      ← Prisma ORM package
β”‚   β”‚   β”œβ”€β”€ prisma/schema.prisma       ← 21 models, 9 enums
β”‚   β”‚   └── src/index.ts               ← Client export
β”‚   β”‚
β”‚   └── shared/                        ← Shared validation & types
β”‚       └── src/index.ts               ← Zod schemas, TS types, plan constants
β”‚
β”œβ”€β”€ docker/
β”‚   β”œβ”€β”€ Dockerfile                     ← Multi-stage production build
β”‚   └── docker-compose.yml             ← PostgreSQL + Redis
β”‚
β”œβ”€β”€ start.sh                           ← One-command Mac setup (12 steps)
β”œβ”€β”€ turbo.json                         ← Turborepo pipeline
β”œβ”€β”€ railway.toml                       ← Railway deployment config
└── .env.example                       ← Environment variable template

Service Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Next.js API Routes                       β”‚
β”‚  /shopify/*    /meta/*    /ai/*    /campaigns   /analytics   β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚            β”‚         β”‚          β”‚           β”‚
       β–Ό            β–Ό         β–Ό          β–Ό           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Shopify   β”‚ β”‚  Meta   β”‚ β”‚   AI    β”‚ β”‚   Analytics Service  β”‚
β”‚  Service   β”‚ β”‚ Service β”‚ β”‚ Service β”‚ β”‚                      β”‚
β”‚            β”‚ β”‚         β”‚ β”‚         β”‚ β”‚  getDashboardMetrics  β”‚
β”‚ syncProds  β”‚ β”‚ getCamp β”‚ β”‚ genCopy β”‚ β”‚  getComparisonMetrics β”‚
β”‚ syncOrders β”‚ β”‚ adSets  β”‚ β”‚ suggest β”‚ β”‚                      β”‚
β”‚ syncCust   β”‚ β”‚ insight β”‚ β”‚ optimze β”‚ β”‚                      β”‚
β”‚ webhooks   β”‚ β”‚ audienc β”‚ β”‚ anomaly β”‚ β”‚                      β”‚
β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      β”‚             β”‚           β”‚                  β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚    Prisma ORM      β”‚
                  β”‚    21 Models       β”‚
                  β”‚    PostgreSQL 16   β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Database Schema (21 Models, 9 Enums)

Organization ─┬──▢ Member (role: OWNER | ADMIN | MEMBER | VIEWER)
              β”‚
              β”œβ”€β”€β–Ά ShopifyStore
              β”‚      β”œβ”€β”€β–Ά Product
              β”‚      β”œβ”€β”€β–Ά Order ──▢ OrderItem
              β”‚      └──▢ ShopifyCustomer
              β”‚
              β”œβ”€β”€β–Ά MetaAdAccount
              β”‚      └──▢ MetaAdCampaign
              β”‚             └──▢ MetaAdSet
              β”‚                    └──▢ MetaAd ──▢ AdCreative
              β”‚
              β”œβ”€β”€β–Ά Campaign ◀──many-to-many──▢ Audience
              β”‚                (via CampaignAudience)
              β”‚
              β”œβ”€β”€β–Ά AIInsight (type: ANOMALY | RECOMMENDATION | PREDICTION)
              β”œβ”€β”€β–Ά AutomationRule ──▢ AutomationLog
              β”œβ”€β”€β–Ά BudgetAlert
              └──▢ SyncLog

              Order ──▢ AdAttribution (tracks which ad drove which order)

🌐 API Reference

Authentication

All /api/* routes (except /api/health, /api/webhooks/*, /api/cron) require a valid Clerk session. The middleware at apps/web/middleware.ts enforces this automatically.

Route Map

System

Method Endpoint Auth Description
GET /api/health None Server status check
GET /api/cron Bearer CRON_SECRET Scheduled sync for all stores & accounts

Shopify Integration

Method Endpoint Auth Description
POST /api/shopify/connect Clerk Connect a Shopify store
GET /api/shopify/connect Clerk List connected stores with counts
POST /api/shopify/sync Clerk Manual product/order/customer sync
POST /api/webhooks/shopify HMAC-SHA256 Receive real-time Shopify events
πŸ“ POST /api/shopify/connect β€” Connect Store
curl -X POST http://localhost:3000/api/shopify/connect \
  -H "Content-Type: application/json" \
  -d '{
    "shopDomain": "my-store.myshopify.com",
    "accessToken": "shpat_xxxxxxxxxxxx",
    "scope": "read_products,read_orders,read_customers"
  }'

Response:

{
  "success": true,
  "data": {
    "storeId": "clxyz...",
    "shopDomain": "my-store.myshopify.com"
  }
}

What happens behind the scenes:

  1. Validates input with ShopifyConnectSchema
  2. Creates ShopifyStore record
  3. Triggers background sync: products β†’ orders β†’ customers
  4. Registers 8 webhook topics
πŸ“ POST /api/shopify/sync β€” Manual Sync
curl -X POST http://localhost:3000/api/shopify/sync \
  -H "Content-Type: application/json" \
  -d '{ "storeId": "clxyz...", "type": "all" }'

Type options: "all" | "products" | "orders" | "customers"

πŸ“ Webhook Topics Handled
Topic Action
orders/create Upsert order with line items
orders/updated Update order status/totals
products/create Create product record
products/update Update product details
products/delete Remove product
customers/create Create customer profile
customers/update Update customer data
app/uninstalled Deactivate store

All webhooks are verified with HMAC-SHA256 signature validation.

Meta Ads Integration

Method Endpoint Auth Description
POST /api/meta/connect Clerk Connect an ad account
GET /api/meta/connect Clerk List ad accounts with campaign counts

Campaigns

Method Endpoint Auth Description
GET /api/campaigns Clerk List campaigns (paginated, filterable)
POST /api/campaigns Clerk Create a new campaign
πŸ“ GET /api/campaigns β€” Query Parameters
Param Type Default Description
page number 1 Page number
limit number 20 Items per page (max 100)
sortBy string createdAt Sort field
sortOrder string desc asc or desc
status string β€” Filter by: DRAFT ACTIVE PAUSED COMPLETED ARCHIVED
πŸ“ POST /api/campaigns β€” Create Campaign
curl -X POST http://localhost:3000/api/campaigns \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q1 Retargeting",
    "type": "RETARGETING",
    "goal": "Recover abandoned carts",
    "budget": 1000,
    "aiOptimized": true,
    "audienceIds": ["aud-1", "aud-2"]
  }'

Campaign types: AWARENESS Β· TRAFFIC Β· CONVERSIONS Β· RETARGETING Β· LOOKALIKE Β· DYNAMIC_PRODUCT

AI Engine

All AI actions go through one endpoint with different action values:

POST /api/ai/generate

Action What It Does Key Input
ad-copy Generate headline, text, CTA + 2 variations productId, tone, platform
suggest-audiences Discover 3-5 audience segments productIds?
optimize-budget Reallocate spend for max ROAS campaignIds, totalBudget
detect-anomalies Find CPA spikes, ROAS drops, fatigue β€” (analyzes all active campaigns)
score-products Composite 0-10 performance score storeId
πŸ“ Ad Copy Generation
curl -X POST http://localhost:3000/api/ai/generate \
  -H "Content-Type: application/json" \
  -d '{
    "action": "ad-copy",
    "productId": "prod-123",
    "tone": "playful",
    "platform": "meta_story",
    "targetAudience": "Women 25-45",
    "includeEmoji": true
  }'

Tones: professional Β· casual Β· urgent Β· playful Β· luxurious

Platforms: meta_feed Β· meta_story Β· meta_reel

Response includes: headline, primaryText, description, callToAction, plus 2 variations

πŸ“ Budget Optimization
curl -X POST http://localhost:3000/api/ai/generate \
  -H "Content-Type: application/json" \
  -d '{
    "action": "optimize-budget",
    "campaignIds": ["camp-1", "camp-2", "camp-3"],
    "totalBudget": 5000,
    "optimizeFor": "roas"
  }'

Optimize for: roas Β· conversions Β· cpa

Returns per-campaign allocations with reasoning and expected impact.

Analytics

Method Endpoint Auth Description
GET /api/analytics Clerk Dashboard metrics
GET /api/analytics?compare=true&period=month Clerk Period-over-period comparison
πŸ“ Analytics Response Shape
{
  "success": true,
  "data": {
    "totalRevenue": 15420.50,
    "totalSpend": 3200.00,
    "roas": 4.82,
    "totalOrders": 142,
    "averageOrderValue": 108.59,
    "conversionRate": 3.2,
    "impressions": 450000,
    "clicks": 8500,
    "ctr": 1.89,
    "cpc": 0.38,
    "cpa": 22.54,
    "revenueByDay": [
      { "date": "2024-01-15", "revenue": 520.00, "spend": 100.00 }
    ],
    "topProducts": [
      { "id": "prod-1", "title": "Premium Widget", "orders": 45, "revenue": 4500.00 }
    ],
    "topCampaigns": [
      { "id": "camp-1", "name": "Holiday Sale", "spend": 500, "revenue": 3200, "roas": 6.40 }
    ]
  }
}

With ?compare=true, response includes current, previous, and changes objects with percentage deltas.


πŸ§ͺ Testing

Run All Tests

# From project root
npm test

# With verbose output
cd apps/web && npx vitest run --reporter=verbose

# Watch mode (re-runs on file save)
cd apps/web && npx vitest

Test Suite Breakdown

Suite File Tests What's Covered
Schemas schemas.test.ts 26 All Zod schemas β€” Shopify, Meta, Campaign, AI, Pagination, Plans
Shopify shopify-service.test.ts 6 Product/order/customer sync, webhook registration, API errors
Meta meta-service.test.ts 8 Campaign CRUD, ad sets, audiences, insights, budget conversion
AI ai-service.test.ts 6 Anomaly detection (CPA/ROAS/CTR thresholds), product scoring
Analytics analytics.test.ts 7 Metric aggregation, sorting, empty data, period comparisons
API Utils api-utils.test.ts 5 apiSuccess, apiError, AuthError helpers
60

Expected Output

 βœ“ __tests__/schemas.test.ts > ShopifyConnectSchema > accepts valid domain
 βœ“ __tests__/schemas.test.ts > CampaignCreateSchema > accepts all campaign types
 βœ“ __tests__/shopify-service.test.ts > syncProducts > syncs products from Shopify API
 βœ“ __tests__/meta-service.test.ts > creates campaign with budget in cents
 βœ“ __tests__/ai-service.test.ts > detects ROAS drop below 1.0
 βœ“ __tests__/analytics.test.ts > calculates metrics from orders and campaigns
 ...

 Test Files  6 passed (6)
      Tests  60 passed (60)
   Duration  1.17s

🐳 Docker

Local Development Stack

# Start PostgreSQL + Redis
docker compose -f docker/docker-compose.yml up -d

# View logs
docker compose -f docker/docker-compose.yml logs -f db

# Stop everything
docker compose -f docker/docker-compose.yml down

# Full reset (delete all data)
docker compose -f docker/docker-compose.yml down -v

Port Conflicts

Port 5432 is commonly used by Homebrew Postgres or SSH tunnels.

# Check what's using the port
lsof -i :5432

# Option A: Use port 5433 instead
sed -i '' 's/5432:5432/5433:5432/' docker/docker-compose.yml
sed -i '' 's/localhost:5432/localhost:5433/' .env
docker compose -f docker/docker-compose.yml up -d db

# Option B: Stop existing Postgres
brew services stop postgresql@16

# Option C: Kill the process
lsof -ti:5432 | xargs kill -9

Database GUI

Prisma Studio gives you a visual browser for all 21 tables:

npx prisma studio --schema=packages/database/prisma/schema.prisma

Opens at localhost:5555 β€” browse Organizations, Products, Orders, Campaigns, AI Insights, etc.


πŸš€ Deployment

Railway (Recommended)

Step 1    Push to GitHub
  β”‚
  β–Ό
Step 2    railway.app β†’ New Project β†’ Connect repo
  β”‚       (auto-detects railway.toml)
  β–Ό
Step 3    Add PostgreSQL service
  β”‚       (DATABASE_URL auto-injected)
  β–Ό
Step 4    Set environment variables
  β”‚       (all keys from .env.example)
  β–Ό
Step 5    Deploy β†’ Health check passes β†’ Live
# Push to GitHub
git init && git add . && git commit -m "Initial commit"
gh repo create growthpilot --private --push

The railway.toml configures everything:

  • Multi-stage Docker build
  • Health check on /api/health
  • Auto-restart on failure (3 retries)

Set up cron job for data sync (every 6 hours):

GET https://your-app.up.railway.app/api/cron
Authorization: Bearer $CRON_SECRET

Docker (Self-Hosted)

# Build
docker build -f docker/Dockerfile -t growthpilot .

# Run
docker run -p 3000:3000 --env-file .env growthpilot

πŸ”§ Common Commands

Command Description
npm run dev Start dev server (Turbopack, port 3000)
npm test Run all 60 tests
npm run build Production build
npx prisma studio --schema=packages/database/prisma/schema.prisma Visual database browser
npx prisma db push --schema=packages/database/prisma/schema.prisma Push schema changes
npx prisma generate --schema=packages/database/prisma/schema.prisma Regenerate typed client
docker compose -f docker/docker-compose.yml up -d Start Postgres + Redis
docker compose -f docker/docker-compose.yml logs db Database logs

πŸ›  Troubleshooting

Problem Solution
npm install fails rm -rf node_modules package-lock.json && npm install
Port 3000 in use lsof -ti:3000 | xargs kill -9
Port 5432 in use See Port Conflicts above
Prisma generate fails Run npm install first, then retry
Clerk auth errors Verify both keys in .env (publishable + secret)
turbo: command not found Use npm run dev β€” it calls Next.js directly
Docker not starting Open Docker Desktop app, wait for engine to start
Tests fail on import npx prisma generate --schema=packages/database/prisma/schema.prisma
ECONNREFUSED on DB Check Postgres: docker ps β€” restart if needed
Vite CJS warning Harmless deprecation notice β€” doesn't affect functionality

πŸ“„ License

MIT


Built with Next.js 15, Prisma, Clerk, OpenAI, and lots of β˜•

⬆ Back to top

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors