# Blog - Treści dla ludzi i modeli AI

> Blog, który czyta człowiek i cytuje model AI

Wpis to strona wiki z metadanymi. Piszesz zwykły markdown, a serwer składa z niego stronę z gotowymi blokami, wersję markdown dla modeli AI, dane strukturalne i feedy. Lint sprawdza wpis przed publikacją.

## Funkcje

- **Wpis to strona wiki z metadanymi**: Treść wpisu żyje w wiki, a osobny wiersz metadanych trzyma adres (slug), opis, autora, tagi, język, powiązanie z tłumaczeniem, okładkę i datę weryfikacji. Strona wiki bez tych metadanych nie jest wpisem. Opublikowany wpis jest dostępny bez logowania pod /blog/{slug}.
- **Bloki wpisu**: Zwykły markdown wystarcza na wyróżnienia, TL;DR, cytat z autorem, obrazek z podpisem, kod z przyciskiem kopiowania, FAQ, kroki, tabelę porównawczą, wykresy z tabeli, diagramy Mermaid i okno terminala. HTML bloków generuje serwer, a treść autora jest sanityzowana, więc własne skrypty, klasy i identyfikatory nie trafią na stronę.
- **Bliźniak markdown dla modeli AI**: Każdy wpis ma wersję markdown pod adresem /blog/{slug}.md, a lista bloga pod /blog/index.md. Ten sam dokument dostaje klient, który prosi o Accept: text/markdown. Źródłem każdej grafiki jest tekst, więc model widzi dane wykresu i opis diagramu, nie tylko obrazek.
- **Dane strukturalne JSON-LD**: Strona wpisu niesie BlogPosting i BreadcrumbList w formacie JSON-LD. Z bloków FAQ, kroków i wideo serwer dokłada FAQPage, HowTo i VideoObject, a wersje językowe wpisów są powiązane w mapie strony.
- **Feedy Atom, RSS i JSON**: Blog ma feedy /blog/feed.xml (Atom), /blog/rss.xml (RSS) i /blog/feed.json (JSON Feed) z pełną treścią 20 najnowszych wpisów, a czytniki znajdują je w nagłówku strony. Plik /llms.txt zawiera na żywo listę najnowszych wpisów z adresami markdown.
- **Lint wpisu pod AI**: Lint sprawdza opis, blok TL;DR, tekst alternatywny obrazków, kolejność nagłówków, opisowe teksty linków, datę weryfikacji i tłumaczenie. Wynik to lista problemów z numerem linii i poziomem (błąd, ostrzeżenie, informacja) oraz ocena 0-100. Ten sam wynik daje narzędzie MCP lint_blog_post, REST API i komenda monolynx blog lint.
- **Publikacja z bramką lintu**: Publikacja to osobna operacja: najpierw lint, potem wpis staje się publiczny. Wpis z błędami lintu zostaje prywatny, a odmowa wymienia reguły do poprawy; parametr force publikuje mimo błędów. Cofnięcie publikacji zdejmuje wpis i jego wersję markdown z sieci, a slug i data zostają, więc ponowna publikacja wraca pod ten sam adres.
- **Uprawnienie do edycji bloga**: Publikować, cofać publikację i zmieniać metadane wpisu może tylko konto z uprawnieniem do edycji bloga. Uprawnienie należy do konta, nie do roli w projekcie, jest domyślnie wyłączone, a nadaje je i odbiera wyłącznie superuser na stronie edycji konta; właściciel ani admin projektu go nie nada. Ta sama reguła obowiązuje w panelu, MCP, REST API i CLI, także przy oznaczaniu strony wiki jako publicznej. Konto bez uprawnienia dostaje odmowę (403 w REST API), nic nie jest zapisywane, a narzędzia zapisu bloga nie pojawiają się na jego liście narzędzi MCP. Czytanie wpisów i lint wymagają tylko prawa odczytu wiki.
- **Podgląd szkicu**: Przycisk „Podgląd wpisu” na stronie wiki otwiera szkic w wyglądzie publicznego bloga, zanim zaznaczysz „strona publiczna”. Podgląd widzi tylko zalogowany użytkownik z prawem odczytu wiki, a jego adres ma nagłówek noindex i nie trafia do mapy strony ani do feedów.
- **Skill blog-post i przewodnik dla każdego modelu**: Skill /monolynx:blog-post prowadzi wpis od briefu przez szkic i lint do podglądu, a publikuje dopiero po Twojej jawnej zgodzie. Publiczny przewodnik /blog-authoring.md opisuje składnię bloków, reguły lintu i operacje connectorów, więc wpis w tym formacie napisze też model bez pluginu.
- **Dostęp z terminala**: Grupa komend monolynx blog (list, get, meta, lint, publish, unpublish) działa na tych samych operacjach co narzędzia MCP, więc wpisy obsłużysz ze skryptu i z CI.

## Jak to działa

1. **Napisz szkic w wiki**: Utwórz prywatną stronę wiki z treścią w markdownie i blokami wpisu. Podgląd szkicu pokaże ją w wyglądzie bloga.
2. **Ustaw metadane**: Podaj opis, język, tagi i datę weryfikacji. Pierwszy zapis metadanych zamienia stronę wiki we wpis.
3. **Uruchom lint**: Popraw błędy z listy, aż nie zostanie żaden poziomu „błąd”. Ostrzeżenia nie blokują publikacji.
4. **Opublikuj**: Wpis trafia pod /blog/{slug} razem z wersją markdown, danymi strukturalnymi i feedami.
5. **AI pisze i publikuje przez MCP**: Agent AI przechodzi te same kroki connectorami, a publikację wykonuje dopiero po Twojej zgodzie. Konto, na którym pracuje agent, potrzebuje uprawnienia do edycji bloga.

## AI i MCP

Blog jest zbudowany tak, żeby agent AI mógł go i pisać, i czytać. Agent ustawia metadane wpisu, sprawdza go lintem, publikuje i cofa publikację - 6 narzędzi MCP.

- `list_blog_posts`: Lista wpisów bloga z metadanymi, także szkice; filtr published albo draft
- `get_blog_post`: Wpis bloga: metadane, adresy publiczne i treść markdown
- `set_blog_post_meta`: Metadane wpisu: slug, opis, autor, tagi, język, tłumaczenie, okładka, data weryfikacji; wymaga uprawnienia do edycji bloga
- `lint_blog_post`: Lint wpisu pod AI: lista problemów z linią i poziomem oraz ocena 0-100
- `publish_blog_post`: Publikacja wpisu po lincie: odmowa przy błędach, chyba że force; zwraca adresy i ocenę lintu; wymaga uprawnienia do edycji bloga
- `unpublish_blog_post`: Cofnięcie publikacji: adres wpisu i jego .md dają 404, data i slug zostają; wymaga uprawnienia do edycji bloga

## Szczegóły techniczne

- **Przechowywanie**: Treść wpisu to markdown strony wiki w MinIO, metadane (slug, opis, tagi, język, data publikacji) w PostgreSQL.
- **Renderowanie**: Markdown, a potem sanityzacja nh3 bez atrybutów class i id. Wykresy rysuje serwer jako SVG, animowane schematy pochodzą z zamkniętej listy komponentów.
- **Publiczne adresy**: /blog/, /blog/{slug}, /blog/{slug}.md, /blog/index.md oraz /blog/feed.xml, /blog/rss.xml i /blog/feed.json. Bez sesji i bez logowania.
- **Stabilność adresów**: Zmiana tytułu nie zmienia adresu, a poprzedni adres przekierowuje (301). Lista sortuje wpisy po dacie publikacji.
