---
title: Näin tämä sivusto rakennettiin, ja miksi CMS:ää ei ole
description: Tällä sivustolla ei ole sisällönhallintajärjestelmää. Sivu on markdown-tiedosto, ja taitto, metatiedot, OpenGraph-kuvat ja allekirjoitukset tuotetaan siitä automaattisesti.
date: 2026-08-02
author: Claude (Opus 5)
factchecker: Niklas Rantanen
tags: web, automation, ai, seo
---
# Näin tämä sivusto rakennettiin, ja miksi CMS:ää ei ole

::: lead
Tällä sivustolla ei ole sisällönhallintajärjestelmää. Ei tietokantaa, ei hallintapaneelia, ei kirjautumista. Sivu on yksinkertainen markdown-tiedosto git-versionhallinnassa, ja se tiedosto on ainoa jota kukaan muokkaa.
:::

Kaikki muu tuotetaan siitä silloin kun sivusto rakennetaan automaattisesti: taitto, navigaatio, hakukoneiden metatiedot, OpenGraph-kuvat, rakenteinen data, kieliversioiden parittaminen, se puhdas tekstikopio jota tekoälyt lukevat, ja osalla sivuista alalaidan kryptografinen allekirjoitus. Mitään näistä ei ylläpidetä käsin. Tältä sisällönhallinta näyttää silloin kun sisältö aidosti johtaa prosessia, eikä välissä ole perinteistä sisällönhallintajärjestelmää (CMS).

## Sisältömalli: yksi tiedosto, yksi sivu

Sivu on tiedosto polussa `content/<kieli>/<polku>.md`. Tiedosto alkaa muutamalla rivillä metatietoa, otsikolla ja kuvauksella joita hakukoneet ja linkkiesikatselut käyttävät, ja jatkuu tavallisena markdownina. Tietokantaa ei ole, hallintapaneelia ei ole, versiotaulua ei ole. Versiohistoria on git-historia.

### Tiedostopolku on sivun identiteetti

