./blog.sh: blogovací engine, kterému stačí terminál

29. 9. 2026
Doba čtení: 6 minut

Sdílet

blog.sh
Autor: Daniel Šnor
Minimalistický blogovací engine ./blog.sh se obejde bez databáze, závislostí a administrace. Píše se z terminálu v Markdownu, komentáře obstará Fediverse a 22 importérů přinese vše, co jste napsali jinam.

První článek na mém blogu vypráví o fotce, kterou jsem v roce 2012 nahrál na Instagram. Odkaz na ni funguje dodnes. Fotka ne. Z téhle drobnosti vzniklo pravidlo, na kterém celý ./blog.sh stojí: text i média patří domů, na vlastní disk, do souborů, které přežijí libovolnou platformu. Všechno ostatní – architektura, funkce i to, co engine schválně neumí – se z něj dá odvodit.

Soubory místo databáze

Blogovací engine ./blog.sh se celý ovládá z terminálu. Každý příspěvek je jeden soubor JSON na disku, web je statický build a publikování je příkaz. Pod kapotou běží Ruby – jen standardní knihovna, žádné gemy – obalené bashem. Žádné npm, žádný lockfile. Instalace:

git clone https://github.com/DanielSnor/blog.sh.git
cd blog.sh && ./setup.sh
./blog.sh add
./blog.sh preview
blog.sh

 Průvodce v terminálu

Autor: Daniel Šnor

Setup je průvodce (mluví anglicky, česky i německy), který odpovědi validuje hned při zadání – překlep v časové zóně, jenž by jinak tiše posunul datum každého článku, prostě nepustí dál. Koncept si prohlédnete přes QR kód na telefonu, publikování lze rozložit do naplánovaných slotů a archiv se prochází fulltextem přímo v terminálu příkazem  browse.

Píše se v Markdownu, HTML znát netřeba. Parser z textu staví typované bloky: tabulky, kód, úkolové seznamy, fotogalerie z obrázků položených vedle sebe i přepisy chatů. Adresa z YouTube, Vimea, Spotify nebo SoundCloudu se sama promění v přehrávač, žádný vkládací kód se nekopíruje. Referenční příručka syntaxe je součástí každého postaveného webu na adrese /markdown/ a generuje ji sám parser – příklady se proto chovají přesně tak, jak se zachovají ve skutečném článku.

Čistě terminálové založení přitom v jednom místě odlehčuje – volitelně, a jen na iOS. Stránku /write/ je možné na iPhonu nebo iPadu přidat na plochu a sepsat na ní příspěvek i publikovat ho mimo počítač; engine si před odesláním vytvoří stvrzenku a stránka se pak ptá, jak to dopadlo, dokud nedostane odpověď, takže příspěvek odeslaný beze signálu se najde, jakmile se telefon vrátí na síť. Kdo tuhle volbu zapne, přidává do jinak čistě statické architektury jeden malý přijímací bod – ten ale zůstává kanálem pro odeslání jednoho příspěvku, nestává se webovou administrací. Vlastnosti příspěvku – sérii, štítky, typ – navíc je možno měnit z obrazovky bez otevření celého textu v editoru.

Proč terminál a ne webová administrace

Terminál není póza, ale pragmatická volba. Statický web, který obsahuje jen články a média, poběží doslova kdekoliv – na CDN, na GitHub Pages, na nejlevnějším webhostingu i na Raspberry Pi v obýváku. Server nemusí nic vykonávat, jen podávat soubory. Systém s webovou administrací potřebuje běhové prostředí a zpravidla i databázi, takže výběr hostingu se řídí tím, co kde běží.

Druhý důvod je bezpečnostní. Webová administrace jsou dveře vystavené celému internetu: přihlašovací formulář, který lze zkoušet donekonečna, sezení, která lze ukrást, záplaty, které je nutné nasadit včas. Tuhle hru musí hrát každý systém s veřejnou administrací – patří to k povaze dveří, ne ke kvalitě produktu. Ve výchozím stavu ./blog.sh žádné takové dveře nemá: na serveru se nic nespouští, není kam vkládat kód a není se kde přihlásit. Volitelné publikování z telefonu zmíněné výše je jediná výjimka – vědomý kompromis pohodlí za jeden malý přijímací bod navíc, ne návrat k plnohodnotné administraci.

blog.sh

 Ovládací rozhraní v terminálu

Autor: Daniel Šnor

Stejná logika pokračuje o patro níž. Bez externích závislostí není co podvrhnout v aktualizaci balíčku, bez pluginů není co záplatovat. Bezpečnostní firma Patchstack napočítala kolem WordPressu za jediný rok bezmála osm tisíc zranitelností, naprostou většinu z nich v rozšířeních třetích stran – samotné jádro je podle téže firmy solidní. To není výtka, ale přirozená daň za ekosystém, který postaví cokoliv; ./blog.sh ji neplatí, protože rozšíření nemá.

Nakonec tu ani není co ukrást: web nevede uživatelské účty, neukládá hesla ani osobní data návštěvníků. Kdyby se přesto něco pokazilo, je celý web reprodukovatelný z vašeho disku – git, rebuild, deploy, deset minut. Neprůstřelné není nic a server i SSH klíče je pořád třeba udržovat; útočné plochy ale zbývá řádově méně.

