r/nextjs • u/NNYMgraphics • 4h ago
r/nextjs • u/AutoModerator • 5d ago
Weekly Showoff Thread! Share what you've created with Next.js or for the community in this thread only!
Whether you've completed a small side project, launched a major application or built something else for the community. Share it here with us.
r/nextjs • u/ShamAhmad2022 • 5h ago
Help Per-tenant feature toggles in Next.js (App Router), one deployment, no redeploy. How would you architect this?
We're building a multi-tenant B2B app on Next.js (App Router + Turbopack). We need to split it into a core + optional features, where each feature can be turned on/off per tenant from an admin panel via API (no redeploy) and tenants ideally shouldn't download code for features they don't have.
Hard constraint: it has to stay one deployment on DigitalOcean App Platform (one build, one container). No multi-app / droplet fleet.
What we've ruled out so far:
- Module Federation — effectively dead under App Router + Turbopack.
- Vercel Microfrontends / Remote Components — need multiple deployments + Vercel's platform, and don't actually solve per-tenant gating anyway (they split by team/route, not by tenant entitlement).
So we're leaning toward keeping it in-app:
- next/dynamic for code-splitting each feature into its own chunk
- a static plugin registry + slot/fill pattern so core never imports a feature directly
- server-side route denial (real 404) for tenants that don't own a feature
- reusing our existing tenant-config flags + policy guards for the runtime gating
Roughly 8–12 features would become "plugins," the rest stays core.
Questions for anyone who's done this:
Did you keep per-tenant feature toggling in a single app, or did you actually split deployments? Any regrets?
Any gotchas with dynamic Redux reducer injection / lazy slices per feature?
Is the "code-split but still in the build" reality good enough, or did stakeholders push for true isolation?
Better patterns I'm missing?
Appreciate any war stories. Thanks!
r/nextjs • u/MysteriousPie7083 • 5h ago
News I built an AI copywriting SaaS boilerplate with Next.js and Tailwind CSS (Sanad AI)
🚀 Just launched Sanad AI!
A Next.js boilerplate to launch your AI copywriting SaaS in minutes.
✨ Features: • AI Sandbox • Bilingual tools • Responsive design
🌐 Live:https://sanad-ai1.vercel.app📦 Get Code:https://mohamedhorizon2.gumroad.com/l/sanad-ai
#BuildInPublic #Nextjs
r/nextjs • u/Coursings • 6h ago
Discussion Built a free secure note sharing service
Cryptinotes is a fully encrypted, self-destructing note-sharing application inspired by Privnote - a legacy tool for sending sensitive text that disappears after being read. Cryptinotes takes that same core idea and modernizes it: markdown formatting, encrypted file attachments, and granular controls over exactly how and when a note destroys itself.
Every note is encrypted client-side before it ever touches the server, and only decrypted client-side once the recipient opens the link. The server never has access to plaintext content - not the note body, not attachments, not even the note's contents at rest in the database.
Every note can be tuned to the sensitivity of what's being shared:
- Markdown support — format notes with headers, lists, code blocks, and other rich text instead of plain strings
- File attachments — attach one or more files, encrypted alongside the note body
- Read limits — configure how many times a note can be opened before it self-destructs
- Expiration windows — set a custom self-destruct timer independent of the read count
- Password protection — require a password (on top of the link's own key) before a note can be decrypted
Cryptinotes runs on Railway across three services:
- Application server — the Next.js app handling note creation, retrieval, and the client-side encryption flow
- Postgres database — stores encrypted note metadata and ciphertext
- Cron worker — handles scheduled cleanup independently of the main app
The cron worker enforces two cleanup rules. Attachments are deleted shortly after a note is opened rather than instantly, giving the recipient a window to actually download files before they're purged. Separately, any note that goes unopened for 30 days is automatically destroyed, regardless of its configured read limit or expiration settings.
File storage runs on Cloudflare R2 (S3-compatible), holding only encrypted attachment blobs that are meaningless without the client-side key.
r/nextjs • u/Ordinary_Bench_3796 • 8h ago
Question Built an in-browser web app for mundane tasks, is this even useabale?
I have been building this project for some time for myself. It is for mundane tasks, not an IDE and there are no extensions to install.
The tools included are a mock data factory, code analysis, code converter, code refactor, code generator, css framework converter, sql builder, regex generator, and a json formatter, self explamatory if you think about it. Specialized tools in there wn domain
The app uses firebase anonymous auth for some features that use redis for device sync and work with databses. The anonymous auth is also used for saving work to the firestore only if the you wants to. All the preferences are saved to localstorage and work drafts are saved to indexDB on the user's devices. I use free AI models from the Vercel AI Gateway and the Groq API, but i consider adding better models later.
Of course, for vibe coders this tool is useless. But for people who still code manually and would like to do things faster, it serves a purpose. Would you even consider using it?
r/nextjs • u/Admirable_Scholar561 • 14h ago
Discussion Recent eCommerce website I'm building for a grill business in Lagos.
Here's a preview of the desktop experience.
My goal wasn't to create another generic restaurant website—I wanted it to feel like a premium ordering app with an Apple-inspired aesthetic: clean, modern, fast, and designed to make ordering effortless.
I'd love to hear your thoughts. What would you improve?
r/nextjs • u/st11x-molm • 1d ago
Help Consistent Runtime Error with Cache Components
Hi,
I'm migrating a Next.js 16 app from ISR to Cache Components, and I'm consistently running into this runtime error during development.
The pattern is always the same:
- Everything works after starting the dev server.
- After editing a page/template (or sometimes after CMS content changes), I start getting this runtime error.
- The only way to recover is to restart the dev server.
- Then it works again until the next change.
I'm using:
- Next.js 16
- Payload CMS 3.86
- React 19
Has anyone run into something similar or have suggestions for where to investigate next?
A snippet of the error is given here.
Thanks
Matt
Module [project]/node_modules/.pnpm/@[email protected]_@[email protected][email protected][email protected]_next@1_3a6ac242312cb58507def477da89ede8/node_modules/@payloadcms/next/dist/exports/client.js [app-rsc] (client reference proxy) was instantiated because it was required from module
....
...
MODULE_9 => "[project]/src/app/(frontend)/[locale]/blogs/[slug]/page.tsx [app-rsc] (ecmascript, Next.js Server Component)" } [app-rsc] (ecmascript) <locals>, but the module factory is not available.
This is often caused by a stale browser cache, misconfigured Cache-Control headers, or a service worker serving outdated responses.
To fix this, make sure your Cache-Control headers allow revalidation of chunks and review your service worker configuration. As an immediate workaround, try hard-reloading the page, clearing the browser cache, or unregistering any service workers.
r/nextjs • u/Commercial-Essay5756 • 1d ago
Discussion how do you keep a next.js storefront up during a flash drop?
Building the storefront for a streetwear sub-brand inside a bigger fashion group, with Next.js on the front (App Router) and a headless commerce backend behind it.
The traffic shape is what's wrecking my rendering plan, since we run 4 to 6 drops a year and each one spikes to around 40k concurrent the second it opens before selling out in about 15 minutes.
Normal days are quiet, so the whole build is designed around a handful of 15-minute windows.
The Next.js side is eating most of my time, starting with the product pages, which are ISR while inventory moves every second during a drop.
On-demand revalidation at that write rate either serves stale stock or melts the backend, which is pushing me toward keeping the page static and pulling the live stock number client-side.
From there it's the edge-middleware waiting room so we don't dump 40k people into checkout at once, then checkout itself, where cart and inventory have to stay consistent while the API throttles and the frontend still has to fail softly.
That last part is what's pulling the backend decision into it, and it's down to SCAYLE or commercetools for the composable route.
With commercetools we'd wire more of it together ourselves, whereas SCAYLE comes more assembled out of the box, and either way a custom SNKRS-style build is out because we don't have the headcount.
So if you've run a Next.js front over a headless backend through a real drop, I want to know what broke first and whether the fix landed on the frontend or the backend.
r/nextjs • u/nicsoftware • 2d ago
Help My GitHub rate-limit cache turned out to already be my ranked list
Had a GitHub API rate limit problem in a Next.js app and nearly built two systems to fix it: a cache for hot reads, and a separate materialised table for a ranked list. Turned out I only needed one.
GitHub's REST API gives you 60 requests/hour unauthenticated, which is nothing once more than a couple of people hit the app in the same hour. Moving to the GraphQL API with a server-side personal access token bumps that to 5,000/hour, and you only pay for the fields you actually ask for instead of chasing pagination across several REST endpoints.
The part that actually helped: every computed result gets upserted into one Postgres table (Supabase) with a 12 hour TTL column. A route handler checks that column first; if it's fresh, GitHub never gets touched. That same table is already sorted and indexed by score, so the ranked list is just SELECT ... ORDER BY score DESC over the same rows. No second pipeline, no sync job, no "is the ranking stale" bug class to think about.
What I didn't expect: my analytics event for a page view fired on both fresh and cached reads. Early on that made a slow feature look popular, ten people hitting a cached page counted the same as ten fresh computations. Had to split the event into fetched vs served-from-cache before the numbers meant anything.
Doesn't generalise to everything, if your writes are heavier than your reads this falls apart fast. But for anything read-heavy where the ranked view and the single-item view can share rows, it's one less thing to keep in sync.
r/nextjs • u/Bejitarian • 2d ago
News Next.js Weekly #136: What Actually Triggers Suspense in React?
r/nextjs • u/Admirable_Scholar561 • 2d ago
Discussion Marketing Agency dashboard design using Nextjs 15
Built AgencyFlow over the weekend.
A frontend-only SaaS prototype with:
• Animated dashboard
• Kanban CRM
• ⌘K command palette
• Realistic demo data
No backend yet but it feels like a funded startup product.
Thoughts?
Discussion Why did we lose the ability to have loading.tsx per route group?
Today while I was spending time on a side project, I noticed something. When navigating with Link, a page was not using the loading.tsx that is placed under its route group.
src/app/[locale]/(base)/loading.tsx
First I was suspicious of cacheComponents and I started testing it with versions between 13-16 (with and without cacheComponents)
Then I found out that it is not about cacheComponents. It was just a silent behavior change between v13 and v14
it works like this
src/app/[locale]/(base)/products/loading.tsx
src/app/[locale]/(base)/purchases/loading.tsx
but not like this
src/app/[locale]/(base)/loading.tsx
and I asked an AI to search through the git repo to see if this is a known bug. It could only find this issue
https://github.com/vercel/next.js/issues/69625
a Next.js core team member claims this is "intentional" but I consider it as a bug. Why do we need to create multiple loading.tsx files if we are not going to make skeletons?
And it is never mentioned anywhere
https://nextjs.org/docs/app/api-reference/file-conventions/route-groups
https://nextjs.org/docs/app/api-reference/file-conventions/loading
https://nextjs.org/blog/next-14
r/nextjs • u/Appropriate-Doubt801 • 3d ago
Discussion If you had to rebuild your image pipeline today, what would you do differently?
I'm self-hosting a Next.js app and I'm trying to figure out the image side before I regret my decisions later.
Right now it feels like every option has a catch.
- Keep using
next/image - Cloudinary
- ImageKit
- Bunny
- Cloudflare Images
- Roll your own with Sharp/imgproxy
If you've been running one of these for a while, what ended up annoying you the most?
Doesn't have to be a deal breaker. Just one of those things where you went "I didn't think this would become a problem."
r/nextjs • u/Charminth • 3d ago
Help [Need Guidence] How to launch a Web App that I created for myself to the public. Asking in context of both coding and real products
I am currently in the process of redesigning my application, Writely. During the update, I encountered a few bugs that I am currently resolving, and I plan to launch the app in the coming days.
I would greatly appreciate your guidance on the following questions:
- Deployment: What are the necessary steps to successfully launch and host the application?
- Monetization: Should I consider integrating a method for generating income in the future?
- Viability: Do you believe this app concept has the potential to succeed?
- Will this work as a side hustle.
For context, I originally built this project to support my personal hobby of writing novels and stories. Currently, I am a university student living in a hostel with zero budget and struggling to find employment. While my primary motivation for this project is not purely financial, I hope that launching this app might eventually provide some financial support.
r/nextjs • u/gaggarwal124 • 3d ago
Discussion I built a complete AI SaaS Admin Dashboard with Next.js 15 + TypeScript - sharing what I learned
Hey r/nextjs,
Spent the last few months building a full AI SaaS admin dashboard. Wanted to share what I learned about the stack choices.
Tech stack I went with:
- Next.js 15 (App Router)
- TypeScript
- Tailwind CSS v4
- Shadcn UI + Radix primitives
- Framer Motion for animations
- Recharts for data viz
Key decisions I made:
App Router over Pages Router — nested layouts made sidebar/topbar much cleaner
Shadcn over MUI — copy-paste model is way better for customization, no bundle bloat
Tailwind v4 — CSS-first config is a game changer but had some issues with oklch color format in scrollbars
Pages I built: AI Chat with markdown + code blocks, Image Generation, Analytics (MRR/ARR/Churn), User Management, Billing, Support Tickets, Settings, Auth pages, Error pages, Landing page.
Happy to answer any questions about the architecture or stack choices!
r/nextjs • u/AbdulRafay99 • 4d ago
Discussion I got tired of pasting .env files into Slack and forgetting which one was current, so I built an open-source secrets manager
Built Envpilot — open-source (MIT) secrets manager, because my team kept pasting .env files into Slack and forgetting which one was current. envpilot run -- npm run dev injects variables at runtime, no .env on disk; VS Code extension and an MCP server so AI agents get scoped audited access instead of keys in prompts. Stack: Next.js 15 monorepo, Turborepo + Bun, Convex realtime backend, WorkOS auth/vault, Tailwind v4, React Compiler. Happy to answer stack questions. Repo: https://github.com/rafay99-epic/envpilot.dev
r/nextjs • u/codee_redd • 4d ago
News introduction to openship
An open-source application platform for building, deploying, operating, and scaling applications on infrastructure you own.
Replace deployment tools, managed services, and infrastructure workflows with one open-source platform.
Available today:
- Mail Server (Built in. One click).
• Runs on your own VPS
• Unlimited domains
• Unlimited mailboxes
• Modern webmail included
• Connect with Gmail, Outlook, Apple Mail, Thunderbird, or any IMAP/SMTP client
• Send email directly from your applications using SMTP
• No mailbox subscriptions or API fees
• High email deliverability
- Deployment:
• Deploy any stack
• Git-based deployments
• Zero-downtime deployments
• One-click rollbacks
• Development, Staging, and Production environments
• Multi-branch deployments with isolated environments • Deploy to VPSs, dedicated servers, cloud VMs, or your homelab
- Services:
Provision the services your applications need in one click.
Replace multiple managed providers with services running on your own infrastructure.
• Supabase
• PostgreSQL
• MySQL
• MariaDB
• MongoDB
• Redis
• MinIO
• Meilisearch
• Qdrant
• RabbitMQ
• Kafka
• ClickHouse
• Elasticsearch
...and deploy any other service alongside your applications.
- Operate:
• Live deployment logs
• Live request logs
• Real-time traffic analytics
• Automated backups
• Monitoring
• Secrets management
• Domains
• Automatic SSL
• Environment variables
• Scheduled jobs
• Health checks
-Multi Environments:
• Separate Development, Staging, and Production environments
• Deploy every branch independently
• Test changes before production
• Isolated services, secrets, and configuration per environment
- Security & Teams:
• Team management
• Role-based access control
• IP allow/block rules
• Rate limiting
• Security rules
- Developer Experience:
• Web dashboard
• Native desktop application
• CLI
• REST API
• MCP support for AI agents, just add the mcp and your agent can do the work for you
• Manage your infrastructure without living in SSH
- Coming Soon:
• Multi-server clustering for applications and databases
• One-click load balancing
• Horizontal scaling across multiple servers
• Built-in high availability and failover
• Scale from a single VPS to a cluster with the same workflow
• Just add servers. OpenShip handles the rest.
Open source.
OpenShip is built by the community, for the community. We welcome contributions of all kinds - code, bug reports, feature requests, documentation improvements, and feedback.
r/nextjs • u/menoo_027 • 4d ago
Discussion Building an expense tracker—looking for real-world feature ideas
Hey everyone,
I'm pretty obsessive when it comes to tracking my money. I like knowing exactly what comes in and what goes out every month instead of trying to figure it all out at the end of a quarter.
While organizing my own finances, I realized I couldn't find an expense tracker that matched how my household actually manages money. So I started building my own tool—not to replace existing apps, but because I wanted something that fit my workflow.
That got me wondering how other people handle these situations:
- What's one thing your current expense tracker doesn't do well?
- How do you keep track of expenses that you don't pay immediately (e.g., milkman, newspaper, laundry, or other local vendors)?
- Do you separate savings from your day-to-day spending?
- Is there a workflow or feature you've always wished existed but haven't found in any app?
r/nextjs • u/PalpitationLow2966 • 4d ago
Help Next.js App Router: searchParams navigation not updating URL/UI in production build (works fine in dev)
r/nextjs • u/PalpitationLow2966 • 4d ago
Help Next.js App Router: searchParams navigation not updating URL/UI in production build (works fine in dev)
## Next.js App Router: searchParams navigation not updating URL/UI in production build (works fine in dev)
**Environment:**
- Next.js: 15.5.4
- React: 19.1.0
- Build tool: Turbopack (`next build --turbopack`) — issue persists after switching to default Webpack build too
- OS: Windows
- Node: (add your version)
### Problem
I have a dynamic shop page at `app/[shop]/page.js` (`export const dynamic = "force-dynamic"`). It reads `category`, `sort`, `search`, and `shopPage` from `searchParams` and fetches product data server-side on every request.
Filter links are plain `next/link` components that only change the query string on the
**same route**
, e.g.:
```jsx
<Link href={`${pathname}?category=${cat.slug}`}>...</Link>
```
**Symptom:**
- Clicking a category filter (e.g. `?category=phone`) triggers a network request — I can see the RSC fetch (`?_rsc=...`) in the Network tab, and the response contains the correct fresh data.
- However, the
**browser URL bar does not update**
, and the
**UI does not update**
either.
- This only happens in the
**production build**
(`next build && next start`). In `next dev`, everything works perfectly.
- It happens across all desktop browsers (Chrome, Firefox, Edge) — ruled out extensions/cache/service workers (tested in Incognito, cleared site data, unregistered service workers — no change).
- Oddly, navigating to a
**different pathname**
under the same dynamic segment (e.g. `[shop]/cart`, `[shop]/checkout`) works perfectly — URL and UI update as expected. Only changing
**searchParams while staying on the same pathname**
(`[shop]?category=phone` → `[shop]?category=offer`, or `?sort=...`) is broken.
- Selecting a category that returns
**zero products**
works fine — the URL updates. It's specifically categories/filters that return non-empty product data that get "stuck."
### What I've ruled out
1.
**Component-level state bugs**
— stripped `ShopProductCard` down to a bare `<Link>{item.name}</Link>` with `memo()`; issue persisted.
2.
**Client Router Cache**
— added `experimental.staleTimes: { dynamic: 0, static: 0 }` in `next.config.js`; no change.
3.
**Browser cache / service worker**
— tested in Incognito across 3 browsers; same result on all.
4.
**Mobile vs desktop**
— issue does NOT reproduce on mobile (tested over LAN IP, so no service worker registered there — desktop uses `localhost` which is a secure context).
5.
**A real webpack-only syntax error**
was found and fixed (`return` outside a function in a `"use client"` file that Turbopack silently tolerated but Webpack correctly rejected at build time):
```js
if (typeof window === "undefined") return; // invalid top-level return
```
Fixed to wrap logic inside `if (typeof window !== "undefined") { ... }`. This resolved a separate `Cannot read properties of undefined (reading 'useNotification')` SSR error, but the searchParams navigation issue
**persists even after this fix and after building without `--turbopack`**
.
6.
**Middleware**
— confirmed via `matcher` config that middleware does not run on the `[shop]` route at all.
### Relevant code
`app/[shop]/page.js` (server component):
```js
export const dynamic = "force-dynamic";
export default async function ShopPage({ params, searchParams }) {
const resolvedParams = await searchParams;
const { shop } = await params;
const category = resolvedParams.category || "";
const sort = resolvedParams.sort || "";
// ...fetch with cache: "no-store"
}
```
Filter component (`"use client"`):
```jsx
const searchParams = useSearchParams();
const pathname = usePathname();
const selectedCategory = searchParams.get("category") || "All";
<Link href={`${pathname}?category=${cat.slug}`}>...</Link>
```
### Question
What could cause
**searchParams-only navigation**
(same pathname) to silently fail to commit (no URL update, no UI update)
**only in production builds**
, while full pathname changes work fine and dev mode works fine? Is this a known Next.js 15.5.x issue with soft navigation / RSC streaming for searchParams-only transitions? Any pointers on how to further isolate (e.g. instrumenting the router, checking for a swallowed error during the RSC apply phase) would be appreciated.
Title: searchParams navigation stuck (no URL/UI update) ONLY in production build, works fine in dev — Next.js 15.5.4
Been debugging this for hours, hoping someone here has hit the same thing.
Setup: app/[shop]/page.js, a dynamic server component with export const dynamic = "force-dynamic". It reads category/sort/search from searchParams and fetches data server-side (cache: "no-store"). Filter buttons are plain next/link:
jsx
<Link href={`${pathname}?category=${cat.slug}`}>...</Link>
The bug: Click a category filter → Network tab shows the RSC request firing and returning correct fresh data → but the URL bar never updates and the UI never updates. It just sits there.
Weird details:
- Only happens in production (next build && next start). next dev works perfectly every time.
- Happens on every desktop browser, ruled out cache/extensions/service workers (tested Incognito, cleared storage, unregistered SW — no dice). Doesn't happen on mobile, but that's likely just because mobile was tested over LAN IP (no secure context = no service worker anyway), so not fully conclusive.
- Navigating to a different route under the same dynamic segment ([shop]/cart, [shop]/checkout) works completely fine, URL updates instantly.
- It's specifically same-pathname, searchParams-only navigation that gets stuck.
- Categories that return 0 products navigate fine. Categories with actual product data get stuck. That threw me off for a while — spent ages checking a product card component before ruling it out entirely (stripped it down to a bare <Link>{item.name}</Link> with memo(), bug still happened).
Things I've already ruled out:
- experimental.staleTimes: { dynamic: 0, static: 0 } in next.config — no change
- Product card component — stripped to nothing, still broken
- Middleware — confirmed via matcher config it doesn't even run on this route
- Found and fixed an actual bug (top-level return in a "use client" file that Turbopack was silently swallowing but Webpack correctly errored on) — fixed it, and also dropped --turbopack from the build script entirely. Neither fixed the searchParams issue.
Anyone seen soft navigation silently fail to commit like this in prod builds specifically for searchParams-only transitions? Trying to figure out how to even get visibility into where it's failing since there's no thrown error in console or terminal at this point.
Next 15.5.4 / React 19.1.0, Windows, App Router.
r/nextjs • u/xlameiro • 4d ago
Discussion There are three open memory leaks in Next.js (15.5-16.3) right now - here's how to tell which one you're hitting
The "my self-hosted Next.js server grows until OOM" reports currently map to three distinct open issues:
Router LRU cache doesn't count its keys (#94890) - the size function counts the value strings but never the URL key, so the cache can retain ~1M keys. Signature: slow drift over days that tracks unique URLs served (bot crawls, long slugs), not request volume; heap-snapshot retainer traces end at
LRUNode.RSC render tree retained on client aborts (#94919) - streams that don't finish normally pin the whole element tree via the Flight request's AbortController. Much worse on Node 22/24 than 20; the reporter measured ~2 MB per request on heavy pages.
Middleware setTimeout ids retained by the sandbox (#95094) - the sandbox TimeoutsManager only releases an id on explicit clearTimeout. Workaround that works today: call
clearTimeout(id)inside the callback.
Also learned the hard way that on serverless you don't get the OOM - you get 504s instead. My blog's tag pages were timing out because of an O(N2) loader; instance recycling had been hiding the waste.
I wrote up the full diagnosis flow (which retainer maps to which issue, a growth-shape table, and my 504 postmortem with numbers): https://xabierlameiro.com/blog/nextjs/nextjs-memory-leak-in-production
If you think you're hitting #94890: chart your heap against distinct URLs, not requests per second - fastest way to confirm.
UPDATE (Jul 21): the blog post above now includes a "How I measured this" section - the exact per-route measurement flow (fresh process, forced GC before every sample, verdict from the shape of the curve) I used to independently confirm #95094 and #94890, plus why #94919 would not reproduce on a minimal standalone repro (TTFB ~5 ms: no stream left to abandon - measure your heaviest real pages instead).
r/nextjs • u/Sad-Hawk372 • 5d ago
Discussion Server/Client Boundaries Are an Architectural constraint in nextjs
One of the biggest architectural changes introduced by the app Router is that the server component boundary is no longer just a rendering choice. It is an application design decision.
many twams treat *use client* as a local requirement: add it wherever interactivity is needed. In practice, this often creates unnecessary client-side dependencies and gradually shifts application logic away from the server.
The goal is not to eliminate client xomponents. they are essential. the goal is to keep the client boundary intentional and minimal.
A component should become clien-side because it requires a browser runtime, not because it belongs to an interactive feature.
This distinction becomes increasingly important as applications grow. Poorly defined boundaries lead to duplicated state, unnecessary apI layers, larger bundles, and more complicated data flow.
The most effective app router applications are not the ones with the fewest client components. They are the ones where every client component has a clear reason to exist.
r/nextjs • u/techpotions • 5d ago
Discussion llms.txt in Next.js: a 100-line App Router route handler (force-static + hourly ISR)
llms.txt is the emerging convention for giving AI answer engines (ChatGPT, Perplexity, etc.) a curated markdown map of your site: llmstxt.org
We implemented ours as an App Router route handler instead of a static file so it regenerates from the same data sources the pages render from (static config + CMS query for published content) - it can't go stale. The decisions that mattered:
- force-static + revalidate 3600: it's a crawler-only route, hourly ISR keeps the CMS off the hot path (same strategy as sitemap.ts)
- fail open: the CMS query is wrapped in try/catch, so a dead DB at build time still emits the static sections instead of a 500
- one-line descriptions truncated to ~160 chars per link - curation beats dumping your sitemap
Live example: https://techpotions.com/llms.txt
Full writeup with the route code: https://dev.to/techpotions/llmstxt-the-100-line-nextjs-route-that-makes-your-site-legible-to-ai-search-2650
Curious whether anyone has seen AI-referral data move after adding one - the honest answer for us is it's too early to tell.
