Plain Vanilla Web
plainvanillaweb.com
plainvanillaweb.com
I've discovered that when you start getting really cynical about the actual need for a web application - especially in B2B SaaS - you may become surprised at how far you can take the business without touching a browser.
A vast majority of the hours I've spent building web sites & applications has been devoted to administrative-style UI/UX wherein we are ultimately giving the admin a way to mutate fields in a database somewhere such that the application behaves to the customer's expectations. In many situations, it is clearly 100x faster/easier/less bullshit to send the business a template of the configuration (Excel files) and then load+merge their results directly into the same SQL tables.
The web provides one type of UI/UX. It isn't the only way for users to interact with your product or business. Email and flat files are far more flexible than any web solution.
I've purchased specialized woodworking tools online that simply involved filling out a form. I later received the parts with an invoice to send payment. You can simply not pay if you choose not to.
There are so many way to do commerce both on and offline and if you squint and look closely you'll find interesting people doing interesting things all around you.
People romanticize businesses like this but there’s a reason you’re not posting the link. It only works when it’s for a small group of people who are in the know and refer trusted buyers.
It’s also trivial to set up any number of different online purchase options that would avoid all of the problems with this for a nearly trivial fee.
I guess I’ve spent enough time dealing with things like non-payment or doing work for trades that never arrive that I just don’t romanticize this stuff any more.
Payment after receipt is very common in Switzerland, but fraud is presumably rare. Your name would probably go on the debtors register and that's the sort of bad credit history you don't want to have. At some point the police/debt collection is involved, they get sent to whatever the address is and so on. For the average person it's not worth burning your name and address for a free spokeshave.
I know the other way around is basically the norm: how does one know the company, the seller, will actually provide the product after paying. But the prevailing culture, currently, is that companies in this regard are trustworthy and customers are not. It's a bit debatable but it makes sense.
It's only a matter of time before this seller falls victim to a scammer - once they're found. I used to work for a book publisher who started doing their own e-commerce, and at the time one of the payment methods was a "pay later" one that predated the internet ("acceptgiro"). It only took a few months (if that) after the first sites went live that someone placed an order for a few hundred euros worth of books and had it delivered at a storage unit address. We scrapped the pay later payment option for orders over a certain amount then, and I'm sure later on the pay later option was removed entirely in favor of pay in advance methods.
There's newer pay later schemes now (Klarna IIRC) but the risk and debt collection falls to this payment provider. Of course, they got in legal trouble recently because they're a loan / credit company but didn't present the user with the right legalese for that.
While an e-commerce solution is not always needed, there’s a good chance that a very simple shop cart facility will convert more than an email link, for certain types of products.
I would immediately discard any website that makes me send an email to order.
Yep :)
Why do I want "interesting" ways to buy things? I want to be able to buy what I want quickly and reliably. I don't get the benefit of making me try to figure out how to buy something I want
There are times when it's the easiest way to handle things, especially for experienced users. But I find it a massive hassle to maintain support for every possible mistake the user can make.
The benefit would be that you have a fixed set of UI components available in Excel and don’t need to worry about styling and whatnot.
If you have certain options, use Excels forms to place buttons, menus and selections.
I'm not an instant fan of it, but it is one way for someone to lay out their thinking about how to solve something that works.
The fact that this all got hyperlinked is a superb. convenient, but also a challenge from tech perspective, and what FAANG did in the 30 years to come (after 1992) led to this horror of entangled and super-complex technologies we have today. Even vanilla web is quite complex if you take into consideration all the W3 standardization.
Security or not, you can have an appliance run much simpler software given longer product lifetimes,... My only hope is now with llm-assisted coding this vanilla approach comes back, as the boilerplate pain becomes more bearable (how I really hated html at some point...). Besides, it is much more pleasant to prompt yourself a website, rather than try to position some image on stupid fb/insta pages/events, which is one major reason to step back and own your content again.
With that title I didn't expect Javascript to be part of the equation. To me "vanilla" is CERN's HTTP+HTML.
The thing that happened is that FAANG redesigned the web for their own needs, then other companies used that to fulfill their own needs too. That's how we ended up with a lot of available content, but also user info mining, browser monopoly, and remote code execution (JS) as a daily normalization of deviance.
There are some secessionists - Gopher is still alive, Gemini - but alternatives have a hard time to compete with the content companies can provide apparently for free. Most of the content we want costs time and/or money. Content creators can be fine with contributing from their own pocket, but this is not really sustainable. User sponsorship (donations via Paypal, Patreon, Kofi, ...) don't work well either.
Also, since the supporters of the alternatives are generally supporters of freedom (who isn't? Well, people don't reject freedom, they are "just" making compromises), they have to deal with illegal content and other forms of abuse.
So there are 3 problems an alternative web must solve: protocols, moderation and repayment.
I originally planned to scrape the data and make my own website with better (imo) controls, but v0 turned into pumping the data into a Google sheet.
I've never needed v1. The Google sheets "UI" solves filtering (i.e., breakfast vs lunch), access control, and basic analytics (~7 other colleagues also use this daily).
Enabling customer self administration/configuration of a "B2B SaaS" system mandates some form of interaction. I would be surprised at how many would not expect "touching a browser" to do so.
> A vast majority of the hours I've spent building web sites & applications has been devoted to administrative-style UI/UX wherein we are ultimately giving the admin a way to mutate fields in a database somewhere such that the application behaves to the customer's expectations.
If there is no validation of information given nor system rules enforcement, then I would question the correctness of said sites/applications.
> In many situations, it is clearly 100x faster/easier/less bullshit to send the business a template of the configuration (Excel files) and then load+merge their results directly into the same SQL tables.
This approach obviates the value added by a system enforcing core software engineering concepts such as fitness of purpose, error detection/reporting, business workflows, and/or role-based access control.
In short, while letting customers send Excel files "and then load+merge their results directly into the same SQL tables" might sound nice, this does not scale and will certainly result in a failure state at some point.
Much of US banking operates almost entirely on this premise and has done so forever.
> error detection/reporting, business workflows, and/or role-based access control.
I'd take a look at the Nacha (ACH) operating rules if you have any doubt that sophisticated business workflows can be built on top of flat files and asynchronous transmission.
We execute Python in our PG database and do testing through PGTAP.
> Email and flat files are far more flexible than any web solution.
Some times I feel like I’m taking crazy pills when I read HN lately. Suggesting that we e-mail requests around and have a person on the other end manually do things including merge data into SQL tables is such a bizarre claim to see. Every once in a while I encounter some business that operates like this and it’s inevitably a nightmare, either as a customer or a partner. Not to mention it’s ripe for everything from fraud to the company falling apart because the person who normally reads those e-mails and does the things for 20 years suddenly leaves one day.
This feels like a mix of rose-tinted glasses reminiscing about the old-timey way of doing things combined with a layer of career burnout that makes everything modern feel bad. Dealing with a business that operates this way is not good.
It was like that one dude on HN that criticized Dropbox back in day saying he could have built it in a weekend using rsync and a bunch other nerd nonsense that the average person doesn’t have the time or the expertise to mess with.
Often it just reads like contrarianism for the sake or it
This evolved through multiple iterations as the government end of it did. At one point you no longer had to walk there physically; instead, there was a dial-up endpoint running UUCP that could be used to fetch the file. Then they found out about Internet, and it became a website with the file, now .mdb (MS Access) rather than .dbf. I rewrote the app in .NET/WinForms, since it was much easier to do all those things from it than to try bolting it onto an old TUI DOS app.
But it was still basically the same table with the same schema by mid-10s, and my app was still chugging along. I wonder sometimes if some iteration of it is still in use today; wouldn't be surprised if it were.
7:40 - Bob was delayed by 5 minutes. ETA 7.45
7:35 - Bob is heading your way. ETA 7:40
7:20 - Bob has picked up your order from Pizza placeIf you have even a small bandwidth to maintain it over time, quick and simple solutions like an Excel template and a few custom scripts work great and often end up being more flexible as your end user is mostly working with raw data.
That said, there are b2b exchanges where a simple website is perfect. Supplier quality cases where people need to exchange short texts or general supplier information exchange.
Also b2b customers are far less concerned about UX style than the average retail customer. The former wants a system that just works efficiently and everything else is a waste of time. Sometimes productivity clashes with modern sensibilities and in the b2b case productivity still wins.
I hate mail though for formal processes though. In that case a link to a simple website that orderly takes up information and it is the better solution.
I also hate putting excel files into tables. There is always something going wrong, especially with files created in many different languages, and it is still work overhead. But there are already solutions for general information exchange that aren't necessarily parasitic SaaS services.
Of course there are alternatives, but I wouldn't call the usual ERP/CRM software superior to web apps.
Every business is basically a phone number that you can message. It does not matter if you buy a pizza or furniture, book a hotel or need someone to clean your sofa.
No website. No need to fill in forms. No platform fee.
that is, letting your user to blindly and impulsively following what they want is a mistake.
My team and I built https://restofworld.org without any frameworks. The feedback, from surveys, outreach, and unsolicited emails, has been overwhelmingly positive, especially around usability and reading experience.
We might adopt a framework eventually (I do appreciate how their opinionated structure can cut down on endless debates), but for now, plain JavaScript serves us really well.
On the one hand we have lots of people on here who are building full-featured web apps, not websites, on teams of 30+. These people look at frameworkless options and immediately have a dozen different questions about how your frameworkless design handles a dozen different features that their use case absolutely requires, and the answer is that it doesn't handle those features because it doesn't require them because it's a blog.
Meanwhile there are also a lot of people on here who have never worked on a large-scale web app and wonder why frameworks even exist when it's so obviously easy to build a blog without them.
It would be nice if we could just agree that the web hosts an enormous spectrum of different kinds of software and make it clear what kind of software we're talking about when we were opining about frameworks—whether for or against.
In this case: this is a WordPress blog.
100kb would never be a considerations for any of the apps I worked on (as a contractor in the corporate world). I mostly work in large teams, sometimes we had mulit-team monorepos with various line-of-buisness apps using React. 100kb are so completely irrelevant, as for LoB or B2B, no-one cares about the initial page load. Your users use the app on a daily basis, so they get all the JS/CSS/static assets served from their browser cache almost all of the time, until we make a new prod deployment (usually weeks). Plus, all users are always on Ethernet or WiFi at least, not some 3G cellular network somewhere in the desert.
If you use some smarter framework like Next.js, you even get smartly chunked js parts on a per-route basis, that are immutable - they contain a sha256 hash of their content in the filename, and we configure the webserver to serve them via `Cache-Control: immutable`. There won't even be a roundtrip to check for newer versions.
Plus Nextjs comes with tons of other stuff, like pre-loading chunks in the background, or when hovering over a link (i.e. using the time between the hover and the click to already load a chunk). Let alone that the initial render is static html and hydration happens completely unnoticed from the user.
I do find it a little annoying that when we have these discussions about vanilla vs frameworks people hold up an example and I go there and see a news site of articles rather than a complex application, and I think to myself yeah I wouldn't have used a framework in this situation anyway. It's annoying from 2 directions: the first that people ARE using frameworks for sites that shouldn't have ever had them in the first place, and I can bring to mind a couple of news sites I visit regularly where this is obviously the case because of the silly ways they work. Secondly that this is then held up as an example, because most of my work is on very interactive sites so I end up thinking well yeah but that's not going to work for me is it. My feeling is that I could do vanilla but would end up with something like a site specific framework.
My current approach is to use a framework and consistent patterns but to try and use as few other dependencies as possible.
Also infinite scroll breaks the most basic usability issue - you can't track where in the article you're with the scrollbar positioning
And you're using WordPress, so yeah you are using a framework. Turns out you do think they're necessary.
And as you can see, framework != slow, whether it's WordPress or anything else.
Shit just show me how long it takes you to create a nice reactive table with search or a form with proper labels, user interaction, validation, errors, etc
Why would I implement that all from scratch when I can install svelte install a UI library and add a couple lines of code, all with a 25kb overhead and get a better, nicer looking, more well tested product that would take you to do in a week?
With most frameworks you don't need 100kB of JS code.
Heck, with Mithril you get the components, vdom, router, and http client in like 10kB gzip.
Puter (https://news.ycombinator.com/item?id=39597030) was also built purely using vanillaJS (or, JQuery to be more precise)
Any sharp edges to this approach?
Developer productivity, theoretically. Although some of these frameworks don’t help with that for me personally.
The web finally provides a widespread standard for deploying applications inexpensively. Unfortunately, the technology used to build user interfaces for the web remains somewhat mediocre.
It’s unfortunate that history took some wrong turns with X11, Java, Flash, Silverlight, .NET, and countless other alternatives that I haven’t personally lived through.
Hopefully, someone will eventually find a way to make developing web applications comfortable and the broader community will embrace it.
I hope that, in the long term, wasm and canvas (or something similar) will gradually take over this niche. Frameworks like Avalonia already let you write a desktop app and then surface it in the browser, today. This stuff is still rough around the edges, particularly wrt accessibility, but there's nothing unsolvable there in principle, it just needs time and effort (and money).
I do not understand why people hold this impression, especially in corporate environments.
Windows supports both system and per-user deployments; the latter so you don't even need administrator rights. And with Intune, deployments can be pulled or pushed.
Many desktop applications are written in .Net so you don't even need to install the runtime because it's preinstalled on the operating system.
Even ClickOnce deployments -- which you can deploy on the web or on a file share -- pretty much make deployments painless.
EDIT: For the naysayers: please then explain to me why Steam is so successful at deploying large games on multiple platforms?
If you’re writing an SPA, and it isn’t Twitter or a content consumption platform, and it isn’t necessary to be API-driven, seriously just stop. You’re not clever, you’re not improving the experience, you’re only appealing to the tastes of other programmers. If billion-dollar companies can’t get them working perfectly, you certainly won’t.
I get that huge apps probably need a lot more than that, but so many people these days reach for heavy frameworks for everything, because it’s all they know.
I openly admit that I'd rather learn a new framework than touch anything to do with figuring out how the browser is intended to behave in practice. What an abomination and insult to humanity.
Edit: holy shit y'all do not like the earnest approach to technology
It’s such a pain having clear separation in development where everything runs off of the react server by default, but then it won’t when deploying, so either you end up doing all sorts of weird stuff or you need to be building and running production locally constantly, thus defeating the whole convenience of having a dev server that can hot reload the changes
The author of this article blog is describing some more advanced SPA-like scenarios, but those are completely optional
Though I think maybe if one is using it for a different purpose, like looking for apartments or roommates then that's probably shit.
Why not?
I run sites that serve hundreds of millions per day and we pour a ton of resources into these projects. We're trapped in a framework (react) prison of our own creation. All failures are those of complexly. Highly coupled state machines with hacked, weaved, minified, compiled, transpiled, shmanzpiled etc. into unreadable goop in production. Yes I know source maps, but only when needed, and they are yet another layer of complexity that can break - and they do. How I long for the good old days before frameworks.
Perhaps nostalgia and the principle of KISS (and a few others) is clouding my judgement here, after all, frameworks are made for a reason. But it's difficult to imagine a new engineer having any more difficulty with vanilla than learning framework after framework.
HTML was supposed to just a slight markup layer to make it easier to transit and render text documents, likewise that's all HTTP was designed for. The ratio of text-to-markup should be fairly high (I'm sure today it's less than 1). But for some reason (probably the initial ease of publishing globally) we decided that the future of application development should be to entirely reinvent GUIs to be built on top of this layer. If you look under the hood at what React is doing, we just have decades of hacks and tricks well organized to create the illusion that this is a rational way to create UIs.
Imagine a world where we decided we wanted to create applications by hacking Excel documents and Visual Basic (being from the before times, I had seen attempts at this), or have every app be a PDF file making clever use of PostScript? When one remembers how ridiculous it is to attempt to do what we have collectively done, it's not too surprising that a website can require megabytes of JS to render properly and, more importantly, to allow reasonable development processes allowing for some organization of the code base.
†I know this claim will rub some people the wrong way, but if you compare the capabilities of web tooling to build rich application UIs against desktop app tooling of even 20-30 years ago, there’s no comparison. The web is still primitive, and while JS and CSS are improving at a good pace, HTML is almost frozen in carbonite.
I also don't like the state of the web.
As someone who stepped away from web for a while and came back to it a couple of years ago, a straight React or Next.js application is so, so much nicer to work with than old-school webapps were. It feels like the web has finally been dragged kicking and screaming into a world of regular software development best practices. JS isn't the best programming language but it's a proper programming language and it does the job, I'm continually baffled that people would rather contort themselves with the sub-Turing tarpit of CSS and what have you instead of just using some libraries, writing some code, and actually solving their problems in what's usually an objectively easier and better way.
I feel the same way. React and Angular (well an earlier version of Angular) were made prior to ES2015 being mainstream, so I do think they made sense to use when they were initially created. Since then, I've become burned out from the constant churn of new frontend frameworks to learn. Even within the world of React, there's different ways of writing components, and different state managers.
But you're not wrong about there being many ways to write components and manage state.
And RSC is a mess. But thankfully you can keep pretending that doesn't exist.
To me the killer app in the modern world is reactivity, ie making views that update in response to changes in the data model. To manually create listeners and do differential updates, and manage removal and teardown of event listeners etc, is akin to doing manual memory management. We used to do that with jquery sometimes, and it’s the most error-prone thing you can do. It’s a stateful shithole.
Once they manage to find a way to modularize components in a way that is largely view-declarative, I would be happy to crawl up on the surface of vanilla JS again, but not before. It’s simply missing functionality, imo.
For a vast majority of websites out there state largely lives on the server. Reactivity is only helpful when the state reacted to is client side, and for that most sites that's only going to happen when we decide to keep a duplicate copy of state in the client rather than rendering on the back end where the state lives.
I get the desire for smooth transitions, optimistic rendering, etc. Those goals lead to endless complexity and bugs when the actual source of truth lives elsewhere.
How a site is build becomes way more simple when we stick to keeping HTML rendering where the state lives even if that means making UX tradeoffs.
Many of the 25 mentions of Shadow DOM in the Components Page and 14 mentions of it in the Styling page are about solving problems you now only have because the site recommended you use Shadow DOM, and the problem Shadow DOM itself is _trying_ to solve is one I don't have in components written specifically for my app, which will only be used in my app.
* web-component is a way to attache javascript to certain elements. There are other ways to do it, but sometime this way feel cleaner, like when you do server-side rendering and not using any javascript framework.
* shadow-dom is a way to organize your styles. As you said there are other ways to do it, but I find it useful because it offers full isolation, and is compatible with browsers 3 years back.
Noob question, but what happens behind the scenes in terms of these concepts for web components instead?
Sure you don't need bundlers and compilers (such as TS to JS), but at some point you might need async updates on `fetch()` of components that also share state with other components. At this point you're into framework territory, whether using your own or someone else's.
Producing a framework with those features that still fits in a single small size JS file would be great, especially if it can do component updates to shared state (without updating the DOM each turn, hence shadow DOM).
The former packs no dependencies, with a total size of 89.18 kB if you were to put all the module JS code together, unminified, on a single file. Which could be even smaller with an optimising bundler that tree-shakes and minifies the build.
[1]: https://www.npmjs.com/package/@tanstack/query-core [2]: https://www.npmjs.com/package/@signaldb/core
> (without updating the DOM each turn, hence shadow DOM).
Uh, Shadow DOM doesn't help with DOM performance and can make some things worse. If your Web Component has terrible DOM performance in the Shadow DOM that can still noticeably degrade DOM performance of the entire DOM.
I'm of the growing opinion that the Shadow DOM is over-complicated for what it tries to do and most Web Components don't actually need the Shadow DOM and would be better without it and would have a better idea of their own performance (issues) without it.
Hot take: The Shadow DOM is built for advertisers that want beefier iframes, not for building good performance.
IMHO everyone building for the web should understand how it works and know how to use the foundational web stack, leveraging the web platform per se. Then, by all means use a build system and your preferred frameworks at your discretion, remaining aware of tradeoffs.
For my part, one of the things I like best about Remix (/React-router v7+) is its explicit philosophical alignment with leveraging web standards and doing more by doing less (e.g. mutate server data using... the HTML form tag).
I also highly recommend https://every-layout.dev which showcases eye-opening, mind-expanding techniques for implementing performant, accessible, flexible web layouts using only browser-native CSS.
Context: I've been professionally involved with web development since 1998.
Oh and it's way worse when said framework is home-grown. They can make something totally broken, and they don't take criticism well.
some doesn't even want to make a framework, the habit and the pattern just repeated intensely and the framework just naturally created.
the way it helps someone maybe tangled you that is normal.
instead hating it, just try to understand why the framework do certain things in certain way.
They can support objects and arrays as attributes in the same way as the old Progressive Enhancement era (jQuery/Knockout-era) web: via data- attributes and the dataset property. Similar to that era you probably still want to support JSON serialization/deserialization to those attributes for SSG/SSR support.
Meiosis Pattern: https://meiosis.js.org/docs/01-introduction.html
Mithril: https://mithril.js.org/
Rendering libraries like Lit handle declarative templates, and there are many state management solutions, the same ones you can use with React, etc.
It’s not some sort of mystery, it’s just a global of your variables.
The example given clearly showed components backed by JavaScript. Which means you could implement a state management system in seconds.
But beyond that state management is overrated. I remember when react came out and somebody from face book was describing updating some pending message count number. And how they had trouble with it. The issue was they made shitty code, and the result of react was a solution that hid that shitty code. Because I bet to this day if you profile their example they still had the bug but the state management system silently hid it as a future performance problem.
No web site is intrinsically valuable - the information and functionality it wraps is what holds its value. Developing the access to that information and function, enforcing correctness, and the timeliness of that development is what frameworks empower orgs to deliver at much lower cost in the present and future, vs. vanilla web dev.
In practice, it is sometimes true, and often not.
You can't overstate how often decisions are large orgs are driven by hype, follow-the-herd, or "use popular framework X because I won't get in trouble if I do" mentalities. The added complexity of tools can easily swamp productivity gains, especially with no one tracking these effects. And despite being terrible decisions for the business, they can align with the incentives of individual decision makers and teams. So "people wouldn't do it if it wasn't a net positive" is not an argument that always holds.
My business doesn't use React anymore, and I'm so happy I don't have to do pointless maintenance.
A side note, included in my repository: you update your element's innerHtml from the constructor, not from the connectedCallback. MDN and the web standards seem to be inconsistent on this, and elsewhere people write about it, too.
People talk a lot about data and binding, etc. I think it's weird, it's like people have forgotten how to just use setters. You can call a render() method from a setter, and it does the same thing WebKit et al do when you call an internal setter on an HTML element.
I don't see the value in these frameworks anymore.
I kept on wondering while making it if I was doing it wrong without any framework. Because that's what everyone else seems to expect.
Splinter, splinter.almonit.club, if anyone cares.
I've been building many simple apps using this technique, it works fine. I'm sure there is some kind of performance hit; it's almost never an issue. I have never seen any browser compatibility issues.
> Warning: This is a security risk if the string to be inserted might contain potentially malicious content. When inserting user-supplied data you should always consider using a sanitizer library, in order to sanitize the content before it is inserted.
https://developer.mozilla.org/en-US/docs/Web/API/Element/inn...
No, generating HTML string and setting innerHTML is unsafe and slower than necessary. It is better to create DOM elements programmatically. HTML is for serialization of the DOM tree; if everything is done in javascript then you don't need HTML as an intermediate step.
Users will be able to inject cross site scripting attacks into the forms of other users.
Not saying to never sit, just saying to be aware of injection attacks on the front end.
Custom elements are very well documented and work in every browser. Get your server to render html with your own elements in them - your own "island architecture", no vercel necessary.
That some site promoting them is moribund doesn't change the fact they work - and are widely used.
I ended up using hugo + isso (for commenting) and it works very well. I moved to this setup after the wordpress drama, and even if I miss something, freedom has no price: https://gioorgi.com/2024/liberta-come-aria/
Because it was heavily pushed, advertised, and is the default way of writing web components (you have to explicitly specify mode: open)
You'll eventually need \<link> anyway for preloads, especially with web fonts, since that's the only way to prevent FOUC. Personally I lean on build steps to solve this. I don't like bundlers or frameworks, but I have grown accustomed to custom-building.
https://plainvanillaweb.com/pages/applications.html This example code does exactly one of those things: update the address bar by setting the fragment identifier. Middle clicking and back/forward buttons work because of that. Error handling (if it were to not just be static content but actually loading something from a server like a real website, which can fail) and loading indicators are not present
Re-implementing browser code in JavaScript is not using the "plain" or "vanilla" web functionality. You're making your own framework at that point
Recommend you try to start with webcomponents + a well thought out design system -> move on from there and you're pretty sure to have a solid base from which you can always add react, lit, vue or whatever else cooks your noodle.
the other way around is near impossible
From where I sit, Lit looks like one of the best ways forward. Here's an awesome design system someone built using Lit: https://nordhealth.design/
It lets you build full web UIs without touching HTML, CSS, or JavaScript, entirely in Java. The UI logic runs on the server, meaning: no API design, no JSON mapping, no Redux — just a Java object model.
Vaadin follows a true full-stack approach, where frontend and backend live in a single codebase. Combined with Spring Boot or other JVM frameworks, this creates a cohesive Java application—no complex build pipelines, no split repos, and no friction between frontend/backend roles.
What I personally enjoy most is the smooth developer experience: you see your changes reflected in the browser instantly — no manual builds, reload fiddling, or sluggish toolchains - just java and a bit of maven. For many internal business apps, it feels just as “plain” as the old-school server-rendered apps—just with modern capabilities like Web Components and security by default.
(Full disclosure: I work at Vaadin, but I’m genuinely a fan of the approach because it saves developers a lot of headaches.)
You have such a great community with big, very well thought out libraries like Tanstack Query that is pretty nice to work with. I can have backend and front end code in the same repository in a simple way and reuse code.
I also have the project in Phoenix Liveview which is also a much nicer way of using components. The thing is I don't really know which tech stack is gonna win so I made a small prototype in both to see different advantages / disadvantages.
One thing is clear tho, pretty much everything is better than using vanilla components and it's really sad because I really do want to use vanilla components and I want them to be good.
I know you’ll “write your own framework” but maybe that’s optimal in some situations - more than we might give credit to at the moment.
Notably, Web Components. They're fantastic for distributing components - after all, a Web Component will work in every framework (even React, the IE of frameworks, finally added support), or even in vanilla HTML. So you can build a component once and everybody can use it. It's fantastic.
But for internally composing a web application, Web Components are simply awful. They add nearly no helpful features that vanilla JS doesn't already have, and they add bucketloads of extra complexity. You got attributes and properties, and they're mostly the same but kinda not always and oh by the way, attributes can only be strings so good luck keeping that in sync. You got shadow DOM which is great for distribution but super restrictive if you want any sort of consistent global styling (and a total pain in devtools, especially once you go 10 levels deep). You can turn that off, of course, but you gotta know to do that. And plenty more quirks like this. It's just.. It makes lots of easy things 5x harder and 1 hard thing 1.5x easier. Totally not worth it!
If you really want to not use a big clunky framework, but at the same time you have a complex enough app that composition and encapsulation is important, you'd be much better off just making your own object hierarchy (ie without extending HTMLElement), skipping all that awkward web component luggage and solely doing what they do best (tie an object to an element).
Or, better yet, get over yourself and just use a framework that does this for you. Your future self will thank you (and your colleagues even more so).
ps. rant time: If only the web browser people had gotten off their high horse and not proposed the word "Web Components"! If they would've just been named "Custom Elements", which is what they are, then we wouldn't have had 5+ years of people mistaking them for a React competitor.
The browser people literally promoted them as a React alternative. Then their goals and role changed every year, and now they are again promoted as an alternative
Perhaps my brain has been addled by a decade of React but as the examples became more advanced, they just looked a lot noiser and more complex compared to JSX or Svelte components.
The web is supposed to degrade gracefully if you are missing browser features, up to and including images turned off.
Now, web developers give you a blank page if you don’t run a megabyte of their shitty code.
No thank you.
I agree. (This should also include CSS, TLS, cookies, and many other things; I often disable CSS, and it should work just as well if CSS is disabled just as much as if pictures or JavaScripts or cookies are disabled.)
However, there are some uses where JavaScripts may be helpful e.g. if a web page has a calculations or something like that implemented by JavaScripts; but that is not an excuse to prevent the documentation from being displayed if JavaScripts are disabled. They should really make documentation and as much other stuff to work even if JavaScripts are disabled (and, depending on what it does, may provide a description of the calculation or of the rules of the game being implemented, or a link to API documentation, or something else like that).
Pictures also might be useful in some articles (but are often overused); but even then, if the picture is not displayed you could use an external program to display them. However, if it can be explained in the text, then it should be explained in the text if possible so that even if you do not have a suitable program to display that picture (or do not want to display that picture, e.g. the file size is too big; or maybe you are using text to speech or a braille display or something else like that) then it will still work.
TLS also should not always be mandatory, either. For things that require user authentication, and for writing, it can be useful to be mandatory (especially if you are using X.509 client authentication; this will be better than using cookies or other methods for authentication, anyways); but for read-only access to public data, TLS should be optional (but the server should still allow it in case the client wants to use TLS for read-only access to public data too).
I’m not convinced it’s worth it.
If you want something à la KISS[0][0], just use Svelte/SvelteKit[1][1].
Nowadays, the primary exception I see to my point here is if your goal is to better understand what’s going on under the hood of many libraries and frameworks.
[0]: https://en.wikipedia.org/wiki/KISS_principle
[1]: https://svelte.dev
> An explainer for doing web development using only vanilla techniques. No tools, no frameworks — just HTML, CSS, and JavaScript.
You're thinking of a lightweight site, which this isn't claiming to be.
WebAssembly doesn't need to be bloated, I've written a C program that imports nothing, and the resulting WASM file is under 3KB in size, and there's under 10 lines of code to load it up.
Tinygo is also on my list to try for Wasm.
https://vorticode.github.io/solarite/
I was planning to improve performance more before announcing it. But even as is it beats React and approaches Lit.js on the JS framework benchmarks.
I tend to rely on Bootstrap so the layout is reasonable on mobile- but that's purely through my own lack of experience.
But I guess someone with a more intimate knowledge can easily get the idea of building a framework. Then add on all the use cases and feature requests...
Some web pages, particularly traditional media websites are absolute hell holes of bloat, but I guess that's more about their ad serving than lean web development.
As an example, the examples on `connectedCallback()` don't guard against the fact that this callback gets called every time the element gets inserted into the DOM tree. This could happen because you've removed it to hide it and then added it later to show it again, or it could happen because you've moved it to a new location in the tree (different parent, or re-ordering with respect to its siblings). Or maybe you're not manipulating this object at all! Maybe someone else is moving around a parent element of your custom element. Whatever the case, if you're element's ancestor path in any way gets disconnected and then reconnected from `documentElement`, `connectedCallback()` gets called again.
That means that you have to spend extra effort to make sure anything you do in `connectedCallback()` either gets completely undone in `disconnectedCallback()`, or has some way of checking to make sure it doesn't redo work that has already been done.
There are some other pitfalls involving attributes, child elements, styling, behavior with bundling, etc., that they never really get into. And generally speaking, you're probably only going to find out about them from experience. I don't think I've seen anywhere that goes into Web Component best practices.
Which is a shame, because they are incredibly powerful and I enjoy using them quite a bit. Now that my company has decided to go all in on React, I think they've only really seen the beginner path on both. Web Components as a beginner look harder than React as a beginner. Once you start actually building apps, I find they actually end up having to do largely the same level of manual shenanigans. But I find that I'm doing manual shenanigans to work around React, whereas with Web Components there isn't any magic to work around, but there also isn't a lot of "help" that you'd end up ignoring in most cases anyway.
More importantly, the needs of the site are drop-dead simple so no need to install a Ferrari when all I need is a bicycle.
Plain vanilla site served from Github FTW!
/s
The boilerplate, the innerHTML strings, the long list of caveats, the extra code to make basic things like forms work, manually attaching styles etc. etc.
My main gripe with web components is that while they expose the first half of the tree traversal (from the outside in, via connectedCallback), they don't provide access to the second half, after child elements have been created. (akin to Initialize and Load events from ye olde .NET)
1. Get the desired node.
2. Write the content.
That is it. The corresponding code is two lines.
But but but... what about state? State is an entirely unrelated issue from writing content. State is also simple though. State is raw MVC plus storage. The way I do it is to have a single state object, the model. I update that model as necessary on user and/or network interaction, the view. When the page loads I read from the state object and then execute the corresponding changes using the same event handlers that would normally execute in response to the user interactions that wrote the state changes in the first place, which is the control.
That is simple, but many people find that simple is not easy.
At first, I learned and use plain HTML/CSS/PHP and I thought that was good. At college, they taught .NET framework and for some years, that was my go to techstack. Then I started to learn about more languages and frameworks. At some point, it's hard to switch between them
Now I stick with one thing, unless that platform doesn't support it. This also allow me to be a lot more productive since I know most of the thing needed to be done
Sure I can start with vanilla web, or some new framework but it'll take a lot more of time and just not worth it
I'm sitting on two UIs at work that nobody can really do anything with, because the cutting-edge, mainstream-acceptable frameworks at the time they are built in are now deprecated, very difficult to even reconstruct with all the library motion, and as a result, effectively frozen because we can't practically tweak them without someone dedicating a week just to put all the pieces back together enough to rebuild the system... and then that week of work has to largely be done again in a year if we have to tweak it again.
Meanwhile the little website I wrote with just vanilla HTML, CSS, & JS is chugging along, and we can and have pushed in the occasional tweak to it without it blowing up the world or requiring someone to spend a week reconstructing some weird specific environment.
I'm actually not against web frameworks in the general sense, but they do need to pull their weight and I think a lot of people underestimate their long-term expense for a lot of sites. Doing a little bit of JS to run a couple of "fetch" commands is not that difficult. It is true that if you start building a large enough site that you will eventually reconstruct your own framework out of necessity, and it'll be inferior to React, but there's a lot of sites under that "large enough" threshold.
Perhaps the best way to think about it is that this is the "standard library" framework that ships in the browsers, and it's worth knowing about it so that you can analyze when it is sufficient for your needs. Because if it is sufficient, it has a lot of advantages to it. If it isn't, then by all means go and get something else... again, I'm definitely not in the camp of "frameworks have no utility". But this should always be part of your analysis because of its unique benefits it has that no other framework has, like its 0KB initial overhead and generally unbeatable performance (because all the other frameworks are built on top of this one).
The benchmarks I've seen actually show web components being slightly slower than the best frameworks/libraries.
The idea is: no build steps initially, minimal build steps later on, no dealing with a constant stream of CVEs in transitive dependencies, no slow down in CI/CD, much more readable stack traces and profiling graphs when investigating errors and performance, no massive node_modules folder, etc. Massive worlds of complexity and security holes and stupid janky bullshit all gone. This will probably also be easier to serve as part of the backend API and not require a separate container/app/service just running node.js and can probably just be served as static content, or at least the lack of Node build steps should make that more feasible.
It's a tradeoff some people want to make and others don't. There isn't a right and wrong answer.
Cognitive burden is relevant to 100% of web apps.
When frameworks are used for that 99% of web apps for which they are overkill, performance actually drops.
> frameworks seem to be the lingua franca for a reason
Sure, but theres no evidence that the reason is what you think it is.
The reason could just be "legacy", ie. " this is the way we have always done it".
I've seen this play out repeatedly. A company needs a basic CRUD system. Consultancy A brings in designers who produce “wireframes” (usually full-featured eye candy) and UX-centric “journeys.” To justify its bloated fees, the consultancy builds something super-slick using frameworks to match the designs. But once the budget runs out, the customer struggles to maintain it. Eventually, the app becomes unmanageable.
So the consultancy sends in a designer again to produce new mockups and “journeys.” The cycle repeats, this time with another framework.
20 lines of anonymous function calling gibberish is so unpalatable.
It's hard to understand what is actual application code in these stacks.
For me it's mostly about de-tooling your project.
For example - I have a fairly complex app, at least for a side project, but so far I managed to keep everything without a single external dependecy nor any build tool. Now I have to convert it all to react and I'm not very happy about that, I will have to add a ton of tooling, and what's most important for me, I won't be able to make any changes without deploying the tooling beforehand.
React is the new Java.
But when you need something the framework can't provide, good luck. Yes, high performance is typically one of those things. But a well engineered design is almost always another, costing maintainability and flexibility.
This is why you almost always see frameworks slow to a crawl at a certain point in terms of fixing bugs, adding features, or improving performance. I'd guess React did this around like 2019 or so.
The site positions itself as advocating for simplicity and minimalism in web development—stressing plain HTML, CSS, and JavaScript—but then pivots into building the entire project using React. That’s a contradiction.
If the goal is truly "plain vanilla web," introducing React (with its build tools, dependencies, and abstraction layers) runs counter to that ethos. A truly minimalist approach would skip frameworks entirely or at most use small, native JS modules.
So yes, it's philosophically inconsistent. Want to dig into a better alternative stack that sticks to that principle?
No regrets, except I found myself also building a framework....
The main reason is I want direct control of the DOM and despite having 10 years or more react experience, it is too frustrating to deal with the react abstractions when you want direct dom control.
The interesting thing is that it’s the LLM/AI that makes this possible for me. LLMs are incredibly good at plain JavaScript.
With an LLM as capable as Gemini you rarely even need libraries - whatever your goal the LLM can often directly implement it for you, so you end up with few of no dependencies.
Also, at the beginning of the first chapter, I read:
> In theory it's possible to extend other classes.. but in practice this doesn't work yet in Safari.
And was like, Ugh! It's always Safari that ruins the party!
https://plainvanillaweb.com/pages/applications.html
Also, "the hash-based routing approach is effectively invisible to search engines."
The problem I found is that my full-SSR project doesn't use any Node.js at all, and it works fine for everything but CSS, because in order to use includes and variables I need a CSS compiler.
For example, I use a CSS library that defines a very nice style class "alib-link" for all links. I would want to set it for all <a> elements, without adding `class="alib-link"` all the time. It's easy with a CSS-preprocrssor, but how to avoid using one?
a {
/* the code from the alib-link class */
}
If you need to style anchor links depending on where they point to, you could use an attribute selector: a[href*="news.ycombinator.com"] {
/* more css */
}
No preprocessing necessary.Problems of FAANG are not our problems, yet they've somehow convinced majority of software architects that complexity is good.
My only concern is when I use HTMX/Hyperscript in my FOSS projects will others be comfortable contributing to it even though it has very little learning curve but they have to empty their React cup.
[0] https://ciechanow.ski/ [1] https://ciechanow.ski/js/watch.js
One recommendation is to change the mental model here. In my eyes it isn’t “don’t use a framework”, it’s “build the framework you need”. It’s tremendously easy to set up an extension of HTMLElement that has 90% of the functionality you’d want out of react. My SPA non.io is built like this - one master component that has class functions I want, and one script for generic functions.
The last 10%, OTOH...
Although I do think there is merit to "light" frameworks such as Astro, with its scoped styling and better component syntax. But at the same time, independence is also important.
I started something similar with https://webdev.bryanhogan.com/ which focuses on writing good and scalable HTML and CSS.
#include "header.htm"
<h1>Title</h1>
...
#include "footer.htm"
I'm still using it, and I wonder when I'll be able to get rid of PHP.One can imagine a cross-compiler so you could write React, but have it compiled to React-free javascript - leaving no React dependency in production.
Would be a lift, but looks superficially possible.
What are the blockers to this?
That in itself undermines a lot of the author's message, as they were not able to reasonably de-framework themselves.
(And - it's not hard to get the navbar right, in any number of ways. But you do have to do a bit of work before you preach things to others.)
Interesting. Why do web components have this effect, but some JS frameworks apparently do not? Or do they all?
if (!this.#span)
What is that kind of magic syntax sugar?! A shorthand for document.getElementById?https://go.rt.ht has other custom elements!
The page https://plainvanillaweb.com/pages/sites.html uses custom components for all code examples and embedded content. Without JavaScript, it merely shows "enable scripting to view ../XYZ.html" in place of all code examples and demos. Better than having no fallback at all, I suppose, yet still not "navigable".
The fact that it does not even bother to build these custom components on any native element with a similar purpose—like, say, a link that users could follow to see the text document (*), or a plain old iframe (**)—is grim.
Web components are indeed useful for prototyping and personal testing, but are they really beyond the threshold where it is safe to serve them in the wild, potentially harming some users?
(*) I know, view-source: links and embeds are sadly blocked by browsers nowadays. Makes very little sense to me. Someone likely managed to exploit it for some nasty purposes, so now we are "protected", I suppose.
(**) See? In the olden days even iframes were said to have a link fallback inside, for user agents that did not support them.
Now, this particular website is indeed a proper website, and so it shouldn't need JS to do its thing. But it's also a website that advocates for a certain way of developing web apps (even if they don't use such terminology themselves), and as such, is essentially a demo for the same.
I'd like to use lit-html but Jetbrains does not support it - very annoying.
All the framework abstractions we made for humans coding productivity will need to be re-visited! I support plain vanilla web for this reason.
Sites are way too bloated nowadays, a lot of the content being served can be static and cached.
Looking forward to playing around with some personal projects. :)
Yeah I don't need your shitty onclick hijacks. Thanks.
The static websites and beautiful designs
With a lot of iframes and widgets, running some kind of services like Disqus chatrooms were
It’s far more secure, too.
Maybe it's time for me to crawl out of my systems-software-only hole and play around with the web again.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Anything more is for the kids on my lawn.