Show HN: A no-build fullstack SSR TypeScript web framework
65 comments
·February 12, 2025bsimpson
I don't understand.
You're authoring in TSX and serving JS to browsers, so there's clearly a build step. How is your model different from e.g. vite serve?
How does it get deployed? Are the files translated to vanilla JS on request, or are they translated ahead of time and cached (in other words, a build step)?
thesephi
My apologies if the wording made it confusing :D By "no build" I only meant "no bundling".
You can check the generated source code of the example deployment to see how it's deployed: https://fullsoak.onrender.com/
But spoiler: it's like in the 90s: each page request results in a text/html response, and the HTML doc then links in any .js or .css file it needs.
I elaborate more in this wiki: https://github.com/fullsoak/fullsoak/wiki/Concepts-&-Example...
leptons
Not having all the code in-line that can be in-line is like the 90s. You had me until the 'no bundling' thing. Separate http requests for all resources is a non-starter for anyone worried about page speed. I do like the choice of Preact though!
thesephi
and that's a totally valid concern :) So far I only wish to check the concept in general (ie: "does it work"). As for "does it work fast / at scale", definitely a future topic.
I do wish to elaborate: since we use JSX/TSX, in theory we can in-line as much as we'd like. Here I include CSS in the component itself: https://github.com/fullsoak/bun-examples/blob/main/src/compo...
So it can be just 1 HTML resource + 1 js file for every unique path. And with preact-iso (or react router) we can make subsequent pages load on-the-fly without a hard browser refresh / hard resource reload. Like so: https://github.com/fullsoak/bun-examples/blob/main/src/compo...
But ultimately: I do see rooms for improvements re. resource optimizations. My personal wish is to use standard web specs such as "preload", "prefetch", "server push", etc. to optimize as much as possible, without taking the "bundling route" - so: just exploring a different taste, not that I have anything against the existing "build routes" :)
root_axis
It works with bun or deno which are alternative node runtimes that support jsx and typescript without a build step.
wubrr
Deno does not support jsx and typescript 'without a build step'. It just runs a build/transform step for you under the hood - using the same tsc compiler, config, etc.
https://docs.deno.com/runtime/reference/jsx/
Saying this is not a 'build step' is like saying a shell script that builds and runs a C program from source has no build step.
nextaccountic
It has no build step. It builds when you run
It's like language implementations that nominally aren't "compiled", like Python, but nonetheless compile to bytecode when you run the program
nsonha
> a shell script that builds and runs a C program from source has no build step
I would say so. Ultimately build step or not isn't a meaningful thing to care about. What matters is the cold start/runtime impact. In the case of deno/bun, the impact seem minuscule/not meaningful.
satvikpendem
So the build happens implicitly via the runtimes, then.
jbreckmckye
Bun handling the TSX at runtime is just its capabilities as an interpeter. Else we'd be saying all interpreted languages have a build step
IshKebab
> Then the app can be started up for local development: > > deno -A --watch src/main.ts
Sure looks like a build step to me?
Anyway I'm fine with one easy Deno build step, but Deno already has a fantastic web framework that supports SSR, so how is this different to Fresh?
thesephi
Thanks for your thoughts! I do adore Fresh. In fact, I have run production projects on Next.js and Remix, and played around with Deno Fresh, and I enjoy them in different ways.
When I wrote "no build", I simply meant that we do not bundle the whole app into a single file.
Fresh is indeed very close to what I'm trying to explore here, yet if I understand correctly about Fresh, we still need a real build step: https://fresh.deno.dev/docs/concepts/server-configuration#-b...
Disclaimer: I have nothing against build steps, I just wish to explore an alternative approach where we completely do without them!
the_arun
Sorry, slightly confused. From JSX docs:
> The difference is that the precompile transform analyses your JSX statically and stores precompiled HTML strings if possible. That way a lot of time creating JSX objects can be avoided.
So if there are compilation errors, who is stopping me from running without the build?
thesephi
Hi! My apologies if the wording was confusing :( By "no build" I mostly meant "no bundling" (so: we're not combining all files into a single js bundle entry).
As for JSX itself: if we choose to use it, for sure we still need to transform it back to vanilla JS. I elaborate more in this wiki: https://github.com/fullsoak/fullsoak/wiki/Concepts-&-Example...
quectophoton
I've been wanting to make a no-build webapp using Mithril.js[1][2], with plain-JS type annotations that don't require build steps (TypeScript's JSDoc syntax [3], but I'm looking forward to the proposed type annotations[4]). With something like this, type-checking would still require running a command when using Node.js, but it's just an optional developer dependency since the code would still be just standard JavaScript.
But in the end I've not done that because I figured it's more effort than it's worth, compared to just doing server-side rendering with other backend languages and just using JS where needed (not necessarily "raw" JS, I just mean it as in "not having a full-page component").
I'm just letting you know that there are definitely some people like me that would like if more JS tooling didn't require a build step or specific runtimes (like Deno or Bun) as a hard dependency.
[1]: https://github.com/MithrilJS/mithril-node-render
[2]: https://github.com/StephanHoyer/mithril-isomorphic-example/
[3]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported...
thesephi
kudos to the MithrilJS project & also for having earned visibility on OpenCollective <3 I can see the (much respected) history track of this project.
Having "survived" the "Internet Explorer ages" of the www, I can share that my heart always has a slot for "vanilla JS" (& anything towards its direction). When coding solo and/or for light-weight (enough) projects, I also tended to do pure JS.
skipants
This looks great. I would love to see something like this evolve to become the industry standard.
My only worry between then and now is will it run into a wall if it is unable to solve problems that build steps did?
Does it handle extensions that webpack did browser shims? I assume those will just be imported modules.
And of course it is a new-thing-to-learn(tm) which is always a tough sell to getting it used in a corporate setting. For good reason.
Here's some things I like about the idea, mostly duplicating what you said already:
1. By holding your project to a no-build constraint, that means we won't go down the rabbit hole of toolchains like we did with bower, webpack, etc. to fix any problem. Ever. Yay!
2. You really did simplify the "build" step. My personal experience has been that that has always been a source of frustration, especially since most developers just want to get-shit-done and the more deep-diving devs would have to martyr themselves to get it working again. Now hopefully they just need to understand one set of config to tweak to get the application working as is.
3. It feels to me like your project will own any breaking issues that come out of it. It's always been a pain when there was complexities at the edges of parts of the toolchain. If NPM v16 breaks with webpack v5 or whatever its version scheme is, one or the other needed to upgrade to fix it and the ownership of the issue wasn't always clear. Sometimes it would take awhile because of a niche interaction between the two. And of course upgrading past it had other painful breaking changes your legacy app needed to address.
Anyways, looks good! Keep it up & good luck! I'm curious to see where this goes.
thesephi
my appreciations!
You're absolutely correct at the "problems that build steps do". One example is the whole loader stuff (e.g. SCSS, Less, and the plethora of other things we can "just import (tm)" into our TSX components). For now it was a conscious decision that I keep things "stupid simple" as I shared in a Bsky post: https://bsky.app/profile/mrkha.ng/post/3lg3qw377ss27
Re. the "selling" part, it's also my wish to see how people resonate with this. Maybe not the framework itself, but only the concept of using standard specs (ie importmap + TypeScript runtime) - & since it's just bare standards, let's see if it attracts frictions (or not).
nbbaier
Does this support serverless environments like cloudflare workers and val town[0]?
jbreckmckye
Can I ask (partly for my benefit, partly for yours) for a short summary of what the problem is I might have, that this tool solves?
thesephi
i wouldn't really introduce this as "a problem solver" :) It's more like an exploration of an alternative approach that combines base concepts such as:
- import map: https://preactjs.com/guide/v10/no-build-workflows/#import-ma... - TypeScript runtime: https://www.reddit.com/r/typescript/comments/y8tsav/comment/... - SSR & Hydration: https://zustand.docs.pmnd.rs/guides/ssr-and-hydration
But if I have to pick my brain and find a benefit that this approach brings, i guess it would be that we now avoid the entire "config hell" and cognitive load of managing build setups. This article shares some of this view: https://deno.com/blog/node-config-hell
Disclaimer: i have nothing against standard build processes that we've used for years. I've juggled a lot with browserify, webpack, and their successors & siblings. I just feel it's worthy to give a spotlight for an approach where we completely go without them :)
blinkymach12
I like it! I spun up a little remixable Glitch project based on your demo so that I could play with it in a web editor. Thanks for sharing. https://glitch.com/~fullsoak
thesephi
Wonderful!!! I wanted to provide a Live Demo, I tried with Deno Deploy, but I got a brick wall there because of some unintended blocker (ironically haha): https://github.com/denoland/deploy_feedback/issues/802
My next best choice was to extend the support to Bun, and then deploy it with Render.com: https://fullsoak.onrender.com/
I wasn't aware Glitch can also support Deno. So, sincere appreciations for your Glitch example <3 <3
darepublic
Taking twobof my favorite parts of the ecosystem (ts and jsx) and leaving behind the rest (webpack). Good luck!
pomdtr
Neat! I'm working on a self-hostable platform to host my deno apps (https://smallweb.run), I wonder if I would be able to your framework on there.
digitaltrees
You are aware the term full soak is slang for sex right? Intentional name?
lerp-io
maybe do something like fullsock instead? idk just a thought
thesephi
no I had completely no idea. Is this a generation gap thing, or maybe I just lived under a rock for too long - thank you for the heads up haha. If this causes too much friction, for sure it should be renamed..
primitivesuave
The slang term "soaking" is primarily used in the Mormon community for a particular method of theologically-acceptable premarital intercourse.
yieldcrv
morman teenagers do 'soaking' because they were told active participation in pre-marital sex like thrusting is taboo while soaking inside… resisting the urge to thrust… satisfies the condition
the lore continues that third persons jump on a bed they're all on is a surrogate for thrusting
not generational, just mormon things
SignalM
Very cool will try it out. Like the bun support
thesephi
thank you! You may find a Live Demo example (deployed as a Bun app) mentioned in this wiki: https://github.com/fullsoak/fullsoak/wiki/Concepts-&-Example...
And Jude was kind enough to roll out a Deno example on Glitch: https://glitch.com/~fullsoak
Hi HN!
I'd love to seek your insights on a fullstack web framework that employs a different approach: no build.
It's not a new concept. The folks as Preact mentioned it: https://preactjs.com/guide/v10/no-build-workflows/
However, in the Web Framework market, I've yet to find many that support both "no build" and "SSR". There's always some sorts of "client mount" and "server mount" and either has (or both have) to go through a build (bundling) process.
With the build process, there comes additional maintenance efforts and cognitive load. I've enjoyed wrestling with tsconfig, webpack config, all sorts of presets and plugins countless times... When things work, they just work, but when we need sth a bit custom or unconventional, then we're almost always in for a tough ride. (or it's just me )
Not to say I'm against any existing build workflow. In fact I benefited a lot in the past from webpack, and i'm very positive about modern bundlers like Parcel 2, Turbopack, rspack, etc.
I just feel it'd be fair to save some slots for the "no build" route :)
To this end, I spent the last month working on a prototype of a TypeScript fullstack SSR web framework. It's compatible with Deno and Bun runtimes. I'd love to make it compatible with Node.js as well (at some point).
The framework registry page (https://jsr.io/@fullsoak/fullsoak) summarizes the motives expressed so far.
An example deployment is available at: https://fullsoak.onrender.com/app
The code behind the deployment above: https://github.com/fullsoak/bun-examples
PS: you may see Preact being used & mentioned everywhere but I'm positive that React is 100% supported as well (just drop-in & use). I just happened to choose Preact to experience it more for myself.
I look forward to your thoughts :) and learning if this might (or might not) be a feasible idea at scale. And perhaps, which future directions you would see this (or something like it) goes. Thank you much for any insight!