Soledade and Bloggram, two experiments that stayed online
[37m╶── [97mgemlog[90m · 2026-11-12[0m
Some projects exist to be used. Others exist so I can find out how something works by building it from the ground up. Soledade and Bloggram are the second kind. Both are live, both work and you can use them today, but neither started with a business plan. They started with a question about how a thing is made.
Soledade, a town made of text
Soledade is a quiet blog in Portuguese, shaped like a small town. It shares its name with Soledade de Minas, the little town in the south of Minas Gerais where I first started taking things apart.
Soledade
The Soledade home page in a dark theme with a monospaced font. A purple bar at the top shows the command "echo | nc soledade.city 1900 | less". Below it, an ASCII drawing of a small town at night, with a church tower, houses with lit windows and stars, and the word "soledade" in orange. A short Portuguese text says the town sleeps with the lights on, and invites anyone who wants to live there to go to the registry office and send their texts through the mail at door 1915. Further down: the latest text, "Manifesto" by @pablo, and a corner of the square where the garden has dried up.
The first document in the project folder is a tutorial dated May 31, 2026, and its goal fits in one line: a minimal blog you can read in a browser or in a terminal. The next day came a stricter note. Keep it small. Markdown is the source of truth, HTML is the output, RSS and a sitemap from the start. It also listed what would ruin the idea: multiple users, a web panel and any ambition to become a platform.
Part of that list didn't survive. The town now has open citizenship, a mayor and letters between neighbors. It still has no web panel, though.
The town
Everything in Soledade hangs on one metaphor. Each author is a citizen with a house of their own at `/@name/`. Each topic is a neighborhood: Cinema, History, Books, Programming and a general one for everything else. The home page is the central square, where the newest writing shows up.
Then the town grew services. There's a registry office where you become a citizen, a post office where letters between residents hang on the wall, a newsstand, a monthly newspaper and a library with everything ever published. There's a community garden in the corner of the square that only blooms when three people water it on three different days, and each watering earns a small coin. There's a ledger for those coins, a street photographer who makes your portrait in ASCII, a bar with a notebook on the counter where everyone writes one signed line, and a lamppost where people glue unsigned notes.
None of it uses JavaScript. The whole town is static HTML, and all the logic runs at the moment something is published.
Reading from a terminal
Every page in Soledade has a command at the top, and that command is a real way in. Port 1900 answers like a Nex server: you send a path, it sends back plain text. On Linux or macOS:
echo mapa/ | nc soledade.city 1900 | less
That gives you the town map, straight in your terminal:
Mapa textual da cidade
\======================
Todos os caminhos de Soledade numa folha só.
Soledade/
├── Praça ..................... /
├── Bairros ................... /b/
│
├── Serviços:
│ ├── Cartório .............. /cartorio/
│ ├── Correio ............... /cartas/
│ ├── Banca de jornal ....... /banca/
No password, no cookie, no browser.
Publishing over the wire
Publishing is the unusual part. There's no login form anywhere. To publish, you open a connection to port 1915 and send a small text package in a protocol I made up for the town, called SOLED/2. It starts with the protocol name, then a few headers, a blank line, the body, and a single dot on the last line to say you're done.
The "Agência 1915" page of Soledade, dark theme and monospaced font, with an ASCII drawing of a mailbox. It explains in Portuguese how to send a package to the post office. A terminal example shows "ncat soledade.city 1915" followed by the lines SOLED/2, ACTION JANELA, CITIZEN, IDENTITY, a blank line, "lendo na varanda" and a single dot, and the server answering "200 janela". Below starts a table of accepted packages: PUBLISH, PREVIEW, LIST and REGISTER, with what each one takes, does and answers.
The server answers like a shop counter, with a number and sometimes a note: `200` when it worked, `401` when your identity doesn't match, `402` when you don't have enough coins, `409` when you already watered the garden today, `429` when you're sending too much too fast.
The protocol does a lot more than publish. `REGISTER` asks the registry office for citizenship. `JANELA` lights your window on the square for seven days, with one line of text. `PLACA` hangs a sign on your door. `FACHADA` takes CSS and paints the front of your pages. `REGAR` waters the garden, `RETRATO` hangs your ASCII portrait and `COMPRAR` spends your coins on a bench or a street lamp for the town. Every action is a few lines of plain text that you could type by hand.
The June version was much rougher than this. The first line was the path, the second a single secret token, then the body and the dot. Deleting a post meant sending the word `DELETE` as the body. The distance between that first version and a protocol with citizens, identities and error codes is the whole point of a learning project.
Under the floor
The code is Python, and only Python's standard library plus one package to read Markdown. There's no Django, no Flask and no database. Texts are `.md` files with a little front matter on top. Two small TCP servers listen on the two ports, one for reading and one for publishing. Every time a text is published, a build script wipes the public folder and generates the whole town again: pages, archives by year and month, neighborhoods, tags, RSS feeds for the town, for each citizen and for each neighborhood, a sitemap and a 404 page. Caddy serves the result and takes care of HTTPS.
Installing it on a fresh Debian server is one bash script that sets up the packages, a Python environment, the systemd services, Caddy and the firewall, and can be run again without breaking anything.
Every page ends with the same line: "Feito em texto. Servido por silêncio. Lido por navegador ou terminal." Made of text, served by silence, read by a browser or a terminal.
Moving in
Right now the registry book has one name on page one, mine, and the garden in the square is dry. That's the honest state of the town. If you read Portuguese and like the idea of publishing with `ncat`, the citizenship guide explains how to get a house. The garden could use some water.
citizenship guide
Bloggram, the same idea in another shape
Bloggram came from the same place: pick something I wanted to understand and build it until it works for real. This time the question was Telegram. A lot of good writing lives in Telegram channels, and almost none of it can be found from outside the app.
The Bloggram home page, plain black text on white in a serif font, with no images. The headline reads "Your Telegram channel, as a blog that search engines can find." Below it, a short paragraph explains that every post becomes a web page with its own address, title and description, a "Start your blog" link, a note that Bloggram is free, has no ads or trackers and runs without JavaScript, and a list titled "What you get" with an address like yourname.bloggram.lol, tag pages, resized photos, RSS and a sitemap.
Bloggram turns a Telegram channel into a blog that search engines can read. You add its bot to your channel as an administrator, and every post becomes a page with its own address, title and description, with tag pages from your hashtags, photos in several sizes, an RSS feed and a sitemap. Edit a post in Telegram and the page changes within seconds.
Bloggram
Where Soledade was Python and plain files, Bloggram is Go: one binary and one SQLite file, with no separate database, queue or cache server. The bot pulls updates from Telegram, puts the work in a job queue stored in SQLite and downloads the photos. Pages come out of a memory cache in a couple of milliseconds, without a line of JavaScript.
The puzzles were different too. Telegram never tells a bot when a channel post is deleted, so Bloggram has to go and check, often for recent posts and less often for older ones. For private channels, the check is an edit that changes nothing, which is why the bot needs the edit permission. And since anyone can open a channel in a minute, a new blog stays out of search engines until it has five posts, ten subscribers and three days of life.
The project also came with rules for how it's written: a failing test before any code, at least 80% test coverage, no new dependency without a good reason. And one more: keep the version at 0.01. It's still there.
Why bother
Neither of these is trying to be big. Both were built to learn, and both stayed online afterwards, so what came out of them is something other people can use, not just a folder on my disk.
If you try either one and something feels wrong, tell me. A town with one resident and a blog service at version 0.01 both have plenty of room to grow.
[37m──╴ [90mend of transmission[0m
Gemlog
Home