I work on OnePassApps, the team behind app.onepassapps.com, so this is our own site. Everything below was measured on 8 November 2026 with plain HTTPS from outside the browser - one GET per URL, no session, no cookie, no JavaScript, signed out.

We have written about the routes that exist (the route contract), the document a missing URL returns (the miss page) and what happens to a query string (the tracking-link contract). This post is about the paths that are not routes at all: what the server answers when you add a file extension, when you add the word "index", and the one live page on the site that nothing links to.

One extension redirects. Seven do not.

Take a route on the site and add a file extension to the end of it. Exactly one extension earns a permanent redirect to the extensionless path. Every other one gets the miss page.

/apps/movie-tracker.html 308 Location: /apps/movie-tracker /guides/movie-tracker.html 308 Location: /guides/movie-tracker /voting.html 308 Location: /voting /studios/image.html 308 Location: /studios/image /guides.html 308 Location: /guides /plans.html 308 Location: /plans /apps.html 308 Location: /apps 

That is seven route bases times eight extensions, fifty-six requests in all:

  • .html answered 308 on all seven, with a relative Location pointing at the extensionless path.
  • .htm, .json, .xml, .txt, .php, .xhtml and .HTML answered 404 on all forty-nine, each returning the same 13,953-byte document titled Page not found — OnePassApps.

So the rule is one lowercase extension, not a family of them: .HTML is a miss page, and .htm is a miss page.

The redirect only fires on a route that exists. Ask for /not-a-real-page.html or /apps/nope.html and you get the miss page, not a redirect - the redirect needs a route behind it: the path is resolved first, and only then can .html be stripped.

The query string survives the extension

/apps/movie-tracker.html?utm_source=devto 308 Location: /apps/movie-tracker?utm_source=devto 

The campaign parameters come through the redirect intact, the same way they survive a trailing slash. A tracked link that picked up a .html somewhere still lands on the page with its tracking.

The index segment is a rule of its own

Drop index into a path and the server answers differently again:

/index 308 Location: / /index/ 308 Location: / /index.html 308 Location: / 

At the root that is one hop. On a sub-path it is two:

/apps/index 308 Location: /apps/ 308 Location: /apps 200 /guides/index 308 Location: /guides/ 308 Location: /guides 200 /voting/index 308 Location: /voting/ 308 Location: /voting 200 /studios/image/index 308 Location: /studios/image/ 308 Location: /studios/image 200 

Dropping index leaves a trailing slash behind, and that trailing slash is itself answered with a 308 - which is why these chains take two hops and the root takes one.

The two rules do not compose

Here is the part that surprised me. If index is a rule and .html is a rule, then /apps/index.html should satisfy both: strip the extension, drop the index, land on /apps.

It does not:

/apps/index 308 Location: /apps/ 308 Location: /apps 200 /apps/index.html 404 Page not found 

The extension rule and the index rule are checked separately, and a path that needs both is answered with the miss page. /index.html is the single exception at the root, because there the index segment is the whole path.

Two escapes behave as if they were decoded first

Hex escapes in the path are resolved before the rules run, so they reach them:

/apps/movie-tracker%2Ehtml 308 Location: /apps/movie-tracker /apps/movie-tracker%2ehtml 308 Location: /apps/movie-tracker /apps/movie-tracker%2F 308 Location: /apps/movie-tracker /apps/movie%2Dtracker 200 /apps/movie%2dtracker 200 

An encoded dot reaches the extension rule, an encoded slash reaches the trailing-slash rule, and an encoded dash is decoded to a plain dash in the slug. The case of the hex digits does not matter.

Two neighbouring paths did not decode the way I expected. /apps/movie-tracker%20 and /apps/movie+tracker both answered 404 with the miss page, so a space in a slug is not something the router can find.

One live page that nothing links to

The last piece is a page that works, and that no index we publish mentions.

/apps answers 200 with 13,815 bytes and the title Apps — OnePassApps. Its description reads "Open a specific OnePassApps app from the main catalogue." It ships the same shell as the rest of the site: four script tags, the crash-fallback template, and the second heading that only appears when the app fails to boot.

Then the things around it:

  • It carries <meta name="robots" content="noindex, nofollow" />.
  • It carries no canonical link. All 56 URLs in our own sitemap.xml carry one.
  • It is not in sitemap.xml, which lists 56 URLs and does not include it.
  • It is not in llms.txt. That file has 22 mentions of /apps and every one of them is a slug such as /apps/newsflow; the bare /apps appears nowhere in it.
  • Nothing on the site links to it. Across all 56 sitemap URLs and the five routes that are not in the sitemap (/, /support, /account, /sign-in, /sign-up) there is not one href pointing at /apps. The only link to it anywhere is the absolute self-link on the page itself.
  • It is cached like a real page: Cache-Control: public, max-age=0, must-revalidate, the same header the 56 published pages send. The miss page sends no-store.

So it is a live, cacheable, deliberately-unindexed page that is in neither of our index files and is unreachable from anywhere on the site. I am not going to guess why it exists; the measurements above are what it is.

Limits

One build, one day, 8 November 2026, plain HTTPS from one network, signed out, no browser and no JavaScript, one request per URL. These are the bytes the server sends - I did not measure how any browser renders them, and I did not sign in. Byte counts and header values are a snapshot of one build.

The miss page's byte count is stable, but its bytes are not identical between two fetches of the same URL: 84 byte positions inside a 127-byte span differ, and that span is Cloudflare's per-request email-obfuscation token. Decoding either token with Cloudflare's own XOR scheme gives the same address both times.

Nothing here is a claim about how a crawler or a browser treats a 308, a noindex tag or a missing canonical. I did not check whether any search engine has indexed /apps, and I did not test from inside a search index.

If you want the apps themselves rather than the routing: the catalogue and the guides.