Komentáře obstará Fediverse

Vlastní komentářový systém engine nemá. Publikovaný článek se automaticky oznámí na Mastodonu, nebo na Bluesky, a odpovědi na oznámení jsou komentáře – prohlížeč čtenáře si je stáhne z veřejného API sítě a zobrazí pod článkem. Diskusi lze i moderovat, a to netradičně: zobrazí se jen odpovědi, které autor na síti ohvězdičkoval, takže moderačním rozhraním je mobilní aplikace, kterou nosí v kapse.

blog.sh

Článek s komentáři načtenými z Mastodonu

Autor: Daniel Šnor

Kompromis přiznávám otevřeně: komentovat může jen držitel účtu na dané síti a debata žije na síti, ne na webu. Výměnou odpadá spam, správa cizích dat na vlastním disku i cizí JavaScript na stránce.

Blog jako archiv

Nejzajímavější kapitola ale není o psaní nových textů, nýbrž o záchraně starých. Engine má 22 importérů: sociální sítě od Facebooku a Instagramu přes Twitter/X a Threads po Mastodon a Bluesky, blogovací platformy od WordPressu přes Medium a Substack po Tumblr, podcasty – a Wayback Machine pro blogy, jejichž platforma už vůbec neexistuje. Přesně tak jsem vytáhl svoje posty z Posterousu, služby mrtvé od roku 2013.

blog.sh

 Výsledný blog jako statická stránka

Autor: Daniel Šnor

Importéry zásadně čtou oficiální exporty, ne živá API. Export je totiž ve většině světa právní nárok: nevyprší, nezdraží a nepotřebuje vývojářský účet, který může kdykoli zaniknout. Výjimkou jsou tři zdroje – Bluesky, Tumblr a LiveJournal – které vydají veřejný archiv každému bez tokenu, takže se čtou přímo ze sítě. Při stavbě facebookového importéru mimochodem vypadlo číslo, které stojí za zamyšlení: na referenčním exportu bylo 95 % příspěvků jen zrcadlením obsahu odjinud, z Twitteru, z Posterousu, z celé éry crosspostování. Kopie přežily originály.

Aby to nebyla jednosměrka, dodává se s enginem i cesta ven: příkaz export vysype celý archiv do markdownových souborů ve struktuře, kterou čte Jekyll a s jedním řádkem konfigurace i Hugo, Eleventy nebo Astro. Kruhový test export–import je součástí testovací sady.

Pojistky v detailech

Fotky při vložení do archivu automaticky přijdou o GPS souřadnice, údaje o fotoaparátu a expozici zůstávají. HEIC z iPhonu engine odmítne a vypíše konverzní příkaz, případně jej převede sám. Příkaz doctor vypíše všechny tiché chyby konfigurace najednou: špatnou časovou zónu, widget bez výstupu, deploy nastavený napůl. Build s podezřele menším počtem souborů než minule se nenasadí, protože rozbitý build vypadá pro rsync --delete stejně jako úmysl.

Přejmenovaný článek nechá na staré adrese trvalé přesměrování – odkaz ve dva roky starém tootu nikdy neskončí na chybě 404. U projektu, který vznikl kvůli link rotu, by cokoli jiného byla ostuda. Nic z toho nejsou efektní hračky – je to důkaz, že za minimalistickou fasádou stojí nástroj provozně promyšlený stejně pečlivě jako mnohem větší publikační platformy.

Komu je určen a komu ne

Nástroj ./blog.sh je pro jednoho člověka, který je v terminálu jako doma a chce vlastnit celý svůj archiv včetně toho, co kdy napsal jinam. Není pro více autorů na jednom webu ani pro nikoho, kdo chce webovou administraci. Limity přiznává otevřeně: jedno vestavěné téma (byť s výměnnými barevnými paletami a vlastním CSS), žádné pluginy, žádný newsletter, žádná monetizace.

webcast HP

Se zavedenými systémy se proto nepřetahuje. WordPress podle statistik W3Techs pohání přes 40 % webu a jeho ekosystém postaví cokoliv od e-shopu po redakci, Wix a Squarespace vyhrávají pohodlím, Ghost je výborná volba pro placené publikování a Hugo zůstává bleskový builder s obrovským výběrem témat. ./blog.sh odpovídá na jinou otázku: co když chci psát z terminálu, mít každý soubor svého blogu na svém disku – a pod jednou střechou i všechno, co jsem za dvacet let napsal na cizí platformy?

Engine je open source pod licencí MIT. Domovská stránka projektu blogsh.app běží na enginu samotném – každá stránka tam byla postavena a nasazena nástrojem, který popisuje. Druhou instalací je můj blog sean.cz. Zdrojové kódy, dokumentace a issues najdete na GitHubu v repozitáři DanielSnor/blog.sh.

Autor článku

Pracuje v IT přes třicet let – jako systémový inženýr, programátor a projektový manažer. Ve volném čase tvoří nezávislé projekty pro český Fediverse.