Why don’t more developers "use the platform"?

56 points by nolan a day ago on lobsters | 30 comments

adam_d_ruppe | 20 hours ago

It is bed time for me and I can rant about this at length, but I think a lot of people just genuinely have no clue what the platform can do, and because everyone else is doing it one way, there's disincentive to bother learning. I'm constantly frustrated by bosses being like "sure you can do that but what about the rest of the team?" even when it is trivial. Or recently here on lobsters I said in a comment it is trivial to do an upvote form without js and several people came in to berate me cuz they couldn't even believe such a thing was possible, much less trivial. If everyone else needs 100 lines of TypeScript to make a hyperlink, why should they believe I can do it with just <a href="url">?

ambiso | 15 hours ago

recently here on lobsters I said in a comment it is trivial to do an upvote form without js

Could you link that thread? I can't find it. Thx!

adam_d_ruppe | 6 hours ago

here it is:

https://lobste.rs/s/esvncd/how_building_html_first_site_doubled_our#c_t1r0eu

Roy Fielding talked about "hypertext as the engine of application state" in his REST paper, often abbreviated to the unfortunate HATEOAS (seriously not good marketing to term you thing "hate" lol). I'd argue you should just call it "hypertext as application state", because when he wrote that paper, what, exactly was the "representational state" being transferred? HTML!

People talk about the difficulty of application state and visual state getting out of sync, but one way to reduce this is to make them one and the same, which is what html lets you do. Then, you make all changes that affect the server go through the HTTP system, which is represented in html as forms.

So, in that case, the upvote button changes a state on the server; it creates an upvote record. So you want it to be a POST form. Anything you do beyond that, like background submission of the data, should be done on top of this form and should use the form data directly, so there's less chance for things to get out of sync.

An upvote button has no additional visual state, but if you look at the github PR (or view source, since it is merged and deployed now), you'll still see one element there: upvote vs unvote. If the UI shows the red arrow, the form changes to unvote. The application state, whether you already voted or not, is encoded right into the html and the form so you see what is submitted. If you were to open another tab and unvote there, your submission now has a state conflict and will be rejected (well that or silently succeed, im not sure what the lobsters backend does, HTTP lets you define a verb that is idempotent - it just ensures your state expectation matches the server - or not and there's standard error code 409 Conflict when it doesn't).

A more interesting case might be something like a table editor. You display some data and want to let the user edit entries and reorder rows. Do this in the DOM! Make each table cell a form element and use the sequence in which it appears to correspond to the state to be modified on the server. A lot of people don't realize that form submissions can have repeated names and the order of each entry is well defined. So you can make an array of names actually be <input type="text" name="name" /> repeated. If you have an existing row id, you can embed that as a read-only form element, or maybe a hidden element if you don't want it user-visible, so it is present in the submission too.

Now, if you want to rearrange an entry, literally move the whole table row node in the dom to the new location. The browser will redraw it, updating the user's visual representation, and when you submit the form, it will submit in the sequence in which it is displayed, so the server can update its representation of the state to match. DOM manipulations are (pending) application state manipulations when you think about it like this.

anyway i write too much in comments and too little in blogs this is why im always behind my publishing schedule lol

adamshaylor | 15 hours ago

Are you talking about the Next.js Link component?

frontsideair | 14 hours ago

It think they're talking about a general trope of creating a <div> and attaching a click handler that does a navigate. I think even Tiktok had one at some point.

adam_d_ruppe | 6 hours ago

Aye, this irks me because it came from a work project. The React guy wrote something like <div onClick={location.pushState(); location.href=something} class="text-underline yada yada yada"> and then user opened a bug report saying middle click doesn't open links in new window and he added another few lines to the handler, then shift+click, then keyboard navigation.... 100 lines is a bit of an exaggeration, but it added up fast. (and right click, open in new window still doesn't work so it'd prolly be more than 100 if it tried to do all that too!)

adamshaylor | 14 hours ago

