Skip to content

About

A Gmail-style demo exploring Cache Components, Partial Prefetching, and the navigation() API with Next.js 16.4, React 19, Tailwind CSS v4, and Prisma.

Topics

Resources

Stars

17 stars

Watchers

0 watching

Forks

Latest commit

 

History

79 Commits

Folders and files

Repository files navigation

Stamp

Next 16 Mail "Stamp"

A Gmail-style mail client that demonstrates Instant Navigations in Next.js 16.5, including the navigation() API.

Live demo →


The architecture follows the Next.js App Architecture skill and the Component Architecture for React Server Components blog post.

Features

  • Cache Components cache each query with 'use cache', name the data with cacheTag, and set its lifetime with cacheLife. The signed-in account is read with 'use cache: private' and passed into each cached query.
  • Partial Prefetching prefetches one shared App Shell per route. Mailbox links, pager links, and the thread rows in view use prefetch={true}, which also resolves each thread's header. Database-backed label routes prefetch on hover.
  • navigation() is awaited in the message components before they query, which keeps message bodies out of every prefetch while their cached results still serve later visits.
  • Server Functions star, archive, mark read, reply, compose, and undo a send on the server, and invalidate only the tags they change with updateTag. New text is screened through the Vercel AI Gateway.
  • React Compiler memoizes components and hooks automatically, so the code needs no manual useMemo or useCallback.
  • View Transitions animate content as it streams in from Suspense.
  • Async React keeps the UI interactive during server work with Suspense, useOptimistic, useTransition, and use.

How the data loads

Each read is cached and arrives at a different stage of a navigation.

Read How it is cached When it arrives
Mailbox links and unread counts 'use cache' per account In the App Shell
One page of a mailbox 'use cache' per account, mailbox, and page With a mailbox or pager link's prefetch
Subject, sender, labels, and toolbar 'use cache' per thread and account With a row's prefetch
The latest message and the reply form 'use cache' per thread, after navigation() On the navigation
Earlier messages in the thread 'use cache' per thread, after navigation() On the navigation, below the latest one

Opening a thread shows its header first. The latest message and the reply form appear together, and earlier messages stream in below them.

Getting started

Stamp runs on SQLite locally and Postgres in production, on a Next.js 16.5 canary. Copy .env.example to .env.local, then:

pnpm install
pnpm run prisma.push
pnpm run prisma.seed
pnpm run dev

Open http://localhost:3000 in your browser. You can browse the data with pnpm run prisma.studio, or wipe and re-seed the database with pnpm run prisma.reset. Restart next dev after re-seeding, since cached reads outlive the rows they came from.

The seed gives one fictional person a work mailbox and a personal mailbox. Switch between them from the sidebar, and write from one to the other. Use the toolbar in the top right to turn Prefetch off and compare, or turn Delays on to watch the header arrive before the newest message, and the newest message before the history. Set VERCEL_AI_GATEWAY_TOKEN to screen replies and new messages for spam and profanity.

Deploying with Postgres

The driver follows DATABASE_URL. A file: URL uses SQLite through @prisma/adapter-better-sqlite3, and a postgresql:// URL uses Postgres through @prisma/adapter-pg. prisma.config.ts swaps the schema provider to match, so prisma generate, db push and db seed work against either. Point DATABASE_URL at your Postgres database and run the same three commands to seed production data.

Testing

The end-to-end tests use @next/playwright with the instant() API to assert that a row's thread header is available before the click and that the message bodies only render after it. They run in CI against Postgres; locally they run against a separate SQLite database.

pnpm test:e2e

Static checks:

pnpm lint
pnpm typecheck

Stack

  • Next.js 16.5 canary: App Router, Cache Components, Partial Prefetching, navigation(), Server Functions
  • React 19.3 with React Compiler: Suspense, View Transitions, useOptimistic
  • TypeScript and Tailwind CSS v4
  • Prisma 7 on SQLite locally and PostgreSQL in production
  • Ariakit for the account menu, the recipient combobox, and the mobile navigation drawer
  • Playwright with @next/playwright for end-to-end tests

License

MIT

About

A Gmail-style demo exploring Cache Components, Partial Prefetching, and the navigation() API with Next.js 16.4, React 19, Tailwind CSS v4, and Prisma.

Topics

Resources

Stars

17 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages