Build fails after adding a new venture
Cause: Generated files are stale — ventures.json was edited but generator was not run.
Fix: Run npm run generate, then npm run build again.
Operations Guide
Step-by-step procedures for operating the Pinehaven Ventures platform. Covers adding ventures, running generators, seeding Stripe, deploying to Vercel, and troubleshooting common issues.
Last updated: March 3, 2026. Procedures verified against current production configuration.
The standard operating procedure for adding a new product to the portfolio. This can be executed end-to-end by an AI agent or a human operator.
Add a new entry to the ventures array with all required fields: id, name, tagline, description, color, icon, status, target_market, features, and plans.
Color options: green, blue, purple, orange, red, cyan, amber. For free tiers, set price: 0 and omit stripe_env_key.
Reads ventures.json and regenerates stripe-products.ts, seed-stripe.ts, .env.example, and scaffolds a new product page if one does not already exist.
npm run generateUse npm run generate:dry to preview changes without writing files.
The generator creates a functional but basic product page. Enhance the hero copy, add "How It Works" sections, flesh out features, and adjust pricing card layout.
Existing pages are never overwritten — only new pages are scaffolded.
Creates Stripe products and prices, configures the billing portal, and outputs environment variable assignments.
STRIPE_SECRET_KEY=sk_live_... npm run seed-stripeUse npm run seed-stripe:dry to preview. Copy output env vars into .env.local.
Run TypeScript type checking and a full production build to catch errors before deploying.
npx tsc --noEmit && npm run buildCommit all changes and push. Vercel will automatically build and deploy to pinehavenventures.io.
git add . && git commit -m "Add <venture-name> to portfolio" && git push| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Required | URL-safe slug (e.g., "my-new-app"). Used in routes and Stripe config. |
| name | string | Required | Display name for the product. |
| tagline | string | Required | Short value proposition (one line). |
| description | string | Required | Longer description for the hero section. |
| color | string | Required | Theme color: green, blue, purple, orange, red, cyan, or amber. |
| icon | string | Required | Icon identifier for the product. |
| status | string | Required | Product lifecycle: live, in-development, or coming-soon. |
| target_market | string[] | Required | Array of audience segments. |
| features | string[] | Required | Top-level product features. |
| plans | Plan[] | Required | Array of pricing plans (see plan fields below). |
| has_free_tier | boolean | Optional | Set to true if the product has a $0 plan. |
| has_demo | boolean | Optional | Set to true if a demo page exists. |
| Field | Type | Description |
|---|---|---|
| id | string | Unique plan identifier (e.g., "my-app-starter"). |
| name | string | Display name (e.g., "Starter", "Pro"). |
| price | number | Price in dollars. Use 0 for free tiers. |
| currency | string | Always "usd". |
| interval | string | "month" or "year". |
| stripe_env_key | string | Environment variable name for the Stripe price ID. Omit for free tiers. |
| description | string | Short description of who the plan is for. |
| features | string[] | Features included in this plan. |
| popular | boolean | Mark as the recommended/highlighted plan. |
| Command | Description | Safe to run? |
|---|---|---|
npm run generate | Read ventures.json and regenerate all derived files. Scaffold new product pages. | Safe |
npm run generate:dry | Preview what generate would do without writing any files. | Safe |
npm run seed-stripe | Create products/prices in Stripe and configure billing portal. Requires STRIPE_SECRET_KEY. | Caution |
npm run seed-stripe:dry | Preview what Stripe objects would be created without making API calls. | Safe |
npm run dev | Start the development server with Turbopack at localhost:3000. | Safe |
npm run build | Run a full production build. Catches SSR errors, missing imports, and type issues. | Safe |
npm run lint | Run ESLint with Next.js recommended rules. | Safe |
npx tsc --noEmit | Type-check all TypeScript files without emitting output. Fast validation. | Safe |
Vercel watches the repo for pushes. Every push to main triggers a build.
Add all variables from .env.example to the Vercel project settings. Include Stripe keys, price IDs, and Airtable credentials.
Vercel auto-detects Next.js. No vercel.json or custom config is needed.
Point pinehavenventures.io to the Vercel project via DNS.
In Stripe Dashboard, set the webhook URL to https://pinehavenventures.io/api/stripe/webhooks and select the five handled events.
Use Stripe test mode keys to verify checkout, success, and cancel pages work end to end.
In Stripe Dashboard, check webhook logs to confirm events are received and returning 200.
These five events must be selected in the Stripe Dashboard webhook endpoint configuration. The endpoint URL is https://pinehavenventures.io/api/stripe/webhooks.
| Event | Action |
|---|---|
| checkout.session.completed | Provision access, record customer and subscription IDs |
| customer.subscription.updated | Handle plan upgrades/downgrades, update access level |
| customer.subscription.deleted | Revoke access, trigger retention flow |
| invoice.payment_succeeded | Log successful recurring payment |
| invoice.payment_failed | Flag for follow-up, notify customer |
Cause: Generated files are stale — ventures.json was edited but generator was not run.
Fix: Run npm run generate, then npm run build again.
Cause: Price ID environment variable is missing or incorrect.
Fix: Check .env.local against .env.example. Run npm run seed-stripe if price IDs have not been created.
Cause: STRIPE_WEBHOOK_SECRET is missing or does not match the endpoint.
Fix: Verify the webhook secret in Vercel environment variables matches the one in Stripe Dashboard.
Cause: NEXT_PUBLIC_STRIPE_PRICE_* env vars are not set in Vercel.
Fix: Add price ID environment variables to Vercel project settings and redeploy.
Cause: Product page already exists — generator only scaffolds new pages, never overwrites.
Fix: This is expected behavior. Edit the existing page manually.
Cause: ventures.json has a schema issue (missing field, wrong type).
Fix: Validate ventures.json fields against the schema documented above.
See the Architecture reference for the full tech stack and file map, or the Site Map for a complete route inventory.