I've found Svelte+React have good support for TypeScript, especially for guaranteeing the types of props passed to components, are there plans to support this? With controllers in Go and Views in Svelte/React, is there any way to help with correctness of data passed as props to the Svelte components?
I think the idea is to ingest a JS "template" and spit out the rendered HTML+JS, kind of like traditional SSR templates, but it could be possible to shoe-horn in an entire client-side router that gets initialized as a DOM object somewhere.
EDIT: I could be wrong, please correct me if so.
You're correct that Bud server-side renders the Svelte files, then hydrates them on the client.
This is similar to what most other JS frameworks do, it works like this:
1. Create two builds: one for server, one for browser. This is done using ESBuild. This is actually done lazily upon request, similar to how a CDN like esm.sh would build JS to be imported. This will hopefully allow the build system to scale for larger apps. Vite was my inspiration here, but it's all done in Go.
2. V8 and the Svelte compiler are baked into the bud binary. When a request comes in, V8 evaluates the compiler running the server-built page and returns HTML. That's a mouthful, hopefully that makes sense.
Happy to go into more depth here or via email email@example.com.
It also has HTMX  integration to create slick/modern UI behavior without writing any JS.
Ent is a nice choice for the ORM. For models, I'm planning to go with a combo of sqlc + xo. I want to tie the DB schema to your application.
relevant hn thread https://news.ycombinator.com/item?id=30290225
Go community has been pretty "anti-framework" (AKA "just use net/http" when it clearly doesn't solve every problems..., "don't put request scoped variables in context" when it's the very purpose of that interface...) and there was a lot of drama around some framework creators, unlike any other web language community I have seen by the way (remember Martini and the insane backlash? Iris and the constant drama, was that Iris, I don't even remember the name...) so it will be pretty interesting to see the reception for that framework.
One advice to the author, congrats but don't call your framework "framework", it's like the go community hate that word, just say "a set of useful libraries to help web development", it seems like euphemisms are easier to swallow for some...
I haven't actually used generics in any serious way yet. I haven't needed them. That being said, I'm happy they're in the language now and I'm really looking forward to seeing what the Go community comes up with during this period of experimentation.
I'm aware of the "anti-framework" ethos in the Go ecosystem. I think it comes from a good place, but there's room for other approaches. Go was created to build large-scale networked applications. The Go community deserves tools that are specifically designed for building web applications. Tools that are just as productive as Laravel, Rails and Next.js.
If this puts me at odds with some Go developers, I'm okay with that. We're probably just focused on different areas. Go is a big tent with plenty of room for different perspectives.
One thing I like about the code generation approach that Bud is taking is that there's more flexibility in the API design.
Need to break out of Bud's Controller conventions? Just pass a http.ResponseWriter and *http.Request and Bud will generate the glue code to wire everything up. You can go high or low-level depending on the problem that's in front of you.
I don't think this will appease the "just use the standard library" faction, but these kind of escape hatches will at least put a dent in their argument.
It was a tough call, but I ultimately decided to server-render JS. This thought-experiment helped:
Bud will eventually ship with it's own JS evaluator. Either through https://github.com/dop251/goja or through porting https://github.com/bellard/quickjs to Go (~25kloc of C)
I've started using Go at work so definitely interested in using this for side-project web apps to keep me in the Go mindset.
Great questions. I answered some above, so I'll copy some and then answer your other questions below:
>> what's it doing?
Bud server-side renders Svelte files, then hydrates them on the client. This is similar to what most other JS frameworks do, it works like this:
1. Create two builds: one for server, one for browser. Both are built using ESBuild. In development, builds happen lazily upon request, similar to how a CDN like esm.sh would build JS to be imported. This will hopefully allow the build system to scale for larger apps. Vite was my inspiration here, but it's all done in Go.
>> what gets sent across the wire?
What gets sent over the wire is HTML. That HTML then has a script tag which requests the client-side version of the page that's used to hydrate the HTML and make the page interactive.
>> How big is the binary for the HN demo?
I just checked the binary size and it's 47.6 MB. It's mostly V8 right now, but will definitely get larger as you add more assets. I haven't tested it yet, but hopefully you'll be able to rsync just the diffs to a server.
>> What's the story for static assets like video or images
You can add them in the public/ directory. There's documentation here: https://denim-cub-301.notion.site/Hey-Bud-4d81622cc49942f991...
Let me know if you give Bud a go on your side-project! Happy to go into more depth here, over email firstname.lastname@example.org or on twitter @mattmueller
I started my programming career after following the Rails how to make a blog in 15min youtube video. Always a good choice.
Fun fact: It took DHH a year after he first introduced Rails to get that famous weblog demo up. This stuff takes time :)
"I think Node is not the best system to build a massive server web. I would use Go for that. And honestly, that’s the reason why I left Node. It was the realization that: oh, actually, this is not the best server-side system ever."
Heavy computation still ties up the event loop in Node.js. We're just not talking about it as much because most people deploy to serverless functions nowadays which can spin up compute upon request. I love serverless and use it with https://standupjack.com, but it comes with it's own tradeoffs!
But then he created deno....
I just don't want a NodeJS backend, all our team wants is to use a Golang backend which saves us ton of resources, which means less instances required, which means less $$$ (and Golang is awesome - performant, easy to read and write, easy to code concurrency, type safe without the hassle, built-in test suites/formatter/etc).
I'd love something like Laravel but for Golang+Svelte.
Please hit me up when you give Bud a try over email email@example.com or on twitter @mattmueller. I'd love to hear what you think!
What's the advantage of rendering HTML templates over websockets? Is this similar to Hotwire where it sends you HTML fragments over websockets when you, for example, click on a button?
The approach is similar to hotwire except I only use stimulusjs and not use turbojs. turbojs doesn’t integrate well with html/template. In my approach, you can simply reuse the html templates you have already written with standard html/template package.
Sorry for the rambling, I haven’t gotten around to writing down all of it in a more structured way.
I see views and controllers in the documentation, but the only mention of model is that "model" is a reserved directory. What are your plans for models and persistence?
>> What are your plans for models and persistence?
I haven't worked out all the details, but it's going to be some blend of https://github.com/xo/xo and https://sqlc.dev/.
1. High-level, type-safe "ORM" that's generated from your database schema.
2. sqlc as a fallback to cover the more complex SQL queries in a type-safe way.
The hard part is going to figuring out how to support extending the ORM with your own custom methods, hooks, computed fields etc.
What do you think?
I have been working with Go professionally since 2015 and quite often it makes me feel frustrated due to lack of full-stack web frameworks.
I was thinking to do something like your project, but with focus to full SSR/zero-js. Lucky me, you started it first . Maybe be in some things I will prefer different approach, however, your project already released (and it's excellent) while mine only in prototype.
After I read the documentation in your project it feels like you really stepped on a lot of minefields. Great job!
One thing is still bothering me though (or maybe I missed it in docs): how is Bud dealing with relative links? Very often JS writers forgetting about the situation when the application could be served under different root locations. Does Bud have helpers to construct relative URLs without relying on user-provided server url? (I made PoC for that - don't use it in production https://github.com/reddec/gin-template-manager/blob/eb09f4e8...)
Having path helpers absolutely needs to happen, something like: https://guides.rubyonrails.org/routing.html#creating-paths-a.... I'll probably get custom routing up before that though because I want to make sure the design covers changes to routes.
There's a whole layer of generated JS/TS that will eventually be built out here.
The last bit about single binary is quite interesting. I could easily deploy app to my raspberry Pi without worrying about bundling things. I know Go can do this but it's nice that framework aligns with Go philosophy.
I've been using Kenny Grant's Fragmenta for past 3 years and I haven't had need for anything else because I like SSR with Go and aim to keep JS as minimal as possible. I assume you're trying to address the need of those who want a Go back-end but with modern JS front-end?
I hope that you get to answer the queries in other comments regarding the design decisions reg CSR & V8 while using SSR.
> I assume you're trying to address the need of those who want a Go back-end but with modern JS front-end?
Yes, that's a big reason. Half of it's preference, the other part is that most of the JS frameworks don't provide a cohesive solution for sending emails, queues, scheduling tasks, etc. The backend is a larger part of your web app than most JS frameworks give it credit for.
Their stance is to outsource the backend to third-party services, but then you're stuck piecing all these SaaS's together. I like the approach Laravel takes here: provide interfaces for Mailers, Queues, Scheduled Tasks, File Storage, etc. then provide implementations for SQS, S3, Mailgun, etc.
Just answered the question about SSR + V8 above!
Bud uses modern FE frameworks and leans heavily into making code generation work well to give you type-safety and higher-level APIs.
Buffalo is farther along in the journey with database migrations, mailers, etc.
Unfortunately, I think Buffalo is no longer in active development. The main author left his own #buffalo Slack channel in gophers.slack.com.
I personally don't find the go ecosystem very good for people who want to goto market as fast as possible, the libraries are less developed and you're going to have to build your own stack.
Bud and Buffalo seem like great developments, but your comment about the Buffalo one no longer being in active development would just totally suck if you had invested your time into building your SaaS on this.
I'm now using Ruby on Rails in the next version, and I couldn't be happier - maybe it's not as fast, but it certainly helps me ship features faster to customers!
Agreed, though when I do find a library it tends to just work. The challenge is finding the right library. There's no real reason for this though and I think with Go modules finally maturing and hopefully more web frameworks written in Go we're going to see an explosion in this space. Fingers crossed.
>> I'm now using Ruby on Rails in the next version, and I couldn't be happier - maybe it's not as fast, but it certainly helps me ship features faster to customers!
This is the spirit I like to see!
i come from a ruby, js and python background using frameworks like: react, django, rails, etc. always wanted to excuse to use GO and this might be it!
Let me know when you give Bud a go! Feel free to email me at firstname.lastname@example.org or hit me up on Twitter @mattmueller.
Their reliance on V8 Isolates will make it difficult, but if they add Docker support at some point, then we're good. I don't see how Bud would work with WASM at the moment, but if someone gets it working, that would be a very pleasant surprise!
I'm more focused on getting Bud working well for deployment targets like Fly.io, Heroku, Lambda, K8s, Fargate and EC2.
Created an RFC: https://github.com/livebud/bud/discussions/33. Feedback very welcome!
Hit me up on Twitter @mattmueller or over email email@example.com. I'd love to hear what you're working on!
I perused the documentation and I can tell a lot of thought went into this. I appreciate the simplicity and applaud all efforts to make Go a serious contender in the full-stack web framework space!
In other words, render the HTML in Go and ship the diffs to a small blob of JS running in the client over a websocket, instead of baking a whole React build into your server-side app. Much simpler toolchain this way, much easier to reason about.
I appreciate that this is a fairly different solution; one of the author’s explicit goals is that it should “Feel like using a modern JS framework”. Personally I’d rather have it “feel like I’m using Django / Rails”, except with most of the superpowers that were historically FE-framework-only.
There is no “ugh ok … better set up react now” feeling to make say an interactive chart because it was always there.
Similarly there is no “ugh ok … better set up a backend now” feeling you get using create-react-app as it was always there.
There is almost no mental gear switch as you switch from front to back to front.
The only small negative is you need to be careful what that first “server side” render produces and what it can access. But that is also part of the magic, as you can fine grain control the initial flash of content. For example include the layout/menus. Or include a cached view of a list that then updates on final render.
It just feels so well integrated more than any other framework I have tried (like aspnet mvc or RoR for example).
It will be hard to beat: If you want to beat it in Go you need at least a good Go->JS transpiler so you can use the same language. But even then anything other than JS/Typscript means I need a mental modal of what the transpiler is doing. I don’t get a free pass
on understanding JS or the DOM.
I hope is that Go <=> JS/Svelte won't be too much of a context switch for folks.
I'm not planning on innovating as hard in the frontend space as Next.js. I'll probably just stick with SSR, add support for pre-rendering and build up the client-side runtime with features like prefetching and client-side routing. If something really cool comes along, we'll see.
I'll instead focus on the area where Next.js neglects: backends. DB workflows, mailers, queues, scheduling, pubsub are all coming to Bud.
As @drewry mentioned, we're aiming to be frontend-agnostic. Changing the renderer should be as simple as creating files with different extensions:
- index.svelte for Svelte
- index.jsx for React
- index.html for HTML
- index.gohtml for go/template
There's more information in this discussion: https://github.com/livebud/bud/discussions/8
Why do you think that?
Can you elaborate how you were spoiled by Go and don't want to go back to writing PHP?
I switched from PHP to Node about 11 years ago. I was probably one of the first 100 Node.js developers. My biggest contribution there was creating https://github.com/cheeriojs/cheerio.
Go spoils me because it "just works". The best way I can explain it is when I'm stuck on something in Go, it's almost always my bad, not something that Go is doing poorly. This is in contrast to the Node.js ecosystem where it feels like half of the problems I run into shouldn't be my responsibility.
I strongly relate to this post by Kevin Burke: https://kevin.burke.dev/kevin/one-year-of-node-js/. A lot has improved since this was written. We're finally over the ES Module vs CommonJS hump, Typescript has become the defacto standard, Babel is less used now and Webpack is effectively abstracted away. I still run into way too many problems with the ecosystem and the transition to Rust will make the ecosystem more complicated, not less.
My transition from Node.js to Go happened because I was working solo on https://standupjack.com/ and I kept running into issues with the message broker. It was using the most popular RabbitMQ client for Node, yet it was still super flaky.
About 6 years ago, I was chatting with TJ Holowaychuk and he kept singing Go's praises. One holiday I decided to rewrite just the message broker in Go. I got it into production in 3 days and didn't have anymore problems with it. That set me on the Go journey :)
curl -sf curl https://raw.githubusercontent.com/livebud/bud/main/install.s... | sh
Hacker culture could benefit from less frameworks to more low code/no code platforms (which is a space with more fertile ground)
I kind of made an almost similar thing can generate custom boilerplate for backend servers a while ago -> https://github.com/tompston/gomarvin
Yes, Go has nice standard templating and HTTP serving libraries, and nice dependency management. These are all important features for a web framework.
No, it will never be productive as its competitors in the web framework space, because you simply cannot write expressions like `order.customer.region` that intelligently hit the database, because you can't override the dot operator. Instead you have to write unreadable crap like `regionController.Show(userController.Show(order.customer).region)` which is infinitely less "productive" than the former, for obvious reasons. Oh, you can `go generate` the *.Show definitions from a simple struct definition (or with 1.18 generics)? Too bad the final product is still unusable!
Use Go where it excels and connect it to your Ruby/Python/Typescript web backend over gRPC or HTTPS.
Writing backend with a rigid, verbose, mostly type-safe ORM: $5
Writing backend with a terse, expressive ORM: $2.50
Adding type annotations to the previous code: $1
So for authoring an app, I tend to agree with you. Languages like Ruby/Python/Typescript are probably faster to get something working.
I try to consider productivity holistically though. With Go, there's a lot less fussing with the tooling. I've also found Go saves a lot of time when onboarding new teammates. This is because of Go's intentional decision to be conservative with syntax. After all, most developer time is spent reading, not writing.
I respectfully disagree with your preference to split your backend up over gRPC or HTTPS. I prefer the approach Shopify takes to break up it's monolith: https://shopify.engineering/deconstructing-monolith-designin...
Bud will support something like this in the future.
Ultimately you will be teaching the framework, not the language, when it comes to large frameworks like this. Both Go and Python are easy to learn, but frameworks always add a lot of complexity.
> I respectfully disagree with your preference to split your backend up over gRPC or HTTPS. I prefer the approach Shopify takes to break up it's monolith:
I'm not arguing for this or that architecture cargo cult. I prefer monoliths too, but sometimes you really need distributed microservices and Go+gRPC is one of the most maintainable ways to do that.