Build1 distinct publisher2 min readPublished
The photo-modal pattern gives a lightbox a shareable URL by resolving the same route twice, once on a client transition and once from scratch. Only the from-scratch path needs a fallback file per slot.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
Follow any of these and your For You feed starts watching them — no settings page required.
build
A strict CSP killed one form in production, and every monitor stayed green1 distinct publisher
build
Five frameworks, one store, and a benchmark that measures when the button works1 distinct publisher
build
Next.js 16 moves the cache decision into the component tree, and the review surface with it1 distinct publisher
build
Next.js 15 warns instead of failing, so the async params fix keeps getting deferred1 distinct publisher
The two navigations resolve slots by different rules. On a client-side transition Next.js already holds a rendered tree, so a slot whose contents no longer match the URL keeps showing what it last rendered rather than unmounting [4]. On a fresh page load there is no prior tree to keep. Every slot in the layout has to resolve from the file system, and a slot with no matching segment and no `default.tsx` has nothing to return [3]. That is where the 404 comes from.
The folders are worth it because the alternative cannot do the second half of the job. A lightbox toggled by a boolean in `useState` opens fine and shares nothing, since there is no URL for that piece of state [10]. Parallel routes give the slot a name instead, and Next.js passes each slot's matched content into the nearest layout as a prop named after the folder, alongside the implicit `children` slot every layout already receives [8]. The `modal` prop in your layout signature is a modal only because you called the folder `@modal`.
The interception rule is narrower than the convention list makes it look. `app/@modal/(.)photo/[id]/page.tsx` intercepts a client-side navigation to `/photo/[id]` when that navigation starts from a route sitting at the same level as the `@modal` folder [9]. Refresh, or paste the URL into a fresh tab, and Next.js resolves `app/photo/[id]/page.tsx` the ordinary way [6]. The dev.to author is explicit that this full page is the destination the pattern is built for by design [6].
So count the files one shareable modal URL costs you: the real page at `app/photo/[id]/page.tsx`, the intercepting page at `app/@modal/(.)photo/[id]/page.tsx`, and one `default.tsx` in the slot [1]. The third is the cheapest of the three, because it is allowed to be a component that returns `null` [12].
The forgiving soft-navigation behaviour is intentional design. The same author reuses the mechanism for a dashboard with `@team` and `@analytics` panes, where clicking a link inside `@analytics` re-renders only that slot and `@team` keeps whatever it was showing [11]. Keeping the last render is the feature there. In a modal slot it is the thing that lets the missing file survive review.
The check is mechanical: one `default.tsx` per `@` folder, and at least one test that arrives at the intercepted URL cold rather than by clicking.
Ranked by verification strength, evidence, and original report placement.
Parallel routes let a Next.js App Router layout render more than one page at the same URL through named slot folders prefixed with @, and slot folders do not add a segment to the URL.
The intercepting route conventions (.), (..), (..)(..) and (...) match a route relative to the file system rather than the URL, so a link clicked inside a feed can render /photo/[id] as a modal without any folder named (.)photo appearing in the URL.
default.tsx is what Next.js renders for a slot when the current URL does not match anything inside that slot; skip it and a hard navigation to a route that does not fill every slot 404s.
On client-side navigation, if a slot has no default.tsx and the new URL matches nothing inside it, Next.js keeps rendering whatever that slot last showed rather than unmounting it.
The author reports that the first time they skipped default.tsx, everything worked in dev until they hit refresh on a route with the modal open and got a 404.
A hard refresh or a shared link to /photo/123 is supposed to render app/photo/[id]/page.tsx as an ordinary full page rather than the modal, and the author calls that fallback the entire point of the pattern, not a bug to route around.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 31, 2026
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Reproducible, but uncorroborated
The mechanics come with their receipts: a file tree, a layout that destructures two slots, a fallback that returns null, a modal that calls router.back(). Any reader can rebuild it in twenty minutes, which puts this well above assertion. What holds the score down is that a single developer's post is the only witness — no documentation excerpt, no second implementer, and no Next.js version to anchor the behaviour to.
Two of the author's own apps
The usage record is exactly one developer deep: a photo grid, a dashboard, and one bug that reached real visitors. That last item is worth more than it looks — a fix forced by production traffic is harder to fake than a tutorial — but there is no download count, no telemetry, no other team's deployment in this reporting.
Talks itself down
The piece spends its most emphatic paragraph arguing that the thing readers want — a modal surviving refresh — should not happen, and that the plain full page is the payoff. No benchmark, no framework triumphalism, no claim beyond what the file tree shows. If anything the headline finding is undersold: a defect that passes every manual test and fails only on the path shared links take deserves more alarm than it gets.
Credibility, not commerce
Nobody is selling anything here. There is no vendor relationship on display, no product, no course — the return on a community-platform post is reputation, and reputation punishes a file tree that does not compile. The mild pull worth naming is the practitioner-narrative genre itself, which rewards a tidy 'I fought it, then I understood it' arc over the messier question of which framework versions this holds for.
Narrow claims, single witness
We are confident about what is being claimed and how to test it, less so about its durability. Framework routing conventions are the kind of fact that changes between minor releases, and with one uncorroborated account and no version named, a reader should verify against their own installed Next.js before trusting the 404 behaviour as stated.