Server-only code is code that runs on the server and never ships to the browser. Database queries, password checks, API keys, cookie secrets — anything that would be dangerous or useless if a visitor could see it.
Think of a theater. The audience sees the stage — the set, the actors, the lights. Backstage is where the rigging, the scripts, and the lighting controls live. You don't wheel the lighting board on stage — some things only make sense behind the curtain.
Your server is backstage. The browser is the stage. Server-only code is everything that belongs behind the curtain — the audience never sees it, and the show breaks if they mess with it.
Two naming patterns tell React Router "this file stays on the server":
.server/ folder — everything inside is server-only. app/.server/auth/cookie.ts never leaves the server..server suffix on a filename — helpers.server.ts stays on the server even if the folder around it isn't marked.React Router sees these names during the build and removes those files from the code that ships to the browser.
This is called tree-shaking — the build process shakes out everything the browser doesn't need, like shaking a tree to drop the dead branches. What's left is only the code your visitors actually run.
Import paths make this visible. If the path contains .server, the code stays on the server:
~/.server/auth/cookie → server-only
~/models/.server/user → server-only
~/lib/data/validate → works on both sides
Without this convention, your database connection string, your cookie secret, and your admin-check queries would all get bundled into the JavaScript the browser downloads. Anyone could open their browser's dev tools and read them. The .server convention makes the boundary visible — and enforced.
Not all code needs to pick a side, though — some code works on both. That's called isomorphic code.
?What is isomorphic code?