Week 2: Next.js 15, Funnel APIs, and 134 Tests
Week 2 recap — Next.js migration, funnel analysis API, AI feedback widgets, loading skeletons, and our test suite hit 219 tests across the monorepo.
Week 2 was dense. Four days, a major framework migration, a new API surface, and 107 new tests across the monorepo. Here's everything that shipped between April 3–6.
Next.js 14→15 + React 18→19
We ripped the bandaid off. Next.js 15 brings async request APIs, which meant every cookies() and headers() call needed to become await cookies(). Not hard, but tedious — touching almost every server component and middleware file.
The bigger win: this resolved 8 Dependabot vulnerability alerts in one shot. React 19 also landed cleanly. No breaking changes in our component tree, though we did have to update a few useEffect patterns that React 19's stricter StrictMode caught.
Was it worth the effort? Yes. We're now on the latest stable of everything, and we won't accumulate migration debt.
Funnel Analysis API
The headline feature this week. Full CRUD for funnels and goals:
// Create a funnel
POST /api/funnels
{
"name": "Signup Flow",
"projectId": "proj_abc123",
"steps": [
{ "event": "page_view", "path": "/pricing" },
{ "event": "click", "selector": "#signup-btn" },
{ "event": "page_view", "path": "/onboard" }
]
}Each funnel tracks conversion between steps. Goals attach to funnels with target percentages. The API supports filtering by date range and segmenting by any event property.
We built this prompt-first — writing the API spec as a conversation with Claude, then generating the route handlers, validation schemas, and tests from that spec. Took about 2 hours from spec to merged PR. The prompt-first pattern is becoming our default for new API surfaces.
107 New Tests
Testing got serious this week.
SDK: 51→85 tests (+34). New coverage for auto-initialization, Web Vitals collection, transport layer retry logic, and full end-to-end flows. The e2e tests spin up a mock server and verify the SDK sends correct payloads over the wire.
Dashboard: 61→134 tests (+73). Component tests for every major UI piece, library function tests, and middleware auth tests. We're using Vitest with Testing Library. The middleware tests alone caught two auth edge cases we'd missed.
Total across the monorepo: 219 tests. All green, all running in CI.
Loading Skeletons
Every dashboard page now has proper loading states. No more layout shift when data arrives. We built a set of skeleton primitives (SkeletonCard, SkeletonChart, SkeletonTable) and composed them to match each page's layout. Small thing, but it makes the dashboard feel real instead of broken while loading.
AI Feature Feedback Widget
The AI-powered features (health score, error explainer, smart prompt) now have inline 👍👎 feedback buttons. Clicks go to a feedback table in Supabase with the feature name, rating, and optional comment. We need this data to know if the AI features are actually useful or just noise.
Docs Overhaul
Eight new documentation pages:
- Troubleshooting guide
- Custom events reference
- Error tracking setup
- Uptime monitoring
- Privacy & data handling
- Environment variables
- Migration guide (from GA, Plausible, etc.)
- SDK API reference updates
We also shipped Cmd+K search across docs using Fuse.js for fuzzy matching. No external search service, no API keys, works offline. The index builds at compile time from all MDX content.
Error Spike Alerts
New hourly cron job that checks for error spikes per project. The logic: if a project has 5+ errors in the last hour AND that's 3x or more the previous hour's count, we send an email alert.
Two thresholds intentionally. The absolute minimum (5) prevents alerts on low-traffic projects where going from 1→3 errors would technically be a 3x spike. The relative threshold (3x) catches real anomalies without firing on steady-state error rates.
Infrastructure
Persistent rate limiting. Moved from in-memory rate limiting to Supabase-backed. Survives serverless cold starts. Fail-open design — if the rate limit check fails, the request goes through. We'd rather serve a few extra requests than block legitimate users because of a DB hiccup.
CDN deployment. cdn.vibeping.dev is live — a Cloudflare Worker that proxies jsDelivr. This gives us a branded URL for the SDK script tag and lets us add caching headers without depending on jsDelivr's configuration:
<script src="https://cdn.vibeping.dev/sdk/v1/vibeping.js" defer></script>Auto-create uptime checks. When you create a new project with a URL, we now automatically set up an uptime check for it. One less manual step.
Content & SEO
Three new blog posts: custom events guide, Google Analytics comparison, and a privacy/cookies deep-dive. Every page now has structured data (JSON-LD) for better search indexing. OG images generate dynamically per page and per blog post — no more manual image creation.
What's Next
Week 3 focus: funnel visualization. The API is in place. Now we're building the dashboard UI — step-by-step conversion charts, drop-off analysis, and the ability to compare funnels side by side. If you've used Amplitude's funnel view, that's the target. Expect a PR mid-week.