18 Next.js 15 App Router sites covering marketing, SaaS dashboard, operator tools, and public APIs.
HOW WE USE IT
Avo runs 18 separate Next.js 15 applications. They range from the public marketing site and case study pages to a multi-tenant SaaS dashboard, a cold-email operator hub, a booking system, and a PDF proposal generator.
The App Router is used throughout. Server Components handle data fetching directly against ClickHouse and Redis without an intermediate API layer for most read paths. This collapses the latency from the typical three-hop pattern (browser to API route to database) to two hops (browser to server component to database). On the intelligence API and regime detection pages this matters: a cold-cache regime page was 1,048ms under the old pattern; with a server component plus a Redis collection cache it dropped to 79-90ms.
Deployment is via Vercel with pnpm as the package manager. Each site has a GitHub Actions workflow that runs tsc --noEmit and the regression test suite before allowing a Vercel promotion to production. The cicd-pipeline case study covers the exact workflow structure.
Example workflow: building a new data page for a client's SaaS dashboard. 1. Create app/dashboard/positions/page.tsx as an async Server Component. 2. Fetch position data directly from ClickHouse inside the component using the typed query function. No API route needed for this read path. 3. Wrap the data table in a Suspense boundary so other page sections render while the query runs. 4. For real-time row updates, extract the table into a Client Component using SWR polling against a dedicated /api/positions route at a 10-second interval. 5. Add export const revalidate = 0 to force dynamic rendering. The page will never be cached at the CDN edge. 6. Gate behind Clerk's auth() check at the top of the Server Component. Any unauthenticated request redirects before the database query fires.
The breaking change reality: Next.js 15 introduced params as a Promise on async server components. Every route that previously destructured params directly required updating. The codemod handled the mechanical part but missed a handful of client components that passed params down as props. Those needed manual fixes. AGENTS.md in the repo documents this specifically because it is the most common source of cryptic TypeScript errors on upgrade.
ISR (incremental static regeneration) runs on the case study pages with a 3,600-second revalidation window. This keeps public pages fast without a full rebuild on every content change. The sitemap route uses revalidate: 3600 for the same reason. Pages that need real-time data (screener, intelligence feed, regime dashboard) are dynamic and opt out of caching entirely.
Production numbers
18
Next.js sites
All sites
App Router
3,600s
ISR revalidation
79ms
Regime page (cold cache)
We discovered 209,033 regime keys with no TTL and fixed them in a single SCAN pass, then cut the regime endpoint latency 13x by eliminating per-request key scans.
209,033 Keys without TTL (found)
Read case study →
InfrastructureWe built a 63-line Node.js proxy that gives Vercel serverless functions read-only access to a private ClickHouse instance with zero database exposure.
12ms Proxy overhead (end-to-end)
Read case study →
InfrastructureWe automated Avo site deployments with a GitHub Actions CI/CD pipeline that catches TypeScript errors in 35 seconds and deploys to Vercel production in 90 seconds.
90 sec Frontend deploy time (was 40-60 min)
Read case study →
AI / Machine LearningWe built a serverless PDF generator using @sparticuz/chromium and Puppeteer that fits in Vercel's 50MB function limit and generates 4-page proposals in 5.8 seconds at $0.004 per document.
5.8 sec p50 generation time
Read case study →
PlatformsWe launched a multi-tenant market intelligence SaaS serving computed signals from 425M rows, with all API routes under 500ms cold and unit economics positive from customer one.
425M+ ClickHouse rows at launch
Read case study →
PlatformsWe built a retail investor dashboard serving live fund performance from a paper trading account, with compliance banners enforced as server-side dependencies and JavaScript bundle under 120KB.
7 Pages built and deployed
Read case study →
Start a project
Most projects ship in under two weeks. Start with a free 30-minute discovery call.
Start a project →