After building SPAs in next.js and blogs in Hugo, I finally settled on the simplest stack: Caddy+Markdown/HTML templates
I’ve talked about it more here: https://notes.alinpanaitiu.com/How%20I%20write%20this%20blog...
But the gist is that you have a Caddyfile like:
http://localhost, notes.alinpanaitiu.com {
root * /static/notes/
file_server
templates {
mime text/html text/plain text/xml
}
encode zstd gzip
try_files {path} /index.html?path={path}
}
…and any .md inside /static/notes will be rendered to HTML, plus any .html/.xml will support Go template syntax.This comes with the benefit of automatic HTTPS, asset compression and a one binary server.
Deploying is as simple as copying the folder with the Caddyfile and assets to my public server and running “caddy run”
I’ve been on this route before and evaluated tons of frameworks (Postgrest, Supabase,Directus, SpringBoot, FastAPI Laravel etc) and I’ve settled on the following to quickly create an MVP:
- Django+AlpineJS+HTMX
- Hugo+ Netlify for static landing page with a custom form linking to GForms.
Generally for side projects I start with a simple PoC and then iterate into a better fit for the projects needs. Most projects start out with the following PoC stack.
PoC: Python + file system as a database
If I actually use it a lot or performance is bad then I tweak the stack. Usually persistence is the first thing upgraded to SQLite. Then, if it's an HTTP project, I usually throw in jinja2 templates to make editing the layout is easier. Finally, if it's something I expect to always be up I'll rewrite it in Rust.
PoC w/ web front end: Python + file system as a database + fastAPI/Flask + HTML/JS/CSS as python strings
Rust doesn't have everything under the sun, so sometimes I'll split the service into two: one which handles requests over a named pipe or unix socket in python and the front end in rust.
Rust Services w/ web front end: Rust + axum + askama + SQLite via tokio-rusqlite Python Services: Python + asyncio using asyncio.loop.add_reader and file descriptors to attach to the named pipe or unix socket.
I typically make a REST backend and client in Vue with all code in one repo that auto-deploys to a cloud VM and/or Nelify with a CDN for app and sometimes also the API.
For the backend I'll use MySQL or PostgreSQL and language/framework I'm interested in, e.g. Go+libs, F#/Giraffe, Elixir/Phoenix, Kotlin/Javalin+JDBI, etc. Even Python/Web2py or Php/Yii2 or Ruby/Rails works alright sometimes.
I'm not much of a fan of ORMs that have a dsl that differs from SQL query composition patterns, JPQL/Hibernate is pretty bad.
Edit: If I were to make a typical/bland mobile app, I'd probably use Dart/Flutter rather than native (and certainly not React-native).
Client / Server Web App: Node.JS, Bang.html[0], the filesystem
Native downloadable executable desktop GUI application: Node.JS, GraderJS
CLI app: ??? Don't know yet, GraderJS can work but it's focused around GUI
Mobile app: ??? Don't know yet
Embedded: ??? Don't know yet
Graphics: Processing (but surely there are much better options nowadays)
AI: ??? Don't know yet
Front-end: VanillaJS[1] or Elm
Server: Deno or Rust
Database: Postgres
Hosting: Cloudflare Pages and fly.io
---
Front-end is usually the complex part, so I focus on that first. Elm creates fast and clean front-ends (and the community packages never have bugs), so I embed Elm when the UI demands extra complexity.
I generally keep my server code _extremely_ light-weight. I shove most of the complexity of my systems into the database queries, where it's easy to optimize.
I also find it useful to organize my API into "one POST for each button" and "one GET for each table".
---
I never use anything truly lightweight for personal projects or prototypes. For one thing, then I'd have to learn a lightweight stack in addition to the heavier ones for real projects, plus, they're not usually that fast and easy to use.
I'm a fan of Node/Svelte(I've never started a new project in it but I have enjoyed working on existing stuff in it).
For new work I'll almost always be using Python, CherryPy, and a Vue3/Websockets based approach, usually with quite a few supporting libraries.
I also use a lot of Mako templating, but I'm moving away from that as Mako doesn't have good IDE support and it can get in the way of realtime responsiveness.
If there will be content involved, which there often is, I'll use Showdown to render markdown.
One technology I really want to work with more is Microsoft's Adaptive Cards, they will likely be finding their way into my projects soon.
Against my better judgement I do have a project idea in mind at the moment, but it would need either Dart or Kotlin, and the backend would probably be MQTT, although anything personal project sized would be trashed instantly by a DDoS since part of the design involves an open public backend with all the security on the client.
And of course, if my project is embedded, ESP32+Arduino all the way, At $5 or so, there's rarely any reason to use a bare MCU or anything that doesn't have WiFi unless you're doing mass production.
One thing I never touch for anything personal is a database. No postgres, no mysql, none of it. If I need one I use sqlite.
If nobody is paying for I'm not doing sysadmin work at home. My stuff is all unzip and run, with dependencies from the Debian or language package repos.
I don't use Docker or Kubernetes or anything like that, because I avoid anything microservice-like, or anything that requires an external process with nontrivial configuration. Needing an MQTT broker or relying on an external daemon for something very big and complex like Zigbee2mqtt is about as far as I'll go.
Even apache/php is too much config for me. I have very little tolerance for system level configuration needed to support one specific app, and messing with containers isn't my idea of fun either.
This will be unpopular. For simple PoC stuff that require a GUI and SQL I'll reach for MS Access. It's so quick at getting something up and running pretty much immediately.
Obviously you move on from it, but Im unaware of anything with pretty much everything in one place like it.
Recently I've been using Dart and Flutter. I can't complain at all.
I’ve been using vite + svelte quite a lot and it’s super nice and extremely lightweight/flexible. Server side I stick mainly with flask because it’s the devil I know and it’s super simple to spin up a functional API. I use boostrap for a lot of prototyping, I usually pair it with bootstrap studio which is very good when it works.
Vanilla Javascript / HTML is the fastest for me. Maybe a couple of Python scripts for automation.
Laravel with tailwind. Great DX and quick to setup
Simple stuff. If I need more than basic static HTML, I'll reach for Flask and postgres.
Lazarus/Free Pascal for anything involving a GUI
Python for things related to libraries, etc.
Front end: Preact, Solid or VanillaJS
backend: a nasty hybrid of NodeJS, zsh and SQLite3
arangodb, python asyncio, jinja2 templates, homemade microframework, very little javascript
i also interested in systems based on websockets and webgl but that's another project
rust (plus whatever packages the problem needs) on any posix compliant system. Usually leaning toward BSD in production.
Laravel + Turbo + Alpine + Tailwind
Blazor Server
Remix Run
I am using old school php like this:
``` <?php include('header.inc.php'); <?php include SOME PAGE BASED ON URL ?> <?php include('footer.inc.php'); ```
And <script> tags of course, with vanilla JS. Super quick and reliable. No layers.