惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
T
The Blog of Author Tim Ferriss
Recent Announcements
Recent Announcements
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
The Register - Security
The Register - Security
MongoDB | Blog
MongoDB | Blog
U
Unit 42
B
Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
P
Privacy International News Feed
L
LINUX DO - 最新话题
博客园_首页
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
V
Visual Studio Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
K
Kaspersky official blog
C
Cisco Blogs
博客园 - 【当耐特】
阮一峰的网络日志
阮一峰的网络日志
I
Intezer
罗磊的独立博客
MyScale Blog
MyScale Blog
Last Week in AI
Last Week in AI
A
About on SuperTechFans
G
GRAHAM CLULEY
Y
Y Combinator Blog
Microsoft Security Blog
Microsoft Security Blog
GbyAI
GbyAI
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
D
DataBreaches.Net
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
I
InfoQ
T
The Exploit Database - CXSecurity.com
Simon Willison's Weblog
Simon Willison's Weblog
博客园 - 叶小钗
Project Zero
Project Zero

Adactio

June 16th, 2026, 11:12am June 16th, 2026, 10:16am Enhancing with CSS Grid Lanes Speaking in Dublin June 13th, 2026, 9:09pm A tale of two browsers Sarah Canary by Karen Joy Fowler June 12th, 2026, 5:59pm The Field Guide to CSS Grid Lanes June 12th, 2026, 12:24pm June 12th, 2026, 8:58am June 11th, 2026, 6:22pm June 11th, 2026, 6:20pm June 10th, 2026, 6:25pm June 10th, 2026, 10:14am June 9th, 2026, 8:50pm June 9th, 2026, 1:55pm June 8th, 2026, 7:45pm June 8th, 2026, 4:32pm Amsterdamming June 5th, 2026, 3:16pm June 4th, 2026, 8:21pm June 2nd, 2026, 8:37pm 25 years of The Session Happy Monday everyone, and let's talk about gender and ethnicity ratios at tech events. AI and the Rise of Mediocrity May 28th, 2026, 7:24pm Picture at an exhibition May 27th, 2026, 9:41pm May 27th, 2026, 1:52pm May 25th, 2026, 8:03pm Gaeltacht cois Tamaise 2026 May 25th, 2026, 3:07pm May 23rd, 2026, 8:06pm May 23rd, 2026, 8:31am May 22nd, 2026, 3:38pm May 22nd, 2026, 8:19am May 22nd, 2026, 7:22am May 21st, 2026, 8:19pm Brigid by Kim Curran May 20th, 2026, 7:12pm The value is in the difficulty - Annotated May 17th, 2026, 6:21pm May 15th, 2026, 4:19pm Tito as Gaeilge The closing talks at UX London 2026 Three things about data Native Apps Should Be Avoided Whenever Possible — No One's Happy WebKit Features for Safari 26.5 May 11th, 2026, 4:17pm I knew my writing students were using AI. Their confessions led to a powerful teaching moment | Micah Nathan Gideon The Ninth by Tamsyn Muir May 8th, 2026, 3:55pm Better Browser Caching with No-Vary-Search May 7th, 2026, 9:55am May 7th, 2026, 7:49am The schedule for UX London 2026 Google’s Prompt API Reminder: You Can Stitch Together Lots of Little HTML Pages With Navigations For Interactions Netizen | Derek Sivers April 30th, 2026, 7:59pm April 29th, 2026, 8:12pm April 27th, 2026, 7:47pm April 25th, 2026, 12:03pm April 25th, 2026, 12:00pm April 25th, 2026, 8:03am April 24th, 2026, 7:57pm April 24th, 2026, 5:12pm Two Paradigms for Enhancing HTML Tags Summary punishment It's Not AI. It's FOMOnetization. Alistair Davidson / validation-enhancer · GitLab Never Lose Form Progress Again :: Aaron Gustafson Dilation Expansion artifacts April 19th, 2026, 6:03pm Finn Mac Cool by Morgan Llywelyn April 17th, 2026, 7:58am April 16th, 2026, 6:42pm Threat models No-stack web development Design and Engineering, As One · Matthias Ott April 14th, 2026, 7:21am April 13th, 2026, 7:47pm April 11th, 2026, 8:39am April 10th, 2026, 5:36pm My salary history Conference organising in 2026 April 7th, 2026, 8:32pm TinyStart AI Might Be Our Best Shot At Taking Back The Open Web | Techdirt April 6th, 2026, 12:46pm The AI Great Leap Forward April 4th, 2026, 6:42pm April 3rd, 2026, 5:27pm April 2nd, 2026, 8:58pm April 2nd, 2026, 4:32pm Web Day Out - 12 March 2026 Mistrust HTML Video Poster Image: Enable Responsive Images and ALT Text for Poster
How building an HTML-first site doubled our users overnight
2026-06-15 · via Adactio

This is a story of how building HTML-first doubled a company’s users literally overnight.

My client was a utility company, and they had a big problem. To apply for their services, customers could either use an old ASP form on the website, or follow a manual process. The manual process was more expensive for the company, of course. Adding a lot of pressure, this was a regulated monopoly, and if their customer satisfaction dropped below 96% (if I remember correctly) it could result in millions of pounds in fines.

