Shopify + Klaviyo conversational analytics for SMBs
Get insights from your e-commerce data through natural conversation. Straai connects your Shopify store and Klaviyo email marketing to provide AI-powered analytics that you can query in plain English.
This is a TypeScript monorepo with the following structure:
straai/
├── client/ # React 18 + Vite + TypeScript + Tailwind + shadcn/ui
├── server/ # Node.js + Express + TypeScript API
├── prisma/ # Database schema and migrations
├── .github/ # GitHub Actions CI/CD
└── package.json # Workspace configuration
- Node.js 18+ and npm 8+
- PostgreSQL database (or Supabase account)
- Git
# Clone the repository
git clone <your-repo-url>
cd straai
# Install all dependencies
npm install
# Set up environment files
# Windows (PowerShell):
.\scripts\setup-env.ps1
# Unix/Linux/Mac:
./scripts/setup-env.sh
# Configure your Supabase credentials (see Environment Setup below)
# Edit .env and client/.env with your actual Supabase values
# Set up database (generate client, run migrations, seed data)
npm run db:setup
# Start development servers (client + server)
npm run devThis will start:
- Client: http://localhost:3000
- Server: http://localhost:8000
- API available at: http://localhost:3000/api (proxied)
Copy env.example to .env and configure the following:
Option 1: Local PostgreSQL
DATABASE_URL="postgresql://username:password@localhost:5432/straai_dev"Option 2: Supabase (Recommended for Auth + Database)
# In root .env
DATABASE_URL="postgresql://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres"
SUPABASE_URL="https://[YOUR-PROJECT-REF].supabase.co"
SUPABASE_ANON_KEY="your_supabase_anon_key"
SUPABASE_SERVICE_ROLE_KEY="your_supabase_service_role_key"
# In client/.env
VITE_SUPABASE_URL="https://[YOUR-PROJECT-REF].supabase.co"
VITE_SUPABASE_ANON_KEY="your_supabase_anon_key"- Configure environment variables in root
.env(seeenv.example):STRIPE_SECRET_KEY,STRIPE_PUBLISHABLE_KEY,STRIPE_WEBHOOK_SECRET,STRIPE_PRICE_ID.
- Start the API server:
cd server && npm run dev. - In another terminal, forward webhooks:
Copy the
stripe listen --forward-to localhost:8000/api/billing/webhook
whsec_...value and setSTRIPE_WEBHOOK_SECRET. - Start a trial subscription (no card required):
POST /api/billing/create-customer-and-subscriptionwith{ "priceId": "price_..." }, orPOST /api/billing/start-trial(usesSTRIPE_PRICE_ID).
- Manage subscription via Stripe Billing Portal:
GET /api/billing/portal(Dashboard has a Manage Billing button).POST /api/billing/cancelto cancel at period end, orPOST /api/billing/cancel-nowto end immediately.
- Webhooks handled:
customer.subscription.created|updated|deleted,invoice.payment_succeeded|failed|upcoming.- On
invoice.upcoming, ifRESEND_API_KEYis set, an email is sent prompting to add a payment method.
- On
# OpenAI (for conversational analytics)
OPENAI_API_KEY="sk-..."
# Stripe (for subscription billing)
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_PUBLISHABLE_KEY="pk_test_..."
# Resend (for transactional emails)
RESEND_API_KEY="re_..."
# Shopify (for store integration)
SHOPIFY_CLIENT_ID="your_shopify_app_client_id"
SHOPIFY_CLIENT_SECRET="your_shopify_app_client_secret"
# Klaviyo (for email marketing integration)
KLAVIYO_CLIENT_ID="your_klaviyo_client_id"
KLAVIYO_CLIENT_SECRET="your_klaviyo_client_secret"- Supabase: supabase.com → Create Project → Settings → API
- OpenAI: platform.openai.com
- Stripe: dashboard.stripe.com
- Resend: resend.com/api-keys
- Shopify: partners.shopify.com → Create App
- Klaviyo: developers.klaviyo.com
- Create a new project at supabase.com
- Go to Settings → API to get your keys
- Enable Google OAuth in Authentication → Settings → Auth Providers
- Set up redirect URLs:
http://localhost:3000/auth/callback(development)https://yourdomain.com/auth/callback(production)
- Configure email templates in Authentication → Settings → Email Templates
npm run dev # Start both client and server in development
npm run build # Build both client and server for production
npm run start # Start production server
npm run lint # Lint all workspaces
npm run lint:fix # Fix linting issues
npm run type-check # TypeScript type checking
npm run test # Run tests in all workspacesnpm run db:setup # Full setup: generate + migrate + seed
npm run db:generate # Generate Prisma client
npm run db:migrate # Create and run migrations
npm run db:push # Push schema changes to database (dev only)
npm run db:seed # Seed database with sample data
npm run db:reset # Reset database and re-run migrations
npm run db:studio # Open Prisma Studio (database GUI)npm run dev:client # Start only client (React app)
npm run dev:server # Start only server (Express API)The application uses PostgreSQL with Prisma ORM. Key entities:
-
User: Application users with authentication and profile data
id(UUID),email,passwordHash,supabaseId,emailVerifiedtimezone,companyName, soft delete support
-
Store: Connected Shopify stores
shopifyShopDomain,shopifyAccessTokeninstalledAt,lastSyncAtfor sync tracking
-
KlaviyoIntegration: Klaviyo account connections
accountId,accessToken,refreshToken,expiresAt- OAuth token management with refresh capability
-
Subscription: Stripe subscription management
stripeCustomerId,stripeSubscriptionId,statustrialEndsAt,currentPeriodEndfor billing cycles
-
Report: Generated weekly PDF reports
weekOf(date),pdfPath,generatedAt- Unique constraint per user/store/week
-
Conversation: AI chat conversations
messages(JSONB) for chat history- Optimized for conversational analytics queries
- UUID primary keys for all models
- Soft delete support (
deletedAt) - Comprehensive indexing for performance
- Foreign key constraints with cascade deletes
- JSONB for flexible message storage
Straai uses Supabase Auth for secure authentication with the following features:
- Email/Password: Traditional signup and login
- Google OAuth: One-click social authentication
- Email Verification: Secure account activation
- Password Reset: Self-service password recovery
- JWT-based authentication
- Automatic token refresh
- Protected API routes
- User session management
- Supabase RLS (Row Level Security) ready
- User signs up/logs in via frontend auth form
- Supabase handles authentication and JWT generation
- Frontend stores session and includes JWT in API calls
- Backend middleware verifies JWT with Supabase
- User data syncs between Supabase Auth and local database
AuthForm: Tabbed signup/login with Google OAuthAuthCallback: Handles OAuth redirectsResetPassword: Self-service password resetuseAuthStore: Zustand store for auth state management
authenticate: Protects routes requiring authenticationoptionalAuth: Adds user context if authenticated- User sync endpoints for database synchronization
# Monorepo root deploy
npm run build --workspace=server
npm run start --workspace=serverMake sure to set all environment variables from env.example in your production environment.
# In production (Railway), deploy migrations
npm run db:migrate:deploy --workspace=server# Run all tests
npm run test
# Run tests for specific workspace
npm run test --workspace=client
npm run test --workspace=serverThis project includes:
- ESLint: Code linting
- Prettier: Code formatting
- Husky: Git hooks
- lint-staged: Pre-commit linting
- TypeScript: Type safety
- Prisma: Database ORM
- Tailwind CSS: Utility-first CSS
- shadcn/ui: React component library
Pre-commit hooks automatically:
- Run ESLint and fix issues
- Format code with Prettier
- Run TypeScript checks
- React 18 - UI framework
- Vite - Build tool and dev server
- TypeScript - Type safety
- Tailwind CSS - Styling
- shadcn/ui - Component library
- React Router - Client-side routing
- Node.js - Runtime
- Express - Web framework
- TypeScript - Type safety
- Prisma - Database ORM
- PostgreSQL - Database
- GitHub Actions - CI/CD
- Husky - Git hooks
- ESLint/Prettier - Code quality
- Vite Proxy - Development API routing
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
This project is licensed under the MIT License.
Database connection fails
- Verify DATABASE_URL in .env
- Ensure PostgreSQL is running
- Check database credentials
API calls fail in development
- Verify server is running on port 8000
- Check Vite proxy configuration
- Ensure environment variables are set
Build fails
- Run
npm run type-checkto find TypeScript errors - Ensure all dependencies are installed
- Check for ESLint errors
Prisma issues
- Run
npm run db:generateafter schema changes - Use
npm run db:migrateto create and run migrations - Use
npm run db:pushfor rapid prototyping (development only) - Use
npm run db:seedto populate with sample data - Use
npm run db:resetto reset database and re-run all migrations
Database setup
- For development: Use
npm run db:migratefollowed bynpm run db:seed - For production: Use
npm run db:migrate(never use db:push) - UUIDs are used for all primary keys for better scalability
- Soft deletes are implemented via
deletedAtfield
- Check existing GitHub Issues
- Create a new issue with detailed description
- Include error messages and environment details