Next.js / React
A complete guide to using Invokix with a Next.js or React project. From pulling your first types to wiring up React Query hooks and validating with Zod — everything in one place.
What Invokix generates for this stack
- TypeScript types for every schema in your contract
- React Query v5 hooks for every endpoint
- Zod validation schemas matching your contract exactly
Setup
1
Install dependencies
Terminal
pnpm add @tanstack/react-query zod2
Set up QueryClientProvider
Wrap your app in a QueryClientProvider. In Next.js App Router, create a client component for this:
components/Providers.tsx
"use client"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { useState } from "react"
export function Providers({ children }: { children: React.ReactNode }) {
const [queryClient] = useState(() => new QueryClient())
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
)
}app/layout.tsx
import { Providers } from "@/components/Providers"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}3
Pull your contract outputs
Run the CLI to pull types, hooks, and schemas into your project:
Terminal
npx invokix pullThis creates three files in your src/ directory:
Generated files
src/types/orders.ts — TypeScript types
src/hooks/useOrders.ts — React Query v5 hooks
src/schemas/orders.ts — Zod validation schemas4
Use the generated hooks in your components
app/orders/page.tsx
import { useGetOrders } from "@/hooks/useOrders"
export default function OrdersPage() {
const { data: orders, isLoading } = useGetOrders()
if (isLoading) return <p>Loading...</p>
return (
<ul>
{orders?.map((order) => (
<li key={order.id}>{order.status} — {order.price}</li>
))}
</ul>
)
}5
Validate API routes with Zod schemas
Use the generated schemas to validate request bodies in your API routes:
app/api/orders/route.ts
import { NextRequest, NextResponse } from "next/server"
import { CreateOrderBodySchema } from "@/schemas/orders"
export async function POST(req: NextRequest) {
const body = await req.json()
const parsed = CreateOrderBodySchema.safeParse(body)
if (!parsed.success) {
return NextResponse.json(
{ error: "Invalid body", issues: parsed.error.issues },
{ status: 400 }
)
}
// parsed.data is fully typed
const { price, lineItems } = parsed.data
// ... create the order
}Keeping outputs in sync
Add the CLI to your CI pipeline so types are always up to date:
.github/workflows/ci.yml
- name: Pull latest contract outputs
run: npx invokix pull
env:
INVOKIX_API_KEY: INVOKIX_API_KEY
- name: Type check
run: pnpm tsc --noEmit