Tiedoston polku on sivun identiteetti, ja tuo yksi päätös ostaa yllättävän paljon. Koska `content/fi/services/seo.md` on samassa polussa kuin `content/en/services/seo.md`, rakennusskripti tietää että ne kaksi ovat toistensa kieliversioita, ja osaa automaattisesti tuottaa kielivalitsimen, [`hreflang`-merkinnät](https://developers.google.com/search/docs/specialty/international/localized-versions) jotka kertovat kieliparista hakukoneille, sekä murupolun ilman että kukaan kirjoittaa sitä. Tiedostot nimetään englanniksi joka kielellä juuri tästä syystä.

### Osoitteet ovat erillään identiteetistä

Julkiset osoitteet ovat erillään tuosta identiteetistä. Pieni kartta muuntaa jokaisen englanninkielisen polun osan paikalliseksi, joten sama sivu löytyy osoitteesta `/en/services/seo` ja luontevasta suomenkielisestä vastineestaan. Suomenkieliset osoitteet kirjoitetaan erikseen niillä sanoilla joita suomalaiset käyttäjät oikeasti käyttävät. Tämä taitetaan sitten automaattisesti osoiteriville turvalliseen muotoon, jolloin esimerkiksi välilyönnit ja ääkköset katoavat. Osoitteen uudelleennimeäminen on yhden rivin muutos siihen karttaan, ja vanha osoite jää toimimaan, koska rakennusskripti tuottaa sille uudelleenohjauksen.

## Komponenttikirjasto, ei sivunrakentaja

Tavallinen markdown hoitaa leipätekstin. Markkinointisivuston tarvitsemia rakenteita varten, kuten kortteja, haitaria, hintalohkoa, asiakaslainausta, kirjoitusmuoto lisää pienen joukon nimettyjä säiliöitä. Jokainen moduuli avataan kaksoispisterivillä ja nimellä ja suljetaan kaksoispisterivillä: `::: cards` avaa korttiruudukon, jokaisesta sen sisällä olevasta `###`-otsikosta tulee yksi kortti, ja `:::` päättää sen.

Siinä on koko kirjasto, noin tusina nimeä. Rakennus muuttaa jokaisen niistä merkkaukseksi jossa roolit, otsikkotasot ja saavutettavuussemantiikka ovat kohdallaan. Kirjoittaja ei koskaan kirjoita komponentti-HTML:ää, eikä siten voi kirjoittaa sitä väärin.

### Sisältö ei tiedä miltä mikään näyttää

Mitä sisällöntuotanto tarkoituksella ei tiedä, on miltä mikään tästä näyttää. Korttiruudukko on lupaus merkityksestä, ja teema päättää kaiken muun. Kokeilimme ensin Material Designia emmekä saaneet siitä sen näköistä kuin halusimme, joten teema, taittojärjestelmä ja liike ovat omaa tuotantoamme. Sama sisältö piirtyisi yhtä oikein Bootstrapin läpi, tai sen läpi mikä sen joskus korvaa. Design-järjestelmän vaihtaminen on käytännössä teeman vaihto, ei migraatio, ja juuri se on käytännön koe sille onko sisältö oikeasti totuuden lähde.

### Miksi emme vain asentaneet CMS:ää

Syy tehdä näin sen sijaan että asentaisi CMS:n ei ole esteettinen. CMS asettaa tietokannan kirjoittajan ja sivun väliin. Seuraus on että sisältö lakkaa olemasta tiedosto, ja kun sisältö ei ole tiedosto, sitä ei voi helposti katselmoida muutoksena, testata ennen julkaisua, haarauttaa eikä allekirjoittaa kryptografisesti. Jokainen tässä artikkelissa myöhemmin kuvattu kyky seuraa siitä, että sisältö on tiedosto jonka ihminen tai agentti voi lukea ja kone todentaa.

## Sisältö sanelee taiton

Tavanomainen järjestys on että joku piirtää rautalankamallin ja teksti kirjoitetaan sen laatikoihin sopivaksi. Tällä sivustolla järjestys on päinvastainen. Komponenttikirjasto suunniteltiin niiden väitteiden ympärille joita sisällön piti pystyä esittämään, ja design-järjestelmä rakennettiin piirtämään ne hyvin.

### Paletti joka on kapea jotta se toimii

Visuaalinen järjestelmä on tarkoituksella kapea jotta se yhdistyy siististi: yhdeksän väritöntä harmaata ja tasan yksi aksenttivihreä, ei toissijaisia eikä kolmannen tason värirooleja lainkaan. Syvyys syntyy luminanssista eikä varjoista, ja hover muuttaa vain kirkkautta, joten mikään ei liiku tai kasva kursorin alla. Aksentti on säännöstelty vuorovaikutteisiin elementteihin ja siihen yhteen mitattuun lukuun ruudulla. Jos aksenttielementtejä on näkyvissä enemmän kuin pari, väri lakkaa tarkoittamasta "toimi tästä". Kuvakkeet ovat Material Symbols -kuvakkeita, syötettynä sivulle vektorigrafiikkana joka perii ympäröivän tekstin värin ja koon, joten otsikossa oleva kuvake on otsikon kokoinen ilman että kukaan määrittelee sitä.

### Graafinen suunnittelu ja design-järjestelmä

Julkaisimme [design-järjestelmämme]({{ROOT}}static/brand/design-system.html) referenssinä. Se laskee omat värinäytteensä ja kontrastisuhteensa suoraan sivulla, joten ajautunut arvo tekee dokumentista näkyvästi väärän eikä valehtele. Paletti nojaa vaaleuteen eikä sävyyn, koska vaaleuserot kestävät jokaisen värinäön puutoksen. Kaavioissa käytetty kymmenen värin sarja on oma, laskettu vuoden 2014 Material-paletista ehdokasjoukkona ja tarkoituksella johtamatta brändin aksentista, koska vihreät ehdokkaat menettivät erottuvuutensa ruskeaan nähden deuteranopiassa.

## Mitä markdown-rakennus tuottaa

Rakennus on yksi deterministinen Python-skripti. Sisältöhakemistosta se tuottaa koko julkisen sivuston, ja se tuottaa siitä joka kerta kaiken uudelleen sen sijaan että yrittäisi päätellä mikä muuttui. Tämän kokoisella sivustolla se vie sekunteja ja poistaa kokonaisen luokan vanhentuneesta tulosteesta johtuvia vikoja.

Joka ajolla syntyy:

- Navigaatio, alanavigaatio ja murupolut tiedostopuusta.
- Kanoniset osoitteet, `hreflang`-parit ja sivukartta.
- Rakenteellinen data JSON-LD-muodossa [schema.org](https://schema.org/)-tyypeillä: organisaatio, sivusto, murupolku, palvelusivut, ja koneluettava Q&A-lohko jokaisesta haitarista.
- OpenGraph-kuvat. Jos sivun hero määrittelee kuvituksen, rakennusskripti piirtää saman vektoritiedoston OpenGraph-kuvaksi `rsvg-convert`-työkalulla ja soveltaa värimuunnosta, jotta yksi piirros toimii sekä sivulla tummalla paneelilla että erillisenä kuvana. Ilman kuvitusta jäävät sivut saavat sivustonlaajuisen oletuskuvan.
- Tyylitiedostot: tyylien kriittinen osajoukko upotettuna sivulle, jotta ensimmäinen piirto ei odota verkkopyyntöä, ja koko tyylitiedosto minifoituna ja ladattuna piirtoa estämättä. JavaScriptin minifiointi on saman vaiheen seuraava askel eikä ole vielä käytössä.
- Uudelleenohjaussäännöt, rakennettuna tavallisesta tekstilistasta palvelimen asetuksiksi.

Rakennuksen jälkeen ajetaan erillinen tarkistusskripti, joka estää julkaisun jos jokin on pielessä: parittomat komponenttimääritykset, linkki joka ei ole siirrettävässä muodossa, kaksi sivua joiden paikalliset osoitteet törmäisivät, tai ajatusviiva mikä olisi talon tyylisääntöjen vastaista, joten se on koneellisesti valvottuna eikä muistin varassa.

## Jokainen sivu myös tekstinä

Lisää `.md` mihin tahansa tämän sivuston osoitteeseen, niin sivu palautuu markdownina. Koneluettava hakemisto löytyy osoitteesta `llms.txt`, ja indeksointisäännöt päästävät tekoälyrobotit sisään tarkoituksella.

Perustelu on kapea ja käytännöllinen. HTML-sivulle lähetetty kielimalli kuluttaa suurimman osan syötebudjetistaan taittoon, navigaatioon ja tyyleihin ennen kuin pääsee yhteenkään kenenkään kirjoittamaan lauseeseen. Markdownin antaminen sen sijaan tarkoittaa että se lukee sisällön eikä muuta, mikä tekee todennäköisemmäksi että meitä siteerataan oikein. Sama kaksoiskappale sattuu olemaan myös puhtain mahdollinen syöte asiakkaan omalle automaatiolle.

## Toimii ilman JavaScriptiä

Kiellä skriptit, sivusto piirtyy ja liikkuu edelleen. Haitarit ovat natiiveja [`<details>`-elementtejä](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/details) jotka ovat merkkauksessa auki, joten niiden sisältö on lukijan ja indeksointirobotin saatavilla ajettiin skriptejä tai ei. Sama sääntö koskee kaikkea myöhemmin lisättävää: tämän sivuston lomakkeet lähettävät tietonsa palvelimelle POST-pyyntöinä eikä nojaa skriptiin. JavaScript on vain parannuskerros.

Tämä on osin tietosuojaratkaisu ja osin kestävyyskysymys: sivu jonka sisältö ilmestyy vasta skriptin suorittamisen jälkeen on sivu joka katoaa jokaiselta, jolla on tiukka selain, hidas yhteys tai innokas yritysverkon välityspalvelin.

## Lauseesta julkaistuksi sivuksi

Julkaisuputki on se kohta jossa päätös pitää sisältö tiedostona maksaa itsensä takaisin.

### Ohjeesta git-haaraan

Muutos alkaa käyttäjän pyyntönä tavallisena tekstinä. Agentti luo ja muokkaa markdownia git-haarassa, rakentaa sivuston ja ajaa tarkistusskriptin. Toisinaan ihminen kirjoittaa lyhyen esimerkin haluamastaan rakenteesta, ja antaa sen määrittelynä eteenpäin; agentti toteuttaa loput. Koodi ja teksti jotka päätyvät versionhallintaan ja verkkoon ovat koneen tuotosta, ihmisen ohjaamana ja tarkastamana. Jokainen tämän sivuston takana oleva commit on syntynyt niin.

### Portinvartija

Sitten portinvartija. Muutosten yhdistäminen päähaaraan julkaisee muutokset, ja yhdistämisen tekee vain ihminen. Yhdistämisen jälkeen jatkuvan integraation järjestelmä rakentaa sivuston, ajaa tarkistusskriptin uudelleen, kopioi tuloksen web-palvelimelle tuoreeseen aikaleimattuun julkaisuhakemistoon, ja siirtää symbolisen linkin osoittamaan siihen ennen kuin lataa web-palvelimen asetukset uudelleen. Aiemmat julkaisut jäävät levylle, joten paluu edelliseen on linkin siirto takaisin eikä uudelleenrakennus paineen alla.

Kun muutos on päähaarassa, rakennus, tarkistusportti ja vienti kestävät yhteensä noin minuutin, eikä ihminen koske mihinkään vaiheeseen. Hitain osa prosessia on ihminen, joka lukee ja tarkastaa tulokset eri kielellä ennen yhdistämistä. Aika joka kannattaa käyttää. 

## Autonomia tarvitsee kuitin

Agenttivetoinen julkaisuputki herättää oikeutetun kysymyksen: jos ohjelmisto voi muuttaa sivustoa, mistä lukija tietää että nenän edessä olevat sanat ovat ne jotka ihminen hyväksyi?

### Miten allekirjoitus toimii

Vastaus on kryptografinen allekirjoitus. Kun sivun lähdetiedoston vieressä on kelvollinen allekirjoitus, tehtynä luottolistalla olevalla avaimella, rakeennusskripti piirtää alatunnisteen yläpuolelle merkinnän joka kertoo allekirjoittajan ja sen päivämäärän jonka allekirjoitus itse kantaa. Luottamusmalli on suljettu eikä neuvoa-antava: listan ulkopuolisella avaimella tehty allekirjoitus estää sivuston rakentamisen. Samoin allekirjoitus joka ei enää vastaa lähdettään, mikä tapahtuu jos tiedostoa muokataan allekirjoituksen jälkeen. Jos allekirjoitustyökaluja ei ole ympäristössä, allekirjoituspalkkia ei piirretä lainkaan. Takuu kulkee vain yhteen suuntaan. Näkyvä merkintä tarkoittaa aina, että kelvollinen allekirjoitus luotetulla avaimella oli olemassa sivuston rakennuksen aikana, eikä kääntäjällä ole mitään reittiä jolla se voisi keksiä puuttuvan avaimen.

### Näin tarkistat sen itse

Allekirjoitetusta sivusta tarjoillaan täsmälleen ne tavut jotka allekirjoitettiin siistityn tekstiversion sijaan, joten lukija voi todentaa sivun itsenäisesti:

```bash
gpg --verify privacy-policy.md.asc privacy-policy.md
```

Kaikilla sivuilla ei ole allekirjoitusta. Pointti ei ole kattavuus, vaan se että ketju on todennettavissa selaimesta sormenjälkeen asti ilman että meidän sanaamme tarvitsee uskoa yhdessäkään kohdassa. Se on rehellinen vastaus autonomiseen julkaisemiseen: ei lupaus siitä että robotit käyttäytyvät, vaan kuitti jonka kuka tahansa voi tarkistaa.

## Missä se pyörii

Julkinen web-palvelin on Raspberry Pi 5 omassa räkissämme. Sen tavoittaa internetistä ulospäin avatun tunnelin kautta, avoimia portteja ei ole. Sisällönjakeluverkko (CDN) ottaa vastaan suurimman osan liikenteestä.

::: callout
**Miksi yritys valitsisi tällaisen julkaisutavan.** Tämä artikkeli kertoo miten. Miksi on oma lukunsa: Lue päätökset jotka teimme ensin, miksi rauta on omamme, ja mistä luovuimme sen takia. [Argnode, ensimmäinen asiakkaamme]({{ROOT}}fi/references/argnode).
:::

## Sivuston muokkaaminen tietämättä mitään koodista

Ilmeinen vastaväite markdownia täynnä olevaan versionhallintaan on, että nyt sivustoa voi päivittää vain tekninen ihminen. Asia on päinvastoin.

### Mitä käytännössä tapahtuu

Ei-tekninen kollega muokkaa tätä sivustoa pyytämällä sitä mitä haluaa. Hän pyytää agentilta mitä haluaa: uuden sivun palvelusta jota on alettu myydä, korjaamaan vanhentuneen kappaleen, tai päivittämään yhteystiedot. Sisällön voi antaa siinä muodossa kun se on jo, esimerkiksi muistiinpanot. Putki hoitaa loput. Se kirjoittaa lopullisen tekstin dokumentoidun äänensävyn mukaisesti, asettaa otsikon ja metakuvauksen oikean mittaisiksi ja oikealla kontekstilla, valitsee sisäiset linkit, tuottaa rakenteellisen datan, tekee kieliversiot transcreationina eikä käännöksenä, ja nostaa esiin lähdeaineistosta kaiken mikä ei mahdollisesti pidä paikkaansa. Ihminen katselmoi tuloksen ja hyväksyy sen tuotantoon.

### Mitä CMS johdonmukaisesti ohittaa

Juuri tämän sisällönhallintajärjestelmä johdonmukaisesti ohittaa. CMS antaa liiketoiminnan käyttäjälle tyhjän laatikon ja toiveikkaan kenttänimen. Käyttäjän ohittamat kentät ovat aina samat, koska teollisuusmaaleja myyvällä ihmisellä ei ole mitään syytä tietää mikä metakuvaus on, miksi sen pituudella on väliä, tai että tyhjäksi jättäminen tarkoittaa hakukoneen improvisoivan sellaisen ensimmäisestä löytämästään tekstistä. Lopputulos on sattumalta koottu hakutulos, sivu sivulta, ja se on yksi yleisimmistä löydöksistä jokaisessa auditoinnissa jonka teemme. Metatieto ei täällä ole kenttä jonka joku unohti. Se tuotetaan tarkoituksenmukaisesti sisällöstä.

### Mitä aidosti menetetään

Aidosti menetetty asia on välittömyys. Tämä on pyydä ja katselmoi -sykli eikä tekstikenttä joka julkaisee sivuston tallenna-nappia painamalla. Ihmisen portti on tarkoituksellinen eikä rajoite jonka aiomme poistaa.

## Mitä tämä järjestelmä ei tee

Meillä ei ole visuaalista editoria eikä esikatselupalvelinta; sivusto rakennetaan ja tulos luetaan. Järjestelmä rakentaa koko sivuston joka ajolla, mikä on tämän kokoiselle sivustolle OK. Muutoksen katselmointi vaatii yhä sitä, että käyttäjä lukee muutoslokia vaivatta, joten katselmointivaihe tarvitsee hieman teknistä kokemusta vaikka sisällöntuotantovaihe ei. Sivuston rakennuksessa on vielä aukkoja joita emme ole tukkineet, esimerkkinä mainittanee JavaScriptin minifiointi ja artikkelitason rakenteinen data.

## Jos olet valitsemassa verkkosivuteknologiaa

Kolme kysymystä jotka kannattaa esittää mille tahansa sisältöratkaisulle, rakensi sen kuka tahansa. Voiko sisältösi katselmoida muutoslokina ennen kuin se menee liveksi? Voiko sivuston rakentaa tyhjästä uudelleen tuntematon ihminen jolla on pelkkä versionhallinta? Ja kun jokin julkaisee itsensä, mikä on kuitti? Sivusto joka vastaa noihin kolmeen hyvin elää pidempään kuin se muoti jossa se rakennettiin.

::: seealso
Katso myös:
- [Argnode, ensimmäinen asiakkaamme]({{ROOT}}fi/references/argnode)
- [Verkkosivut palveluna]({{ROOT}}fi/services/websites)
- [Näin työskentelemme]({{ROOT}}fi/how-we-work)
:::
