DEV Community

OnePassApps
OnePassApps

Posted on

The Data-Attribute Layer of app.onepassapps.com: 16 Names, 589 Attributes, and One Page That Carries 77

I work on OnePassApps, the team behind app.onepassapps.com, so this is a measurement of our own site. Everything below was measured on 9 November 2026 with plain HTTPS from one network - no session, no cookies, no JavaScript, one build, one edge.

We have written about the id layer, the class layer, the link layer, the JSON-LD identity layer and the landmark layer of these 56 pages. This one is about the layer in between: the attributes whose names start with data-.

It is the layer that says what a thing is for, rather than what it is called. Counting it whole gives a census of the fleet, and the census has a clear outlier: one page carries more of these attributes than the other 55 put together.

The census

I took every URL in our own sitemap - 56 of them - fetched each one and counted every attribute whose name starts with data-.

There are 16 distinct names across the fleet and 589 attribute instances in total.

Split them by who wrote them and the numbers get more interesting. 186 of the 589 are not ours at all: Cloudflare's edge adds data-cfemail, data-cfasync and data-cf-beacon to the documents it serves. The other 403 are ours.

The three Cloudflare names behave completely differently from ours, which is worth knowing before you write a parser against our HTML. data-cfasync and data-cf-beacon sit on one script tag on every page - 56 of each - and never vary. data-cfemail is Cloudflare's email obfuscation, and it is the one to watch: it does not carry an address, it carries a token. There are 74 of them, and they are spread very unevenly: 54 pages carry exactly one, one page carries two, and one page carries 18.

Our own names, and how far they reach

Only two of our names reach all 56 pages, and they sit on the html element: data-theme="dark" and data-theme-preset="graphite". The first is the dark-mode lock - the build sets the theme before first paint so a reader never sees a flash of the wrong one - and the second is the palette it locks to. Both carry fixed values, with no variation anywhere in the fleet.

Six more names sit on the 33 pages that boot the workspace: the startup shell, the startup phase, the startup mark and pulse, the shell fallback and the readable fallback block. Each of the six appears exactly once on each of those 33 pages, which is 198 attributes, and not one page in the fleet carries them a second time.

One name sits on the 23 static guide pages: data-public-discovery, on the main element, once each.

Those two groups do not overlap at all, and between them they cover all 56 pages. So from the served HTML alone you can tell a static guide from a page that boots the workspace - which is a faster test than counting script tags, and it needs nothing but the document.

That leaves four names that do not travel that widely, and they are where this story is.

The Terms page is the outlier

The Terms page carries 77 of our own data- attributes. The other 55 pages carry 326 of ours between them - an average of just under six each.

69 of the Terms page's 77 use names that appear on one or two pages of the whole fleet, and they break down into three groups.

55 of them are data-slot. Three slot names are in use, and they split the page's own furniture: link on 41 elements, reader-section on 12, and key-points on 2. A data-slot attribute names one of those three roles for an element, and the Terms page is the only page in the fleet that uses the vocabulary at all.

12 are data-policy-section, and every one of them has an empty value. By its name it marks the element as a policy section; the value carries nothing. Twelve sections, all marked the same way, all with nothing after the equals sign.

One is data-model-cancellation-form. A single element, marked as the cancellation form, on one page.

The remaining eight of the Terms page's 77 are the two theme attributes and the six startup names it carries like every other page that boots the workspace. Add Cloudflare's twenty - eighteen of them data-cfemail, plus one data-cfasync and one data-cf-beacon - and the Terms page serves 97 data- attributes in all.

Three of our names now exist on exactly one page in the fleet: data-slot, data-policy-section and data-model-cancellation-form. All three are on the same page.

The one name that names two pages

Exactly one of our data- names appears on precisely two pages, and it appears once on each: data-static-document.

Its value is the page's own name. It reads terms on the Terms page and plans on the Plans page - and nowhere else in the fleet.

Worth noting what it is not: it is not a marker of the static pages. The Terms page and the Plans page are two of the 33 pages that also carry the startup shell, so they boot the workspace like the app routes do. Whatever this attribute marks, it marks it on two pages out of 56.

What this layer is for

If you build a page that ships its own readable copy before JavaScript runs, you need to mark three different things, and it helps to mark them with different names:

  • the readable copy that a crawler or a no-JavaScript reader is meant to see,
  • the startup shell that stands in for the app until the app boots, and
  • the place the app is in its own lifecycle.

We use six names for the second and third of those, and one for the first on the guide side. The value is that a reader of the served markup can tell which page it is holding without executing anything.

What this is not

One build, one GET per URL, 9 November 2026, plain HTTPS from one network, signed out, with no browser and no session. The counts are a snapshot of that build. Cloudflare's three names are its own and can change whenever Cloudflare changes them; the 403 that are ours can change whenever we ship. I read the markup as served and counted attribute names and values as they appear - I did not run the app, so I make no claim about what these attributes are once the bundle boots, and I did not check whether anything in our own JavaScript reads them back. The 12 empty data-policy-section values are empty as served; I did not look for a script that fills them in later.

If you want to read the page that carries most of this vocabulary, it is here: the Terms page

And the other page that carries data-static-document, which is the only other page in the fleet with a named document of its own: the Plans page

Top comments (0)