{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreig4tgdqh6iujr2p5gpgjbgnse5m7lmv7kfkdea66n7vwpu4c2krgy",
    "uri": "at://did:plc:iw5jw32bqqdf4bkbhotvf23m/app.bsky.feed.post/3mnakcp7ofqz2"
  },
  "description": "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.\n\nThere was something deeply pleasant about the whole thing. The design, the layout, the restraint — everything seemed ",
  "path": "/building-a-little-city-of-text/",
  "publishedAt": "2026-06-01T16:55:52.000Z",
  "site": "https://pablomurad.com",
  "tags": [
    "The Midnight Pub",
    "Nightfall City",
    "soledade.city"
  ],
  "textContent": "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.\n\nThere 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.\n\nBut what really caught my attention was not only the visual style. It was the way the blog itself worked.\n\nWell, well.\n\nIt was a Nex/NPS-style blog.\n\nAnd honestly, I got ridiculously excited.\n\nI 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.\n\nI 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?\n\nAnd that was how soledade.city began.\n\nThe 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.\n\nSo I created a Python virtual environment and started building.\n\nThe 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.\n\nAt 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.\n\nThe 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.\n\nFor 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.\n\nThe more peculiar part is outside the static generator.\n\nSoledade 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.\n\nFor 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.\n\nThat 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`.\n\nReading is asking for a path.\n\nPublishing is sending a path, a token, a body, and a dot.\n\nThat is all.\n\nAnd that is exactly the point.\n\nSoledade 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.\n\nThe project is already alive at soledade.city, though there is still plenty to improve. But that feels right. Small places should grow slowly.",
  "title": "Building a Little City of Text",
  "updatedAt": "2026-06-01T16:55:53.346Z"
}