Sometimes I get the impression—especially in the case of the larger, more enshittified social media platforms—that obfuscation is not an accident but the goal.

kornel | 18 hours ago

The platform is often all-or-nothing, so when the built-in behavior isn't perfect - in all browsers - the devs are forced to reinvent the thing from scratch. The date picker is most hopeless of them all. Sometimes it's due to some detail, like a weird line-height or small tap area, or animation that is too fast/slow/not in sync with some custom element.

I also expect that devs who got burned by some buggy or non-customizable detail don't even try to use the platform next time, and go for having full control from the start to avoid disappointments later.

adamshaylor | 15 hours ago

<select> is another. When a developer has everyone who signs their paycheck (and the people who sign those people’s paychecks) breathing down their necks about why it doesn’t look like the rest of the website or doesn’t have the search feature the designer promised because the number of options is very long, they can either find a real solution to that very real problem or they can find some other job that affords them the ability to cling to a platform-or-bust ideological purity and spit on those who don’t.

[OP] nolan | 16 hours ago

That's a good point, and it's kind of the whole reason that the Open UI effort exists. A lot of the built-in <input>/<textarea> -type elements really suffer from this. (Monica Dinculescu had a great talk on the subject.) I think that the direction the standards bodies are going in nowadays – starting from base primitives like popover and anchor positioning – are likely to lead to better outcomes than the all-or-nothing approach.

Thanks, I didn't know about Open UI. And you are right, every couple of years I discover that what previously necessitated a fully custom element can now be just lightly styled.

MatejKafka | 16 hours ago

