Frontend: URLs With a Good Memory

Deep linking is your app’s memory trick.

Instead of hiding state in fragile client-side limbo, you let it live right in the URL—out in the open, honest, and bookmarkable. A good URL doesn’t just say where you are; it explains why the screen looks the way it does.

Done well, a refresh brings you back to the exact same spot, which:

  • Makes links easy to share
  • Makes bugs easier to reproduce
  • Makes state visible instead of mysterious

The URL becomes part of your UI contract.


Route Params vs Query Params (Know the Difference)

Think of URLs as having two kinds of pockets:

Route parameters

  • IDs
  • Slugs
  • Things that identify what you’re looking at

Query parameters

  • Filters
  • Sorting
  • Pagination
  • Tabs and view modes
  • Anything unbounded or optional

Route params answer “which thing?”
Query params answer “in what state?”


Standalone Routes Are a Feature

A deliberate tradeoff of deep linking is this:

Every route should gather everything it needs to render itself correctly.

No relying on:

  • A previous page visit
  • A half-remembered global store value
  • A fragile sequence of user actions

Each view should stand on its own two feet. This makes:

  • Reloads safe
  • Navigation predictable
  • Debugging far less mystical

Example: Honest State in the URL

// /users/42?tab=posts&sort=recent
export function UserView() {
  const params = useParams<{ id: string }>();
  const searchParams = useSearchParams();

  const { id } = params;
  const tab = searchParams.get("tab");
  const sort = searchParams.get("sort");

  return <div>...</div>;
}

Anyone opening this link—now or later—lands in the same context. No secrets. No surprises.


Backend: Predictable Routes, Calm Brains

On the API side, a RESTful route structure that mirrors your data model keeps things boring in the best possible way.

Predictability is a feature.

If you know the resource name, you should be able to guess the endpoint without consulting a wiki or a Slack thread from 2021.


A RESTful User Resource

GET    /user        -> list users
GET    /user/:id    -> fetch a user
POST   /user        -> create a user
PUT    /user/:id    -> replace a user
PATCH  /user/:id    -> partial update
DELETE /user/:id    -> remove a user

Each verb means exactly what it says.
Each URL shape tells you what it operates on.

No riddles. No surprises.


Why This Matters (More Than It Seems)

When frontend routes and backend APIs are:

  • Explicit
  • Predictable
  • Shareable

You get:

  • Easier debugging
  • Clearer mental models
  • Fewer “how did we get here?” moments

This structure also plays very nicely with:

  • Automated documentation
  • Testing
  • CI/CD
  • And AI tooling that expects clear, contract-driven systems

Final Thought

URLs and APIs are not just plumbing—they’re interfaces.

When they clearly describe state and intent:

  • Your app becomes easier to reason about
  • Your users get reliable behavior
  • Your team spends less time guessing

Make state visible.
Make routes predictable.
Let links tell the truth.

Back to Philosophy