BOM[12:00 AM]
PROFESSIONAL SOFTWARE ENGINEER
FOCUS ON WEB DESIGN AND DEVELOPMENT
● AVAILABLE FOR WORK
NYC[12:00 AM]
ARYAN KATHAWALE
SOFTWARE ENGINEER / DESIGNER
HELPING WITH FULLSTACK , SYSTEM DESIGN ,UI/UX , LOW LEVEL
4+ YEARS OF EXPERIENCE AS A GENERALIST DEVELOPER
BOM[12:00 AM]
MENU
A
R

EXPERIENTAL
DESIGN ENGINEER

Y

DEVELOPER

A

UI/UX

N
K
ARYAN KATHAWALE
SOFTWARE ENGINEER / DESIGNER
HELPING WITH : SYSTEM DESIGN ,
UI/UX , LOW LEVEL 4+ YEARS OF EXPERIENCE AS A GENERALIST DEVELOPER

An entire app lighter than a Shadcn button

2025-05-23

"I'm not a clown, I'm a Next.js developer"

you can read the original article here

A few days ago a recent blog by Tero Piirainen @tipiiraiTero Piirainen @tipiirai was published. It was a very interesting read, and I'm glad to have read it. The author, a Nua.js developer, explained how he built a large scale app using Nua.js. Not only is the application beautiful and the engineering elegant, but it is also very lightweight. It showed the capabilities of Nua.js and how it can be used to build large scale applications.

The Application is only 38kb in size which is impressive! The author shows how impressive it is by compairing it with a shadcn button in a Vite/React Application, which clocked in at 73kb. To give more context on the projects, here are the links for the projects:

That being said , there are several problems with the perspective that Nua.js beings, which I think are important to highlight.

The Raw no of bytes is a dead giveaway, but this is not the only thing that people should consider when comparing Nua.js and Vite/React.Below is the chart of Performance Comparison between Nua.js and Vite/React collected from V8 Lighthouse application.

METRICNUAREACTDIFFERENCE
Largest Contentful Paint (LCP)30.4s1.3s-29.1s
First Contentful Paint (FCP)4.3s1.3s-3s
Speed Index9.0s1.3s-8.7s
Total Blocking Time3,620ms0ms-3.620s
Cumulative Layout Shift0.1330-0.133
Interaction to Next Paint (INP)144ms32 ms-112ms
  • ⏺︎the testing was done on a MacBook Pro with M2 chip, with a 16GB RAM and a 256GB SSD,both tests are done in same connection speeds and same network bandwidth.

This comparison is a bit like someone bragging that their entire house weighs less than your couch—impressive, but you'd want to know if the roof leaks, right?

To know more about this , we need to talk a bit more about the Architecture of Nua.js and Vite/React.

NUE.JS Architecture

Nue is a framework that is based on web standards, designed to play well with bun.js ( although it has support for node and deno). the main architecture of Nue is based on the concept of modules, which are similar to the concept of components in React. each module is responsible for rendering a specific part of the application, and it can be reused across different parts of the application. But unlike React which decided to break stuff up into components, Nue decided to break stuff up into modules.

app/
├── index.html        # Main entry point for the application
├── app.yaml          # Application configuration
├── model/            # Business logic and data operations
├── view/             # UI components and templates
├── controllers/      # Routing and interaction handling
├── design/           # Application styling
└── img/              # Application-specific images

it is more aligned with MVP architecture, which is a pattern that is used in frameworks like Laravel and Ruby on Rails.let's look at some files I got from their docs.

// app/model/index.js
import { customers } from './customers'
import { deals } from './deals'

export { customers, deals }

an example of a module is given below :

// app/model/customers.js
function enrichCustomerData(customer) {
  return {
    ...customer,
    lifetimeValue: calculateRevenue(customer.purchases)
  }
}

export const customers = {
  async find(filters) {
    const results = await db.customers.find(filters)
    return results.map(enrichCustomerData)
  }
}

and on the frontend side ( View)

<article @name="customer-profile">
  <header>
    <img :src="customer.avatar" class="avatar">
    <div>
      <h2>{ customer.name }</h2>
      <p>{ customer.email }</p>
    </div>
  </header>
  <dl>
    <dt>Company</dt>
    <dd>{ customer.company }</dd>
    <dt>Lifetime Value</dt>
    <dd>${ customer.lifetimeValue }</dd>
    <dt>Member since</dt>
    <dd>{ formatDate(customer.joined) }</dd>
  </dl>
  <footer>
    <button @click="editCustomer">Edit Customer</button>
  </footer>
</article>

and for Interactivity (controllers) we have script tags embedded in the HTML.

<script>
  import { model } from './model/index.js'
</script>

