The task was to build an offline capable site which displayed the latest Hacker News posts, and loaded more lazily when scrolling.
I had to use the official HN API, and I couldn't have any middleware or caching. Everything had to be done client-side.
The app ended up being 1.4kb in total, with support for practically streaming in the items, batching them by network response times and render frames, while keeping the order.
There's an irony about posting in a topic about simple, vanilla, no-framework scripting and then linking to a repository with the following unnecessary ancillary files:
Plus the actual source code is spread over four TypeScript files, JavaScript, CSS, and HTML.
This isn't meant as criticism of your code specifically but of "modern" web development which hypocritically espouses simplicity but actually increases complexity of development.
My point is your app could have been a single HTML file (or HTML, JavaScript, and CSS if you want to split hairs). Instead there's 15+ files because that's the state of modern development.
I really don't like posting in this passive-aggressive quote-answer format, but I feel that I need to address each point specifically.
> no-framework scripting
This isn't a script. It's a project for a mini app.
> My point is your app could have been a single HTML file (or HTML, JavaScript, and CSS if you want to split hairs)
The app has no bundled deps and no framework.
I actually just went on CodeSandbox, started a vanilla TS project (could've just as easily be JS + jsdoc since both CodeSandbox and VScode are using Monaco, but why would I?). 2 clicks. It uses parcel but I could've just used vanilla JS imports. That's what a few of the other artifacts are from.
Lastly, the app was built as a monolith initially and then I split out a few things to make it more readable.
> .gitignore
bruh.
> README.md
BRUH.
> REQUIREMENTS.md
It's there for the people who need more context
> manifest.webmanifest
It needs offline support. That's how the platform works. Same goes for sw.js
You're being a bit dishonest and writing in bad faith. If you work in web development, you know that the times of inline JS and styles in an HTML file, uploaded via FTP to a LAMP server are long gone. Like, 10+ years gone. If you are still romanticizing that, you may have an advanced case of Old Guard™.
If you are a non-web developer, then I hope you don't apply the same reasoning in your everyday work, for your colleagues' sakes.
Right, OP totally should have included the interview question requirements as a commented block at the top of index.html instead of separating it out. It's way too complex as is.
And definitely, .gitignore is well known to be responsible for the "complexity of web development." Maybe we should include .gitignore in index.html too?
That's nice. I myself did try out one too, as a hobby project to serve as an alternative frontend for a local gym https://varjosport.net/ There's a small flicker as the app generates the HTML which still annoys me but I couldn't bother to write a Lambda to server-side render the HTML every time the data is refreshed.
One thing I noticed though was that creating HTML fragments is a major pain in the ass, which I see you've solved with .createContextualFragment Interesting, I might have to try that one out too.
I myself quite immediately after starting to parse my JSON payload and turning it into dynamic HTML elements turned to Preact, which I guess as a lesser version of React is an acceptable choice. One thing which still was left to irk me were the CSS classes. I'm not a big fan of writing them anymore, with BEM syntax or not. Styled Components in my opinion is the future of writing modular React/web components. But since I vowed to myself to keep this simple, I stuck with CSS.
But it's indeed an interesting project to create a minimal modern website without the massive toolings/libraries you normally take for granted with React etc. There's a lesson there to be learnt in how sometimes that complexity is unnecessary, but sadly it's often not in the scope of a project to start optimizing such things. And I can't blame them, since when things get complicated you much rather have your app already written in React than having to rewrite it from custom JS/TS mess.
With styles in components, can you support skinnable components? If so, do you have to accept parameters in the component and modify the component every time you want to change some style to make it fit with your page look and feel?
If you mean theming components, then yes. Skinnable components is not a term I've encountered before but theming is something SC enables and is part of its core functionality. You can either use something like a global theme variable to set styles, which each component can depend on or just the regular props for different styles eg <Button intent="success />
I myself have mostly just remained with a one default theme, although adding a dark-theme has crossed my mind several times. It's just that UI features like this are rarely on top of the to-do list.
That's a nice, clean, simple approach - I learned about `createContextualFragment()`, so thanks!
I wanted to ask, did the company you were interviewing for tell you what they wanted to get out of the assignment on their end - specifically what they were assessing you on?
Thanks! I really appreciate that!
I think I can post the evaluation criteria:
1) App performance. We will be looking at the wait times for reader to see the content — the shorter, the better.
2) We will evaluate your code’s quality. Does your code have good modular design and testability? Is it easy to read?
3) We prefer the project to be lightweight, and all dependencies should be well justified.
I was focusing on #1 and #3. As for #2, they found it too tightly coupled and hard to read.
I thought that the app is simple enough to not warrant extracting modules in the main app logic. The coupling was also there for performance / filesize reasons.
Too tightly coupled? Fuck me. I'd have given them a single .js file. There's a point where decoupling everything is just a complete waste of time. Sounds like the company was run by idealistic developers who have never had to work under real-world deadlines.
Your comment makes me imagine a more nuanced technical interview process - i.e you get to provide feedback to criticisms from the interviewer, you get to escalate/request review from someone else at the employer if you disagree with the interviewer. A platform ensures that the protocols are abided by by both employer and candidate.
These sorts of interactions sound pretty far out now, but a few years ago who would have thought that people would be typing code into a web page in real time as part of a job interview process?
> Sadly, I didn't get a chance to provide feedback to the criticisms
That's a shame. It sounds like the criteria were fairly well defined, but it would be nice if your assignment was used as a starting point for good in person discussion. E.g. "we think the code in index.js was too coupled - what could we do to break that out?"
I distrust any interview that includes something like this.
It's an arbitrary construct that is not indicative of what form the work will take. Only the first three months of working with someone will give any real indication of what'll be like to work with them for another three+ years.
> It's an arbitrary construct that is not indicative of what form the work will take.
Agreed.
I had a similar code challenge and after joining the company, in the first year of work I did little if any JS work which even approached the level of the challenge I was presented with. To this day, I'm still bitter the company gave me the old "bait and switch" tactic to get me to come work there.
Yeah we created a test for our interview but we give it onsite I think requiring people to do work even if its compensated is wrong, its not that hard to put together a small exam based on the source for your projects to analyze whether a candidate can handle the work.
I have had this issue as well with take home projects. Most companies are looking for someone who will follow KISS, so demonstrating ability to do complex things like your render queue is not at all appreciated. They want to see that you can match a spec and write well-factored code.
Adding complexity for performance will be a pure negative unless you can factor that out so the next person can use it on their component.
I would read this code and think I was dealing with a very talented programmer that needs seasoning. Such a programmer can be very dangerous to the wrong company, as the seasoning will have to be added on the company’s dime.
Works here on Firefox Dev. Try refreshing, there was a bug I missed with the api returning 200 for a post, but the content was `null`. Fixed it, but you still might have the old cached JS due to the service workers.
They could also have been articles, probably also better for a11y.
The browser's implementation of numbering ol's is to align them to the right and render them hanging. They don't impact the layout, much like position: absolute, and they grow to the left.
The default ol/ul behaviour leaves some space to the left where the bullets/numbers should fit. This means you need to take into account the maximum width of the number.
I had no idea how much is the limit of the API, could have been thousands of items, and I didn't want to leave space for four digits until you scroll down to item #1234
I could also have implemented this using CSS `counter-increment` and `content`, but this was a better approach for debugging if the articles were rendering in the right order, while the CSS approach only takes into consideration the amount of DOM nodes.
I'm so glad to see this and projects like this getting attention. I'm responsible for several tools at my current job using nothing but straight JS, including a couple which have had a significant (positive) impact on the special projects team here.
I love JS. I love it's ubiquity (F12 in any browser and you've got a REPL). I love the freedom I have when I write in it to do whatever the fuck I want and shoot myself in the foot in all sorts of strange ways. It's a very expressive language that lends itself to all sorts of fun. I love being able to inline C functions as WASM. I love manually managing memory with typed arrays. I love the filth of it all. It's liberating to give up all your dignity and just fling mud with a big grin on your face because your ridiculous 5 lines are a functional standin for a templating engine.
let applyTemplate = template => object => {
let keys = Object.keys(object)
return new Function('input' , `let {${keys.join(',')}} = input
return \`${template}\``)(object)
}
> Use of the with statement is not recommended, as it may be the source of confusing bugs and compatibility issues. See the "Ambiguity Contra" paragraph in the "Description" section below for details.
It creates a function returning a function, where the argument to the first (which is a template) is used as a closure in the second (which takes a dict of values).
The last function called in turn creates a function using the Function constructor, which, since it takes a string argument as the function body, allows the expansion of the values dict into variables and thus the population of the template string:
It's not my code :) However, tagged template literals won't allow dict expansion the way this solution does. Also, a template literal is evaluated at the time of assignment. This will allow you to re-use an arbitrary template string with any matching values:
Soundslice (https://www.soundslice.com/) — a website built around interactive/responsive sheet music, rendering the music entirely in client-side JS — doesn't use JavaScript frameworks or libraries.
I'm the developer of Soundslice and continue to be happy with the vanilla JS decision, 8+ years into the company. It means better performance, clearer code, smaller JS filesizes.
Amazing site. I noticed one thing that could easily improve the feel of the site — the sheet music playhead which is outside of the canvas.
You are using fractional units to position it, but you're also using left/top/height properties which can't be fractional.
If you convert these to GPU translated layers via translate, you'll get a smoother playhead since these can be positioned fractionally, plus you'll cut down on the repaints!
It's a firefox bug. I needed to add a very fine rotation for it to render subpixel, so you can try again. You can also see the repaints if you open up the dev tools: https://i.imgur.com/A8btxpu.png
Lately I've really enjoyed writing small apps in vanilla TypeScript. Since the TS compiler generates JavaScript that works in modern browsers and those also support the module syntax natively, you can get away without using NPM and a bundler like Webpack at all. Of course this starts to fall down when you get over a certain size but it works well and is quick to get going with for simple things like this lunch menu I built: https://gitlab.com/Nicd/sodexo-menu
The only gripe I have there is that you need to write imports with a JS extension as the TS compiler won't change them. So to import `foo.ts`, you need to write `"./foo.js"`. The compiler understands it and it also allows the browser to understand it too.
Too bad we can’t have php style autoloading in JS.
Actually what I really want is to lazy-load modules on demand! So if something is concatenated into a giant file then I don’t need to load modules anymore.
Like maybe this:
function load(module) {
if (load.loaded[module]) return;
import(module)
.then(() => load.loaded[module] = true);
}
I actually don't see why someone couldn't write a PHP style autoloader for JS, there is already a lot of cool hacks around require. I think a simple autoloader would just do something like (almost pseudocode):
It qas a few montgs since I used it, bit it wprks basically exactly like you want, only ghat the "is loaded" check isn't needed, the module is global and may even be a singleton.
Following node but just async. It’s simple and it works. We were able to know the name of the latest loaded js file in exports() by a trick of throwing an exception and catching it to see what script was on the top of the stack. All browsers seem to support this.
Since it worked back then, we didn’t need anything else. It is super simple to just keep using those things and replace the middleware underneath to whatever is the standard du jour.
It's super short and simple, you can implement similar things in your projects:
I feel the analogy is more like: You need to fix a single brick so you buy 72 pallets of bricks, buy a fork lift, 5 cement trucks, buy a garage to park them, try to acquire at least 2 cement factories, hire 4 people to do logistics, someone to do HR, 12 truck drivers and 4 fork lift chauffeurs. Placing the brick is outsourced.
I ran into a 13 year old master glue coder on irc one time. Since he was 9 he touched/used 3 js/php frameworks/modules/libraries per day. He said he didn't know any programming. (not entirely true ofc) He knew how to ask for something. There was always someone willing to write the data transformation after he broke down the problem properly. He showed a bunch of hilarious things he made. I praised him for keeping all of his projects. He said it was to embarrassing and deleted pretty much everything. I ask him things like, what do you do when things don't work, they stop working or stuff gets really slow. His solution was to delete everything and start from scratch using different modules where possible or just delete the project. I learn from him that the glue-ables are for the most part not high level enough. I wish I had learned to just delete everything and start over, regularly, just like that. ha-ha
There’s no need for these projects to be “mini”. Javascript and html is a good choice for big things too. It’s still my go to “frontend stack” for lots of stuff today.
Here’s a pretty big “VanillaJS” project I built back in 2006, back when we called these things web apps:
I love these type of showcases. It‘s been a wonderful time when simply upload files via SFTP and had a running application. No need of webpack bundles, vendor libraries to achieve a simple functionality that could be solved in a few lines of code ...
I really do hope this kind of developer attitude (writing pure VanillaJS) is coming back.
There's a reason why a lot of those libraries and tools are used though. Webpack bundles are used to strip down multiple JS files and libraries into a single bundle that contains only what is needed to run a particular application. Libraries like React serve a purpose too, particularly when you're building large applications that need to be maintained by many people all at once, or when you need insane compatibility (e.g. IE 11, the old Edge, etc.)
Is there a need for these tools all the time? No. But are there valid use cases? Absolutely yes.
Right, its so funny! This is why I cant/wont/refuse to find a job of this type. I can write JS just fine. In employment I would have to glue bloated libraries (which takes me forever!) and then wait for tools to purge the unwanted garbage from the creation. The end result is slow and I feel clueless what is actually going on. Of course this also means I'm impossible to work with which only adds to the joke.
Yeah it’s really frustrating. My metric of the moment is total NPM package count that comprises a project. Since Angular, out of the box, is greater than 1100 packages I ignore all job postings that mention Angular. I am extremely hesitant whenever I see things like Webpack or Babel.
Until we rediscover that manually keeping the DOM up-to-date is tedious and error prone for almost any project and switch to a good middle ground such as Preact or React without a build step
It’s not that tedious. Learning to do it properly takes less effort than learning a major framework. You would actually have to do it and learn it for this to make any sense though.
I tried both approaches on a recent project and in my experience it gets tedious once my application (and with it, its rendering logic) got more complicated. Manually juggling around listeners and mutable state all over the place just leaves a lot of room for error. (As opposed to leaving all that to some DOM reconciler that I don't have to, essentially, implement myself for every problem.)
Initially learning a new paradigm (declarative over imperative in this case) is hard, of course, but it can be worthwhile. Whatever works for you though.
> I really do hope this kind of developer attitude (writing pure VanillaJS) is coming back.
If it's coming, it's coming for the first time.
Way back in the first decade of this century, when JavaScript was first transitioning from a language you wanted to learn as little of as possible to a language you might actually want to learn, jQuery sprang up as a way to deal with browser incompatibilities. I went to a jQuery conference where people were advised to really learn JavaScript and use it where possible, not always relying on jQuery. I don't think that advice was widely heeded.
React took over from jQuery and has the same problem. People learn the library first and slowly pick up the language, hopefully, as time goes on.
I hope not, convincing people to adhere to coding standard where I can tell "this is angular way, please do so" or "google does that" is so much easier than actually convincing herd of cats to "here we have modules, please put your code in a module, not inline because that is the way we do here". I do not care about standard it could be any other framework, just have it consistent, please.
I hope so too, but it’s not. In all my observations things are moving in the opposite direction at all possible speed. It appears (personal opinion) that this has nothing to do with technology. It’s more about perceptions and behaviors.
Some Javascript frameworks I like; some I tolerate. Some (<cough>angular</cough>) I learned to despise.
I reserve my love only for VanillaJS.
My library for playing with the canvas element[1] is entirely VanillaJS. 0% dependencies. 1000% a learning experience for me, having to seek into the darkest corners of the language to find solutions to problems I didn't even know existed!
I wish more NPM modules were vanilla JS; then it wouldn't be quite so hellish to audit your dependencies or vendor them.
I needed a lib to measure text for layout recently, and ran across https://github.com/soulwire/FontMetrics which is nice and clean and completely self contained. It's a perfect library.
Yep, I wish either nmpjs.com or npms.io would list the total number of transitive dependencies in their search so I could sort by it.
npmjs.com shows the number of dependencies at the top but doesn't total in dev-dependencies unless you dive in further. At first glance, npmjs.com leads you to believe webpack has only 24 dependencies when they have 52 additional dev dependencies leading to ~300 transitive deps with ~200 maintainers I now have to either constantly audit or implicitly trust[0]
I did a project around 2018 if I remember correctly where I did all of the code in inlined vanilla JS. It was simply firing off timed API calls for a pop quiz but it was resilient up to the point where a page reload would simply continue where the last question left off. Maybe 300 lines of code, max. Literally anybody that had to work on it kept asking why I didn't at least use jQuery or another flavor of the month framework.
"Can you point out in this code where using a framework is necessary?"
Never got an answer to that, still people were so nervous about the lack of JS frameworks.
Interesting. As a developer who's done no front end work since the nineties and has had little appetite for getting back into it (after having seen what modern front end devs seem to contend with) I surmise that all those crap.js frameworks of the month don't do a whole lot of useful stuf after all.
I suspected as much but was always too timid to speak up when I observed how much noise and fury in the office produced so little UI.
I always find it interesting that the people who unabashedly admit they have minimal front-end experience usually have the strongest condemnation of the current tools.
Most of them are merely abstraction layers for capabilities the browsers already provide. Rarely do they offer anything more. The big selling point is that they help organize the logic in a declarative way or automate a bunch of tiresome tasks that wouldn’t be there in the first place had you not used a mountain of tooling.
There are only 2 APIs in the browser: DOM and the web APIs. As far as writing cohesive logic that does wonderful things that’s on you. Most JS developers would rather it not be on them and instead adopt an Invented Here Syndrome mentality. The fear of writing any original code is very real.
It's more understandable if you think about it the other way around: people who don't like the current front-end tools usually try to avoid contact with them. Which these days, mostly means not doing professional front-end development.
I've built UI's with Qt, Gtk, swing, VBA, Access, winforms, WPF, TK, html/css and more I can't remember and I stay away from front end webdev these days because the tools are such a tyre fire and way less productive than what we were using > 20 years ago.
I find the people that like most of the current tooling grew up with it, don't know any better and don't want to learn.
These aren't web-native so I don't think the comparison is particularly salient. Building on the web is a business requirement, all the tools are to make that requirement manageable.
You can do quite a fair bit with vanilla JS, HTML, and CSS.
Things get a little tricky when you start having to maintain a lot of state that multiple elements need to be aware of.
It's not impossible to do this with vanilla JS, but the mental model can be a bit difficult and this gets amplified across teams.
What crap.js frameworks do well is provide a contract for how state can be organized and how components should react/interact with the change in state. This scales well across teams as following a set of mutually agreed upon conventions produces more legible code instead of an entire team rolling their own code for everything.
Thanks for stating this so succinctly. This is a vanilla JS thread, but the "frameworks are crap" groupthink is also getting a bit out of hand. If you are building complex dashboards where multiple components are sharing and updating state, using a declarative framework like React or Vue and state management like Redux keeps things manageable as requirements change.
When you start tracking state in the DOM, you start having to be very imperative on what gets updated as state changes.
For example, if you have a search application and you want to paginate results, you can get pretty far with vanilla js, but you have to evoke changes based on events which is hard to scale beyond one person rolling their own code.
This is a lot nicer with frameworks because you can be less explicit on which elements get updated and rather describe changes in state with elements "subscribing" to these state changes. Furthermore, these frameworks have conventions to follow that makes things consistent which is nice for teams.
I tend to use jQuery for things that require basic JS interactions, but when there are things that require very scoped JS state with a complex set of interactions, I will defer to Vue.js.
When I was working for the USGS I was tasked with making a stream tracer to help the national park service fight oil spills at mammoth cave. However I wasn’t allowed to write any server code due to security issues so I wrote the whole algorithm in javascript. It would take about 1 min to parse all the geojson streams into what what I called a node array which contained all the nodes containing the info of where streams connect and which stream they either flow downwards or upwards into. I eventually learned how to use node.js to allow me to run the node processor on the computer and then to just load the output files into the algorithm to allow the website to bypass this processing. I made a big push to try and open source my algorithm (minus all the confidential data the project had), however the website doesn’t have all the fancy controls that I created for the real project as I was hired by another company fairly quickly once I started applying around with this and a d3.js choropleth under my belt as my 2 first professional projects.
It's open source so feel free to rip the code from there, or just use the full Q.js !
For loading code, a long time ago we just implemented two methods:
Q.exports(a, b, c)
Q.require(src, callback)
Following node but just async. It’s simple and it works. We were able to know the name of the latest loaded js file in exports() by a trick of throwing an exception and catching it to see what script was on the top of the stack. All browsers seem to support this.
Since it worked back then, we didn’t need anything else. It is super simple to just keep using those things and replace the middleware underneath to whatever is the standard du jour.
It's super short and simple, you can implement similar things in your projects:
so happy to see brad and traversy media get some attention on hacker news. been watching his youtube channel for a long time and learned so much from him.
I agree, I'm glad to see him on HN. Brad is great for beginners, and I still use him for my "how to I get some boilerplate up and running" type things for languages and frameworks I'm not familiar with.
Cool! I've build a couple of vanilla js projects, a widget and a framework.
https://github.com/naikus/svg-gauge
This one is all in one widget completely in vanilla js. Zero deps. An interesting thing is there is an angular-js wrapper that someone else built on top of this.
This one is actually a view lifecycle management framework for simple SPAs and mobile web apps
https://naikus.github.io/stage/ (This site is actually built using the stage)
Quick / dumb question : in the breakout game example (https://github.com/bradtraversy/vanillawebprojects/blob/mast...) wouldn't the game feel fast/slow depending on the power of your computer since the physics loop does not make use of the elapsed time between updates ?
The function `requestAnimationFrame(update)` on line 191 [1], typically updates at 60 frames per second [2]. When it fires, it re-calls the `update()` function starting on line 184 [3].
As you say though, it's not 100% reliable in terms of speed, but I imagine 90%+ who play the game get a good experience.
True when using a normal monitor, but could be a problem if using a 120Hz monitor or if the previous call didn't finish fast enough. The best is to use the timestamp requestAnimationFrame sends in to the callback to find time-delta since last call
>> The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation.
Yeah I think it typically only gets slower, not faster. But it's a good point - if you're going to run your physics loop in the update loop (not ideal) then your movements should be time based.
Physics and game logic should always run at fixed intervals and not depend on the time available. Otherwise you may run into oscillations that can be observed e.g. in games with ragdoll physics where bodies suddenly start to twitch due to such glitches. Thus, physics and logic should run at a fixed rate (e.g. 120 Hz) while graphics can run at whatever speed the machine can manage.
This is good for practice and learning but honestly what is the point of going backwards. Some of these demos don’t even work on safari in mobile. Frameworks are there for a reason. If one must learn in plain ja then sure go for it but no point knocking down frameworka
Most of these didn't work on Firefox either or fail gracefully, so no cross-browser support. I'd say that the more "stuff" you need to do on a web app, the more likely those features will need to be cross-browser compatible, and having done that in the past, I can say that VanillaJS is a fine thing for simple straightforward web apps, but when you start needing more features, it can be a load-off to outsource it to a framework.
If you understand what the framework is doing, used sparingly, some frameworks can save you some time. JS libraries have the same deal, there are some features that I would prefer not rewrite every time I write an app. For instance, PDF.js is quite indispensable at reading PDFs in the browser and I think someone would spend quite a bit of time re-writing all the features you need from that library.
Anyways, I guess it just all comes down to using the right tool for the job.
Right now I am working with a React app that is even more striking - how little it does with so much code. Though I am starting to see the trick. Keep making wrappers that only reference other wrappers.
I normally do iOS development and have been building a few fun sites in the last few years and because I'm not familiar with web front-end frameworks and tooling, all the stuff I've done[1] is done in vanilla javascript. I've found it pretty easy to build things just using it alone, although my apps are just mini projects.
A few years ago my work environment became so complex that I felt like I was spending more time trying to code, than actually coding. So I started that thing where on Sunday mornings, I would give myself a couple hours, in bed, to code something simple in vanilla js.
I love seeing vanilla JS projects getting some love. I started one last year (https://github.com/CarlMungazi/aprender-js) and I feel it has made me a better programmer.
If anyone wants to learn more vanilla JS stuff, you should check out https://gomakethings.com by Chris Ferdinandi.
I love vanilla/minimal js frontends, but I don't think this is a prime example. The basic function of it could basically be a math function, and it does not not include any accessibility features, and if smallness is what you prioritize it could be smaller by using the form API's more, especially for things like radiobuttons (for example, a selected radio value for `units` can be found with `form.units.value`, the same can be done for other inputs).
My point is mostly: do vanillajs but also understand what api's are actually available for you from the start. There is a lot built into the browser, use it. Usually it already has better performance and accessibility than whatever you would write yourself.
I have recently experimented with writing dependency-free JS. I ended up using Webpack and Babel, but no frameworks or libraries, and I find it quite nice to work with. These are my tips for making the best of it: https://magnushoff.com/blog/dependency-free-javascript/
I'm not sure if this qualifies as "mini", but mi chiptune/MIDI player [1] was written without the use of any big frameworks, even though it relies heavily on Javascript, both for navigation, visuals, and of course audio synthesis (via Emscripten).
It's not VanillaJS but it feels like it https://github.com/alpinejs/alpine/ I have been using alpinejs and is really easy to start and complete! something that is difficult to have together.
I'm making an open source .NET Core CMS where the UI is written in non-transpiled ES6 run natively in the browser - including imports through Javascript modules
Cool 3 letter names. Reminds me of the commands in Bloomberg Terminal/some old HCI. I really like how you've built a whole stack of custom tech there.
That's my aim too. My work is all Vanilla. I hate to use external frameworks and libraries in the browser, but love to use stuff on npm. I prefer to write something I like to use, rather than use something that exists that I don't like working with.
I just finished coding a few functions in pure Javascript I need for a project (parsing turtle files I have ownership one). After searching for libraries and having read their Github project's Readme, I choose to implement them by myself because making them working in browser (most target Node) and understanding their API would have take longer than doing it myself anyway. The front-end tooling has became a huge mess of tools (none of which I have experience with) so I always keep it to vanilla JS (or TS) to progress on my project instead of learning a tool that might not exists in 3 or 5 years.
You can see it in action here: https://hn-scroll.netlify.com/
The task was to build an offline capable site which displayed the latest Hacker News posts, and loaded more lazily when scrolling. I had to use the official HN API, and I couldn't have any middleware or caching. Everything had to be done client-side.
The app ended up being 1.4kb in total, with support for practically streaming in the items, batching them by network response times and render frames, while keeping the order.
You can see the batched items in this version: https://codesandbox.io/s/hardcore-stonebraker-8m8fx