Build a production-style PokeAPI explorer that showcases the major capabilities of a modern Next.js 16 App Router application while still feeling like a real product instead of a demo sandbox.
The app should let users browse, search, filter, compare, and save Pokemon, and it should deliberately exercise core Next.js 16 patterns such as Cache Components, async route APIs, Server Components, Server Actions, Route Handlers, metadata generation, and modal routing.
- feel polished enough to use as a public portfolio-quality reference project
- showcase major Next.js 16 capabilities in one coherent app
- keep the architecture aligned with App Router best practices
- remain fast, indexable, resilient, and accessible
- use the public PokeAPI as the main data source
- authentication
- payments
- admin back office
- custom database infrastructure
- multiplayer or real-time collaboration
- full offline-first support
Users should be able to:
- land on a fast home page with featured Pokemon and curated entry points
- browse a searchable and filterable Pokedex
- open a quick-view modal from the list without leaving context
- open a full Pokemon detail page for deep information
- compare multiple Pokemon side by side
- save favorites and a lightweight team draft
- share pages with rich metadata and generated social preview images
Use PokeAPI for:
- pokemon list and pagination
- pokemon detail
- species detail
- evolution chains
- type data
- abilities
The app may derive normalized view models from PokeAPI responses, but the external source of truth should remain PokeAPI.
- Next.js 16
- React 19
- App Router only
- TypeScript
- Node.js runtime by default
The implementation must showcase these capabilities in meaningful ways:
- App Router file conventions
- async
paramsand asyncsearchParams - Server Components as the default rendering model
- minimal Client Component islands for interactive UI only
- Cache Components enabled via
cacheComponents: true use cachewithcacheLifeandcacheTagfor data and UI cachingupdateTagfor read-your-writes freshness after user mutations- streaming and Suspense boundaries for slow sections
loading.tsx,error.tsx,global-error.tsx, andnot-found.tsx- Route Handlers for backend-for-frontend style endpoints
- Server Actions for user mutations such as favorites and team draft changes
after()for non-blocking logging or analytics side effectsproxy.tsinstead of deprecatedmiddleware.ts- dynamic metadata with
generateMetadata - file-based metadata such as
robots.ts,sitemap.ts, andmanifest.ts - generated Open Graph images with
next/og - parallel routes and intercepting routes for modal detail views
next/imagewithremotePatternsnext/font- typed routes enabled in
next.config.ts
- no
middleware.tsfor primary request interception - no
images.domains; useimages.remotePatterns - no
next/legacy/image - no Pages Router for new feature work
-
/- landing page
- featured Pokemon
- featured types or generations
- prominent entry points into browse and compare flows
-
/pokedex- searchable and filterable Pokemon index
- filter by name, type, generation, and base stat ranges where practical
- quick-view modal support from list results
-
/pokemon/[name]- full Pokemon detail page
- hero section
- stats
- abilities
- type matchups
- species flavor data
- evolution chain
- artwork gallery
-
/compare- compare up to 3 Pokemon
- search-param driven shareable comparison state
-
/favorites- user-specific saved favorites
- cookie-backed or server-action-backed persistence without requiring auth
-
/team-builder- lightweight team drafting experience
- add and remove Pokemon from a six-slot team
- show type coverage summary
Use parallel and intercepting routes so that:
- opening a Pokemon from
/pokedexcan render as a modal quick view - direct navigation to
/pokemon/[name]renders the full page - modal close returns users to the prior browsing context
Use Server Components for:
- home page sections
- Pokedex result rendering
- Pokemon detail data composition
- compare page data composition
- SEO-critical content
Use Client Components only where necessary, for example:
- search input interactions
- filter controls
- modal shell and close behavior
- favorite toggles
- compare selection interactions
- team builder interactions
Enable cacheComponents: true in next.config.ts.
Use Cache Components to create:
- a fast static shell for top-level routes
- cached shared data for popular Pokemon and type metadata
- streamed uncached sections for user-specific or highly variable UI
- cache stable list and detail fetches with
use cache - apply
cacheLifeto avoid needlessly refetching stable PokeAPI data - tag cache entries in a way that supports selective invalidation
- use
updateTagafter favorites or team mutations when freshness is expected
- centralize PokeAPI access through server-side data utilities
- normalize raw responses into UI-friendly models
- avoid client-side waterfalls for primary content
Use Server Actions for:
- add favorite
- remove favorite
- add Pokemon to team
- remove Pokemon from team
- clear team
Persistence may be cookie-based for this version as long as the flow is consistent and demonstrable.
Add Route Handlers where they improve the product, for example:
-
/api/search- typeahead search suggestions
- normalized shape for the client search box
-
/api/team/share- optional share/export endpoint for a drafted team
Route Handlers should behave like backend-for-frontend helpers, not duplicate the whole app data layer.
Add a proxy.ts that handles a small but meaningful request-layer concern.
Acceptable examples:
- redirecting legacy URLs into the new route structure
- assigning an A/B experiment cookie for alternate home page hero content
- enforcing canonical browse entry points for malformed query patterns
Do not use Proxy for slow data fetching or full authorization logic.
Provide strong root metadata in app/layout.tsx.
Use generateMetadata for:
- Pokemon detail pages
- compare pages
Include:
robots.tssitemap.tsmanifest.ts- favicon and app icons
Generate dynamic OG images for Pokemon detail pages using next/og.
The app must include thoughtful UX for:
- initial loading states
- slow route segments
- failed remote fetches
- empty search results
- invalid Pokemon names or IDs
- global rendering failures
Required file conventions should be used where appropriate:
loading.tsxerror.tsxglobal-error.tsxnot-found.tsx
- use
next/imagefor official Pokemon artwork and sprites - configure
images.remotePatternscorrectly for all remote image hosts used - use
next/fontfor the primary type system
- first load should present a meaningful shell quickly
- list and detail routes should avoid unnecessary client-side fetching
- streamed content should improve perceived load time for slower sections
- the app should avoid obvious waterfalls in composed detail pages
- keyboard-accessible modal interactions
- semantic headings and landmarks
- accessible search and filter controls
- image alt text for Pokemon artwork
- contrast-safe UI
- home page
- Pokedex page
- Pokemon detail page
- modal quick-view route
- compare page
- favorites
- team builder
- metadata and OG generation
- route handlers
- proxy
- server actions
- loading, error, and not-found states
- generation-specific entry pages
- type matchup visualizations
- shareable team card
- daily featured Pokemon
The project is complete when:
- all primary routes are functional
- major Next.js 16 features listed above are implemented in meaningful product scenarios
- the app works without relying on deprecated Next.js patterns
- PokeAPI data is composed into a coherent, polished user experience
- the project is strong enough to serve as a public showcase of modern Next.js 16 development