await straight inside a component, which
means an entire layer of API plumbing — the /api/products route, the
fetch('/api/products') call, the JSON marshalling — can disappear. Your
component asks Esix for what it needs, and that’s it.
Esix features used: all, find. Next.js features used: async server
components, dynamic route segments, and notFound().
Note: Esix talks to MongoDB and must run on the server. The patterns
below all live in server components (no 'use client' directive). If you
need to surface data inside a client component, fetch it in a server parent
and pass it as a prop.
What You’ll Build
Project Setup
Inside a Next.js App Router project:DB_URL and DB_DATABASE in
.env.local. Esix picks them up automatically the first time it opens a
collection.
The Product Model
A Server Component can import the model directly — there’s no separate “API layer” to keep in sync:The List Page
A server component is just anasync function — await the query and render
the result:
useEffect, no loading state, no fetch. The HTML for the list is
generated on the server with data already inlined.
The Detail Page
Dynamic route segments arrive as theparams prop. When find returns
null, hand off to Next.js’s built-in notFound() helper — it renders the
nearest not-found.tsx and sets a 404 status:
find accepts ObjectId hex strings and plain string ids, and it never
throws on bad input — perfect for trusting whatever Next.js routes hand you.
Generating Static Pages at Build Time
If your catalog doesn’t change often, you can pre-render every product page withgenerateStaticParams. Esix queries run during the build just like any
other server code:
pluck returns a flat array of values for a single field — exactly the shape
generateStaticParams wants.
Caching and Revalidation
Server components inherit Next.js’s caching model. The two most common patterns:revalidate for a catalog page, force-dynamic for anything personalised
(carts, dashboards).
Pattern Notes
- No API tier needed. A Server Component calling Esix replaces the
/api/products → fetch → componenttriangle with a single function. - Pass models down, not into client components directly. Class instances with methods don’t serialise. If you need to hand data to a client child, spread the fields you actually use into a plain object first.
notFound()is the right escape hatch. It plays nicely with<Link>prefetching and gives you the correct status code for free.
What’s Next
- Mutations with Server Actions — the matching pattern for writes.
- Filter and Paginate — drive this list page from URL search params.
- Retrieving Models — full reference for the query methods used here.