<form @name="chat-form" @submit.prevent="submit">
  <textarea name="body"></textarea>
  <button class="primary"><icon key="send"/></button>
  <script>
    submit(e) {
      const body = e.target.body.value.trim()
      if (body) {
        const user = model.users.get(this.id)
        user.threads.reply(body)
        e.target.body.value = ''
      }
    }
  </script>
</form>

Again , Very simple and straight forward, the architecture is clean and makes consideration for the future developement easy. you can also bind javascript directly with rust-wasm , which means things take less overhead due to Javascript ( always a nice thing. ).

// Rust code (engine.rs)
#[wasm_bindgen]
pub struct Model {
  events: Vec<String>,
}

#[wasm_bindgen]
impl Model {
  pub fn search(&self, query: String) -> String {
    let matches = self.events.iter()
      .filter(|e| e.contains(&query))
      .collect::<Vec<_>>();
    serde_json::to_string(&matches).unwrap()
  }
}


// JS integration. (Table/index.js)
import init, { Model } from './engine'
await init()
const engine = new Model()

export const model = {
  search(query) {
    const data = JSON.parse(engine.search(query))
    return data.map(el => hilite(query, el))
  }
}

So this framework is designed to be used to serve html as fast as possible with as less javascript as possible, and it is very easy to integrate with rust-wasm. But the only advantage I could think of rather than using react is simply that you can write your backend in multiple languages, with benefit of web standards.

here are the negatives though:

  • ⏺︎The Hate for Components:

The Component composition is not a downside, it's not a framework specific pattern, several people have diverted from using it and all came to same conclusion. Svelte, Solid, Vue, React, Angular, etc. are all using the same pattern, Why is that? even people not in the web dev ecosystem like Sony ( in Playstation ) have used this pattern, Microsoft has React Native for windows, which is what allegedly powers the Start menu soo many people use.

I'm not asking to change the current architecture, the way it seperates the concerns using standards is nice, but it is not desirable in 2025 where people have things like HonoX, QWIK, Solid.JS , Preact, which blasts Nue out of the water in core web standards. It leaves a lot more desired to be done in the future. And saying it is much better than these frameworks used by people who have 10, 20 years of experience in web development is just a lie, not only are you robbing yourself of the benefits of these patterns, you are falsely claiming that we should go back to seperating these layers when industry has moved on to the next level.

  • ⏺︎The original boast of optimizations:

a few days ago I saw a post from Zack Jackson @ScriptedAlchemyZack Jackson @ScriptedAlchemy the creator of Rspack.

rspack now produces the smallest build output of all bundlers. we have worked closely with swc to improve code optimization between the two tools.

Rspack

look at the minified version of React router, it's only 13.2kb ( Minified and Gzipped ) , compared to the original . This is possible because of the innovations in the Bundler ecosystem, Rspack uses something called Advance Dictionary Compression, achieving 86-92% better compression . and if you want real world cost savings, well have I got a quote for you.

Performance: Up to 92.1% improvement over standard compression Proven Savings: $12,600 - $313,200 annual CDN cost reductions - Zack Jackson @ScriptedAlchemyZack Jackson @ScriptedAlchemy

The advances in the bundler ecosystem have made it possible to achieve such amazing results, While keeping the DX of React-Router-Dom v7 in mind. Im not saying there is not a conversation to be had about less bytes, but it is important to remember that the goal of a framework is to make things easy for the developer, not to make things easier to boast about, going bullish on a pattern that is designed for optimization only is not a good idea because at any point there will be a shiny new approach that will make it even better ( Im looking at signals, compilers, Partial Pre-rendering, Image Optimizations,Rust NAPI, Perforr.js, HTMX, Vue Vapor,Million.js etc ).

  • ⏺︎Bun wars:

this is a minor complaint, but bun for all it's glory is a very performant, Nue is bullish on Bun. But, Bun.js is not WinterTC 2025 compliant. Bun.js while being a great project,introduces concepts like Bash Scripting in Javascript, It is cool to see but it might not be a good idea to use it in production yet. This is a minor complaint and does not detract from the overall goodness of the project.

  • ⏺︎Last but not the least, Hope for the future:

NUE.js is a new project, it's ideas have existed for a while but there is a lot of work and passion in the project and I for one am excited to see what the future holds for this project. I just hope this starts a better conversation about what developers realistically want from a framework, and what the future holds for frameworks. That is my goal. and when the next time I type in pnpx create-next-app@latest in my terminal, I will think about it and smile.

fin.

comment on bluesky / mastodon / x / rss

HEY THERE,
[GENERAL]
[Platforms]
[Personal Details]
(+91) 8421-911-353
RESUME
[ADDRESS]
CBD Belapur
Mumbai , Maharashtra , India.
CC BY-NC-SA 4.02024-PRESENT © Aryan Kathawale