I suspect there are a few more aspects:

  1. Many (most) developers are not power users and they don't see the depth of what the platform provides and what they lose by rolling their own implementation. To give a few examples:
  • middle-clicking a link to open it in a new tab (doesn't work with most JS-based "links")
  • keyboard navigation (Alt+<letter> shortcuts in menus, tab order, typing in dropdowns,...)
  • consistency with other native controls
  • platform integration (password managers, accessibility tooling, navigation history,...)
  1. Especially on the web, some platform components are still somewhat broken (e.g., date pickers) or missing (e.g., why is there no browser component for an image gallery and instead every website has its own creatively broken half unusable version? same for rich text editing).

koala | 9 hours ago

Many (most) developers are not power users and they don't see the depth of what the platform provides and what they lose by rolling their own implementation.

I suspect you are right, but it really says something that being the web like one of the most popular platforms for anything, that web developers might not be familiar with middle-clicking, shortcuts, etc. is... something.

My other theory is that the people who take the decisions don't think quality leads to profit. So they'd rather spend resources in trying to make money from more questionable things, such as selling customer information, targeted advertising, etc.

[OP] nolan | 4 hours ago

It's a good point, yeah. I think in my "dialog" example a common case would be that the JS developer builds something that works well enough for sighted mouse users and then completely ignores all the stuff you're supposed to do for keyboard or screenreader users.

I think some of it also comes from React component libraries not having the proper affordances/idioms to easily swap in a link for a button or vice versa. So you reach for a button to do a link's job and then break a bunch of stuff like right-click, middle-click, etc.

OTOH I've also seen cases where the React library did have the proper idioms, and the problem is that the developer didn't know to use them! For example at my work we use Chakra UI which I've found has excellent accessibility, but only if you use it exactly as documented. (Arguably this is another case of "not understanding the platform.")

adam_d_ruppe | 2 hours ago

Two comments... one, when people say like <select> looks wrong (something btw that isn't the case anymore like it used to be), I point out that compromises are always made. Often, people compromise on the accessibility or nojs or whatever minority case instead of the visual bits the majority sees, but fact is they do compromise on requirements and sometimes you can convince them to shift which compromises they make in favor of using the platform instead of the alternatives.

Second comment on links and buttons, it occurred to me a little while ago that every link is a button, but not every button is a link. Specifically, every link is conceptually a submit button on a little GET form, with action of the href url. I think it is kinda useful to realize this to help with a conceptual model (actually, why can't you submit any form to a new window? they really should be more interchangeable than they currently are), but the link is also quite specialized out of the box and it is the specializations that give the attention to detail that makes a UI pleasant to use.

I think my advice (and I want to write a tutorial someday, like web from first principles, but who has the time) would be to realize the general concept then go to the most specialized thing the platform offers that still fits, and then go ahead and specialize it a bit more with your css/script. When doing a thing, ask: What is it? What does it do? What does it look like? in that order and go from there. But "what is it?" is a kinda deep philosophical question that is easy to beget lol

frontsideair | 14 hours ago

Oh boy I have a lot of thoughts about this.

Firstly, #usetheplatform is regarded as false a premise by many, because the "platform" they talk about is 90% controlled by Google and their most recent motivations, and usually "Works best in Google Chrome™" until their competitors are bullied into implementing those features as well.

As a "React developer" I personally enjoy working at a higher abstraction level while building web UIs, and dropping down to the imperative browser APIs causes me to do a mental gear change. I would never want to mix this with business code, and containing it to a reusable component in the end looks the same as pulling a dependency from npm with much better testing and coverage, if I can find one.

I think the IKEA effect can be reversed as well. If you can use something from npm, building it yourself instead is kind of fun and challenging. There are many npm packages that only exist to wrap a non-ergonomic browser API to adapt it to the React world. And I've seen many junior engineers (and agents) make the mistake of never bothering to check if this was already packaged on npm and roll their own version of it.

React vs browser APIs being in different abstraction levels may not be obvious to everyone, so let me elaborate a bit further. React--and most of its modern alternatives--let me write and compose components declaratively, and you pass things directly using variables and import/exports. Web components, the cited platform alternative to React and its ilk, use string references as component names, and pollute a global namespace. That's just the tip of the iceberg for me for never even considering web components.

To set the record straight, even though the platform is controlled by an evil company, most of it is still great. I get excited by code that I get to delete thanks to the new browser feature! And I usually consider non-ergonomic web APIs as a compile target anyway and write my code at a higher abstraction level. I find npm to be a treasure trove if you know how to navigate it, but it's still useful to take a few minutes to see how your dependencies work under the hood.

#usetheplatform hashtag tries to make this picture black and white. There are horrendous web APIs that I wouldn't touch with a ten foot pole, but I still use web APIs directly or indirectly, and I see it as my responsibility to keep up with the additions to see how I can make my code easier to maintain, more performant, and more accessible.

As a user, I utterly despise react as the reason why every indivifual browser tab these days takes 20 seconds to load and hydrate, and then eats up good half a gig of memory while providing absolutely no value over a plain server-side-rendered html page.

frontsideair | 14 hours ago

I think it's more like 30% React and 70% the stack of 50+ trackers the business insists on putting on the website. GTM, RUM, they have even started capturing traces to generate test cases.

aspensmonster | 14 hours ago

while providing absolutely no value over a plain server-side-rendered html page.

Alas, the "value" is in pushing the HTML rendering expense onto the client so that you don't have to buy servers to render the HTML.

frontsideair | 14 hours ago

Server-side rendering with React is old news at this point, and you can even avoid the hydration penalty by not shipping the React bundle and using React as a nicer server-side templating engine? (Though not widespread, this kind of usage isn't zero.)

alanmeira | 7 hours ago

until their competitors are bullied into implementing those features as well.

That's quite the distortion. Google can't bully Apple implement anything. Apple isn't some defenseless victim when they don't implement PWAs correctly.

frontsideair | 7 hours ago

But Apple isn't the only competitor.

alanmeira | 7 hours ago

which browser competitor got bullied to implement features? By bullying you mean the billions of dollars Google paid Mozilla?

[OP] nolan | 4 hours ago

I think it's a fair point that "use the platform" originally came out of Chrome DevRel (at least, that's where I first heard it). But I can't recall any other browser vendors taking exception with it, and I imagine that the non-Google engineers working at the CSS Working Group would be delighted if more web devs used their stuff!

One of the reasons I didn't get into web components is that they're a very touchy subject and not an obvious slam-dunk win like "replace 100 lines of JS with 1 line of CSS." Also keep in mind that nobody (or very few) people in the web components space ever expected web components to replace frameworks entirely – there's a reason that Lit, Fast, LWC, etc. are built on top of web components. So some of the "use the platform" marketing there was directed at framework authors themselves (React, Solid, Svelte, etc.), who I think had very reasonable gripes with the limitations of web components (SSR, accessibility, etc.). Anyway I had two entire posts on the topic, so no need to rehash it here. 😆

adam_d_ruppe | 2 hours ago

Until recently, I thought web components looked kinda cool, but were also impractical for real work because of the requirement to use javascript. The benefits they bring can mostly be done other ways too... like I have server side expansions around, can use delegated event handlers in the dhtml case, etc. What convinced me to finally try it again was a blog post (i don't think from you but possible) here on lobsters that said use it without the shadow dom as a progressive enhancement hook.

I just started playing with that on Friday and I'm already really happy with it - keep the server side expansion, then implement the same thing in javascript as well (both based on just three substitution rules from a template, my impl was about 100 lines in both D and Javascript), and put a little framework around concatenating stylesheets using the relatively new nesting stuff in css and... it is coming out really nice and I'm not sacrificing the nojs users. And actually, it enhances a bit even for them, because it makes the noscript bit a little easier to support - putting all the script-required bits in the attach element thing and allowing some <noscript> bits in my template does a nice bit of encapsulation.

Like I said, only started playing on Friday, so too premature to delcare Mission Accomplished but I am really happy with it so far. I might even actually use the shadow dom sometimes now lol

freddyb | 14 hours ago

Adopting a library is always easier than removing it. Every project that builds on an evolving platform needs a team that tracks libraries and in-house abstractions against new platform features to then remove the old cruft. But I bet most just don’t.

ryan-duve | 22 hours ago

Not sure about your Clickhouse compression experience, but for me building from scratch is an amazing way to learn and develop.

A few years ago while our database guy was OOO, I spent a Friday afternoon writing a SQL query (Presto, maybe?) that took urlsafe, base64 encoded UUID (stripped of padding) and converted it to the typical 36 character varchar. IIRC, the guy came back Monday morning and redid it with like 2 built-in functions as expected, but the things I learned that day about SQL, base64 and UUIDs have been of immense utility ever since.

[OP] nolan | 21 hours ago

Oh yeah, a world where you don't experiment and just take APIs handed to you on a silver platter is a world where you don't learn. This is the thing I wrestle with in the post where I talk about my experience building polyfills, shims, etc.

I don't have a great answer except that I think it's fine to experiment, but you should always be self-skeptical and run benchmarks, tests, etc. to make sure you haven't just fallen in love with your own code, Narcissus-style.

alevizio | 18 hours ago

The docs point is underrated imo. A library README shows you the finished thing with a demo, MDN shows you a mechanism and you assemble the rest yourself. <dialog> has worked fine for years, but the unstyled default is so bare that people still grab a component just to get something that looks done.

forestj | an hour ago

Because the "the platform" is not one thing, it is unpredictable in practice. If I customize the scroll bar in chrome, to make it wide enough so that users can see it, there is no indication to me that this will be ignored by Firefox.

If I try to use a key derivation algorithm to create an asymmetric key pair , it will work in chrome , and again, there is no indication to me that it will fail in Firefox until i test it..

So for any component which Must work (why put things in your app that don't have to work?) We have to exhaustively research how every single platform implementation implements it.

Sometimes its just easier to build it yourself than to do the research, other times, the platform is user-hostile in ways that we don't like, or conflicts with design requirements, such as the user being able to see the scroll bar and grab it, or being able to generate an asymmetric key from something other than the webcrypto prng, such as from user input.