Building a Little City of Text
The other day, while wandering through the stranger, quieter corners of the internet, I came across a curious place called The Midnight Pub. It felt less like a website and more like a door half-open in an alley: dimly lit, quiet, full of small voices and forgotten rooms. From there, I eventually found my way to Nightfall City, and I have to admit, I was immediately taken by it.
There was something deeply pleasant about the whole thing. The design, the layout, the restraint — everything seemed to belong to another internet, one that had not yet been buried under dashboards, feeds, pop-ups, infinite scrolling, and algorithmic noise. It reminded me a little of Pico, another place that once made me want to participate simply because it felt human.
But what really caught my attention was not only the visual style. It was the way the blog itself worked.
Well, well.
It was a Nex/NPS-style blog.
And honestly, I got ridiculously excited.
I had not seen something like that in years: a blog that could be read like a small textual place, where paths mattered, where the terminal felt welcome, where publishing did not require a bloated interface or a database pretending to be necessary. It felt old, but not obsolete. Small, but not poor. Technical, but strangely warm.
I even sent a few emails to the creator, just to say congratulations. I never received a reply — which, somehow, only made the whole thing more charming. So I thought: why not build one for myself?
And that was how soledade.city began.
The name Soledade is an old Portuguese word meaning “solitude” or “loneliness.” It has a quiet, archaic beauty to it. But it is also the name of my own little city, the place where I was born, in the south of Minas Gerais, Brazil. A small town with fewer than seven thousand people, but one that has my heart completely. Soledade is not just a word to me. It is a memory, a landscape, a place of origin.
So I created a Python virtual environment and started building.
The idea was simple: no CMS, no database, no admin panel, no framework, no unnecessary machinery. Just text, files, and a small set of Python scripts doing exactly what they needed to do.
At its core, soledade.city is a tiny Python system built almost entirely on the standard library. pathlib keeps the project’s paths clean and readable, separating content/, public/, templates/, secrets/, and logs/ without turning the code into a mess of string manipulation. The only meaningful external dependency is markdown, used by build.py to transform .md files into static HTML pages. I enabled small comforts like extra, toc, and sane_lists, enough to make writing pleasant without letting the project become a full-blown publishing platform.
The generated site lives in public/. That is the whole public face of the project: static HTML, RSS, sitemap, health check, and a custom 404 page. Caddy takes care of serving those files on the web and handling HTTPS. Python does not pretend to be a web server here. It writes files, rebuilds the site, and steps aside.
For safety and correctness, the code uses html when escaping HTML content and xml.sax.saxutils when generating XML for the feed and sitemap. datetime and email.utils handle proper dates for health.txt, RSS, and sitemap entries. The project is small, but I wanted the boring details to be right.
The more peculiar part is outside the static generator.
Soledade also runs two small TCP services using Python’s socketserver. One listens on port 1900 and behaves like a minimal reading protocol: the client sends a path, and the server returns the raw Markdown. The other listens on port 1915 and handles publication: send a path, a token, the Markdown body, and a final line containing only a dot. If the token is valid, the server writes the file into content/ and rebuilds the site.
For the publishing token, I used secrets.compare_digest, because even a tiny system should not be careless when checking secrets. The publication service is still intentionally plain — no login screen, no session, no browser interface — but it respects the basics: path validation, token validation, size limits, logs, and firewall rules.
That is the strange little heart of the project: internally, it is just a static site generator; externally, it behaves like a small textual city. You can visit it in a browser like a normal website, subscribe to the RSS feed like it is 2005, or talk to it from the terminal with ncat.
Reading is asking for a path.
Publishing is sending a path, a token, a body, and a dot.
That is all.
And that is exactly the point.
Soledade is not trying to become WordPress, Medium, Substack, or yet another “content platform.” It is intentionally small. It is a place for Markdown files, static pages, terminal rituals, and quiet publishing. A little city of text, named after another little city, built against the obesity of the modern web.
The project is already alive at soledade.city, though there is still plenty to improve. But that feels right. Small places should grow slowly.
Member discussion