There were two previous failed (and very expensive) attempts to solve the problem. In the most recent, contractors in another country had built a React app. The React app was online for 3 days before being pulled because of customer complaints. I took one look at it and told my boss “we can’t take ownership of this.” It was a mess of loading spinners and global javascript states. It was not accessible. Image upload was a vital part of the form, and it attempted to store images (along with all other form data) in localstorage which has a 5mb limit!

I took a very bold decision and built a new version of the site using Astro. It was HTML-first. Javascript existed, in web components, but only to progressively-enhance a website that worked perfectly fine without it.

My logic was thus:

  1. This is a public service
  2. It should work on every machine possible
  3. It should work when connections are poor
  4. The forms must never lose data once it is entered

I was very moved by this anecdote from Terence Eden:

A few years ago I was doing policy research in a housing benefits office in London. They are singularly unlovely places. The walls are brightened up with posters offering helpful services for people fleeing domestic violence. The security guards on the door are cautiously indifferent to anyone walking in. The air is filled with tense conversations between partners - drowned out by the noise of screaming kids.

In the middle, a young woman sits on a hard plastic chair. She is surrounded by canvas-bags containing her worldly possessions. She doesn’t look like she is in a great emotional place right now. Clutched in her hands is a games console - a PlayStation Portable. She stares at it intensely; blocking out the world with Candy Crush.

Or, at least, that’s what I thought.

Walking behind her, I glance at her console and recognise the screen she’s on. She’s connected to the complementary WiFi and is browsing the GOV.UK pages on Housing Benefit. She’s not slicing fruit; she’s arming herself with knowledge.

The PSP’s web browser is - charitably - pathetic. It is slow, frequently runs out of memory, and can only open 3 tabs at a time.

But the GOV.UK pages are written in simple HTML. They are designed to be lightweight and will work even on rubbish browsers. They have to. This is for everyone.

Some requirements I derived:

  1. Each session with the form should have a unique ID
  2. At every step in the form wizard, submitted data should be stored on the backend, including uploads
  3. It should be possible to complete the form without javascript
  4. It should be possible to complete the form on outdated and crap web browsers
  5. We had to meet WCAG accessibility (the team settled on AA rather than AAA)
  6. Javascript and modern CSS should be used to enhance the experience

The basic setup ended up being that each step in the form wizard was its own page. When the user clicked next, the form would submit. If the data was judged to be valid by the API, the browser would be redirected to the next step.

A venerable web application pattern that has had a small modern renaissance thanks to Remix, form submissions and redirects took a while to explain to my colleagues, on account of everyone being used to heavily client-side web applications. I have nothing against heavily client-side applications, in their place. But this is just a big form - it’s not showing real-time data. Our user could be standing in the middle of a field on a new-build housing estate, holding a decade-old commodity android phone they bought in Tesco. Shipping them 20MB of javascript before we even render a form would be a ridiculous thing to do.

Next, I tackled one of my biggest bugbears, form validation (and form and form error rendering). I have seen teams waste person-months of effort wrangling React validation libraries. If you are a React person, you might be scoffing at this - skill issue, I guess - but it is the reality for many teams. I would like to humbly suggest that you too may be spending more time than you realise, and a lot more time than is necessary, interacting with and maintaining poor imitations of the validation system that ships with every browser.

So I built an HTML web component. These are simple custom elements that wrap around existing HTML and bring it to life. No shadow DOM, no (or little) rendering HTML in javascript. Mine wrapped around any HTML form, picked up the HTML validation, and made it look modern. It would prevent those HTML validation popup tooltips, and instead place the error in the aria-describedby element associated with the field (today, aria-errormessage is advised instead). It would clear validation while you typed, if you reached a valid state, and assess it again on blur and submit.

Exactly the user experience a form needs, delivered in under 1KB. If it failed, the form would fall back to built-in browser validation. If that failed, the backend API would handle validation. We reported validation issues to the user as early as possible given their browser, and always fell back to an acceptable experience if it failed.

I have since written a new version of this web component from scratch, aimed for general use. It’s called validation-enhancer. I have been in this industry for over 20 years, and it is the best form validation library I have ever used. I am very proud of it.

The code is so simple to work with:

<validation-enhancer>
  <form>

    <label for="my-email">Email</label>
    <input type="email" name="my-email" aria-errormessage="my-email-error" required />
    <div id="my-email-error"></div>
    
    <button type="submit">Submit</button>
  </form>
</validation-enhancer>

The results? When we launched, the number of people completing the form doubled. The analytics people didn’t even know where these users were coming from. Of course, your javascript-based analytics package doesn’t see the users you are bouncing because of javascript failures. It was a flood! We also saw my “keep a backend session, never lose user data” approach pay off. In one case, someone completed a form a month after starting it.

There was a sad coda; as is the way of contract work, I moved on. I explained what I had built to my replacement, that it always worked even without javascript. He was appalled and said, “but that’s a lot more work for us.”

It is not acceptable to bounce users on old browsers, users with bad network connections, users using assistive technologies. Certainly not from a monopoly public service. A lot of hype and noise is pressing us to extend the cowboy, wild-west phase of the software industry’s expansion. We should set that aside, and take ourselves seriously as a mature industry. Build a web application that works on a playstation portable on a 3G connection - if you do, it will work for all your users, and it will still work 30 years from now.