<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Peltopiri – Blogi</title>
    <link>https://peltopiri.com/blogi</link>
    <atom:link href="https://peltopiri.com/rss.xml" rel="self" type="application/rss+xml"/>
    <description>Kirjoituksia WordPressistä ja WooCommercesta, SEO:sta, GEO:sta, saavutettavuudesta ja tekoälyagenteista.</description>
    <language>fi</language>
    <item>
      <title>Rakensin itselleni Kurikan lounaslistojen hakubotin</title>
      <link>https://peltopiri.com/blogi/kurikan-lounaslistojen-hakubotti</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/kurikan-lounaslistojen-hakubotti</guid>
      <pubDate>Sat, 24 Oct 2026 06:00:00 GMT</pubDate>
      <description>Botti hakee viiden kurikkalaisen ravintolan lounaslistat, Gemini muuttaa ne rakenteiseksi dataksi ja sivu näyttää päivän lounaat yhdessä paikassa.</description>
      <content:encoded><![CDATA[<p>Tein itselleni sivun, joka näyttää Kurikan lounaspaikkojen päivän lounaat yhdellä silmäyksellä: <a href="/lounas">peltopiri.com/lounas</a>. Botti hakee listat viiden ravintolan omilta sivuilta, Googlen Gemini-kielimalli muuttaa ne rakenteiseksi dataksi ja sivu näyttää joko tämän päivän tai koko viikon lounaat. Kerron tässä, miten se on tehty ja miksi kielimalli on tässä parempi kuin pelkkä HTML:n kaivaminen.</p>
<figure class="shots">
  <img src="/assets/blog/lounas/lounas-desktop.webp" alt="Kurikan lounaslistat -sivu työpöydällä: päivävalinta maanantaista lauantaihin ja viikko, alla perjantain lounaat ravintoloittain korteissa ruokavaliomerkintöineen." width="1200" height="750" loading="lazy">
  <img src="/assets/blog/lounas/lounas-mobiili.webp" alt="Sama sivu puhelimella viikkonäkymässä: Wanhan Aseman kortissa maanantain ja tiistain ruoat päivämäärineen." width="601" height="1303" loading="lazy">
  <figcaption>Päivänäkymä desktopissa ja viikkonäkymä mobiilissa.</figcaption>
</figure>

<h2 id="mika-vanhassa-versiossa-oli-vikana">Mikä vanhassa versiossa oli vikana?</h2>
<p>Minulla oli vanhalla sivustolla PHP-skripti, joka haki samat listat. Se latasi jokaisen ravintolan sivun, poimi XPath-valitsimella lounasosion HTML:n ja liimasi sen sellaisenaan omalle sivulleni. Välimuistina oli tekstitiedosto, joka vanheni tunnissa. Tämän päivän nimi korostettiin JavaScriptillä säännöllisellä lausekkeella.</p>
<p>Se toimi, mutta siivouskoodin tekeminen oli iso työ. Sivulle tuli viiden eri sivuston HTML, josta piti karsia kaikki ylimääräinen, jotta listat näyttivät samalta. Siivoussääntöjä kertyi: tämä otsikko pois, tuo lomake pois, hinta pois yhdeltä ravintolalta. Turhat sanat ja sitovat välilyönnit poistettiin säännöllisillä lausekkeilla. Kun ravintola vaihtoi sivustonsa teemaa, valitsin lakkasi löytämästä mitään. Sivulla luki silloin vain &quot;No menu found&quot;.</p>
<h2 id="miten-uusi-botti-toimii">Miten uusi botti toimii?</h2>
<p>Uusi versio on kaksi Firebasen Cloud Functionia samassa projektissa kuin tämä sivusto.</p>
<ol>
<li><strong>Ajastettu haku</strong> käynnistyy maanantaista lauantaihin neljä kertaa päivässä. Se hakee ravintoloiden sivut ja poimii lounasosion tekstinä <a href="https://cheerio.js.org/">Cheeriolla</a>. Rivinvaihdot säilyvät, jotta listan rakenne näkyy.</li>
<li><strong>Gemini jäsentää tekstin.</strong> Teksti lähtee Vertex AI:n kautta Gemini 3.5 Flash-Lite -mallille yhdessä JSON-skeeman kanssa. Skeema määrää, mitä vastauksessa on: viikkonumero, päivät, ruoat, ruokavaliomerkinnät, hinnat ja lisukkeet. Vertex AI:n <a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/capabilities/control-generated-output">rakenteinen tuloste</a> pakottaa vastauksen skeeman muotoon, joten koodin ei tarvitse arvailla, mitä mallilta tulee.</li>
</ol>
<figure class="figure">
  <img src="/assets/blog/lounas/wanha-asema-lista.webp" alt="Ote Wanhan Aseman lounaslistasta: Viikon 43 lounas 19.10.–24.10., maanantaina Aseman kebab ja tsatsiki (l,g), Kasvisriisiä (m,g) ja Broilerikiusausta (l,g), tiistaina Seesamibroileria ja sitruunamajoneesia (m,g) ja Lohilaatikkoa (l,g)." width="1040" height="720" loading="lazy">
  <figcaption>Wanhan Aseman lounaslista ravintolan omalla sivulla.</figcaption>
</figure>

<p>Samasta listasta Gemini palauttaa tällaisen JSONin (ote maanantailta):</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-json">{
  &quot;viikko&quot;: 43,
  &quot;paivat&quot;: [
    {
      &quot;paiva&quot;: &quot;maanantai&quot;,
      &quot;pvm&quot;: &quot;2026-10-19&quot;,
      &quot;ruoat&quot;: [
        { &quot;nimi&quot;: &quot;Aseman kebab ja tsatsiki&quot;,
          &quot;ruokavaliot&quot;: [&quot;L&quot;, &quot;G&quot;], &quot;hinta&quot;: &quot;&quot; },
        { &quot;nimi&quot;: &quot;Kasvisriisiä&quot;,
          &quot;ruokavaliot&quot;: [&quot;M&quot;, &quot;G&quot;], &quot;hinta&quot;: &quot;&quot; },
        { &quot;nimi&quot;: &quot;Broilerikiusausta&quot;,
          &quot;ruokavaliot&quot;: [&quot;L&quot;, &quot;G&quot;], &quot;hinta&quot;: &quot;&quot; }
      ],
      &quot;lisat&quot;: &quot;&quot;
    }
  ]
}
</code></pre>
<p>Päivämäärä on päätelty otsikon viikosta. Sulkeissa olevat pienet kirjaimet ovat muuttuneet yhtenäisiksi ruokavaliomerkinnöiksi.</p>
<ol start="3">
<li><strong>Tulos tallennetaan</strong> JSON-tiedostona Cloud Storageen.</li>
<li><strong>Sivu piirretään palvelimella</strong> siitä JSONista. Firebasen CDN pitää valmiin sivun välimuistissa kymmenen minuuttia, joten sivu aukeaa heti eikä kävijä koskaan odota kielimallia.</li>
</ol>
<p>Gemini kutsutaan vain, kun ravintolan teksti on muuttunut edellisestä hausta. Botti laskee tekstistä tiivisteen ja vertaa sitä edelliseen. Käytännössä malli ajetaan kerran viikossa ravintolaa kohden sekä silloin, kun ravintola korjaa listaansa kesken viikon.</p>
<h2 id="miksi-kielimalli-eika-pelkat-valitsimet">Miksi kielimalli eikä pelkät valitsimet?</h2>
<p>Viidellä ravintolalla on viisi tapaa kirjoittaa lounaslista. Yksi kirjoittaa &quot;MAANANTAI 19.10.&quot; omalle rivilleen, toinen laittaa viikonpäivät taulukkoon, kolmas listaa lisukkeet ja hintaan sisältyvän kahvin jokaisen päivän perään. Ruokavaliomerkinnät ovat milloin suluissa, milloin pilkuilla erotettuina ruoan perässä.</p>
<p>Jokaiselle sivulle voisi kirjoittaa oman jäsentimen, mutta ne hajoavat juuri silloin, kun ravintola muuttaa jotain. Kielimalli lukee listan niin kuin ihminen lukee sen. Kun Gemini palauttaa saman muotoisen JSONin jokaisesta ravintolasta, kaikki kortit näyttävät samalta, ruokavaliot voi näyttää yhtenäisinä merkintöinä ja tämän päivän lounaat voi poimia suoraan.</p>
<p>Valitsimia tarvitaan silti, mutta enää vain rajaamaan, mistä kohtaa sivua lista löytyy. Jos valitsin ei löydä mitään, botti antaa Geminille koko sivun tekstin ja kirjaa varoituksen lokiin. Lista näkyy silloinkin. Lokista näen, että valitsin kannattaa päivittää.</p>
<h2 id="riittaako-halvin-malli">Riittääkö halvin malli?</h2>
<p>Riittää. Analytiikka-agenttini käyttää Googlen isointa mallia, Gemini 4 Argonia, mutta lounaslistan muuttaminen JSONiksi on pieni tehtävä: syötteenä on alle 1 500 merkkiä tekstiä eikä siinä tarvita päättelyä. Kokeilin Flash-Lite -mallia kaikilla viidellä ravintolalla ja tulos oli oikein ensimmäisellä kerralla. Varalla on isompi Flash-malli, jos Flash-Lite ei vastaa.</p>
<p>Kielimalli voi aina muuttaa sisältöä. Siksi ohje kieltää mallia keksimästä, kääntämästä tai korjaamasta ruokien nimiä. Lisäksi mallin satunnaisuutta säätelevä lämpötila-asetus on nollassa, jotta tulos ei vaihtele ajokerrasta toiseen. Sivulla kerrotaan, että listat haetaan automaattisesti.</p>
<h2 id="mita-muuta-tein-toisin-kuin-ennen">Mitä muuta tein toisin kuin ennen?</h2>
<ul>
<li><strong>Vanhentunut lista tunnistetaan.</strong> Jos ravintola ei ole vielä päivittänyt listaansa uudelle viikolle, kortissa lukee, miltä viikolta lista on. Vanhaa ruokaa ei näytetä tämän päivän lounaana.</li>
<li><strong>Hakuvirhe ei tyhjennä sivua.</strong> Jos ravintolan sivu ei vastaa, edellinen onnistunut lista jää voimaan.</li>
<li><strong>Botti esittäytyy rehellisesti.</strong> Vanha skripti esiintyi Googlebotina. Uusi kertoo User-Agent-otsakkeessa, mikä se on ja mistä se tulee.</li>
<li><strong>Sivu toimii ilman JavaScriptiä.</strong> Päivävalinta toimii tavallisilla linkeillä. Saavutettavuus on tarkistettu samalla tavalla kuin muulla sivustolla.</li>
</ul>
<h2 id="mihin-muuhun-samaa-tapaa-voi-kayttaa">Mihin muuhun samaa tapaa voi käyttää?</h2>
<p>Sama malli sopii moneen yritysten arkiseen ongelmaan: tieto on jonkun toisen sivulla, PDF:ssä tai sähköpostissa vapaana tekstinä ja se pitäisi saada omaan järjestelmään. Haku ja tallennus tehdään tavallisella koodilla. Kielimalli tekee vain sen osan, joka on ennen vaatinut ihmisen: tekstin tulkinnan. Tällaisia <a href="/palvelut/integraatiot">integraatioita</a> ja <a href="/palvelut/tekoalyagentit">tekoälyagentteja</a> rakennan myös asiakkaille.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="paljonko-tallainen-botti-maksaa-yllapitaa">Paljonko tällainen botti maksaa ylläpitää?</h3>
<p>Käytännössä ei juuri mitään. Gemini ajetaan vain listan muuttuessa. Yksi lista on muutama sata tokenia. Cloud Functions ja Cloud Storage pysyvät tällä käyttömäärällä pienissä senttisummissa.</p>
<h3 id="saako-ravintoloiden-lounaslistoja-hakea-automaattisesti">Saako ravintoloiden lounaslistoja hakea automaattisesti?</h3>
<p>Listat ovat julkisia ja botti hakee ne harvoin: neljä kertaa päivässä yhden sivun ravintolaa kohden. Botti esittäytyy ja sivulla linkitetään jokaisen ravintolan omaan listaan. Jos ravintola ei halua olla mukana, poistan sen.</p>
<h3 id="voiko-listaan-lisata-ravintolan">Voiko listaan lisätä ravintolan?</h3>
<p>Voi. Uusi ravintola on yksi rivi asetuksissa: nimi, osoite ja valitsin, josta lista löytyy. Jos valitsinta ei ole, Gemini etsii listan koko sivun tekstistä.</p>
]]></content:encoded>
    </item>
    <item>
      <title>PHP2Shell: miksi PHP:n haavoittuvuus oli iso juttu ja voiko WordPressiin yhä luottaa</title>
      <link>https://peltopiri.com/blogi/php2shell-haavoittuvuus</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/php2shell-haavoittuvuus</guid>
      <pubDate>Thu, 22 Oct 2026 15:00:00 GMT</pubDate>
      <description>PHP paikkasi 21.10.2026 kaksi kriittistä haavoittuvuutta. Mitä tapahtui, mitä paikkaus vaati ja mitä sivuston omistajan kannattaa tehdä nyt.</description>
      <content:encoded><![CDATA[<p>PHP julkaisi 21.10.2026 hätäpäivityksen kahteen kriittiseen haavoittuvuuteen, joille on annettu yhteinen nimi PHP2Shell (CVE-2026-109618 ja CVE-2026-109619). Niiden avulla hyökkääjä voi pahimmillaan ajaa omaa koodiaan palvelimella ilman kirjautumista. Korjatut versiot ovat PHP 8.5.12, 8.4.27, 8.3.36 ja 8.2.35. Jos sivustosi pyörii PHP:llä, eli esimerkiksi WordPressillä, WooCommercella tai Laravelilla, varmista heti, että palvelimen PHP on päivitetty. WordPressin oma päivitys ei tätä korjaa.</p>
<h2 id="miksi-tasta-tuli-niin-iso-hassakka">Miksi tästä tuli niin iso hässäkkä?</h2>
<p>Tavallisesti haavoittuvuus on yksittäisessä lisäosassa tai sovelluksessa ja se koskee vain niitä, jotka sitä käyttävät. Nyt vika oli PHP:ssä itsessään. <a href="https://www.php.net/archive/2026.php#2026-10-21-5">PHP:n tiedotteen</a> mukaan se koskee kaikkia verkkopyyntöjä palvelevia PHP-asennuksia, ajettiinpa PHP:tä PHP-FPM:llä, Apachen mod_php:llä, php-cgi:llä, FrankenPHP:llä tai LiteSpeedillä. Riski on suurin mod_php:llä, jossa hyökkäys voi käynnistyä yhdellä pyynnöllä ennen kuin sovelluksen koodia on ajettu lainkaan.</p>
<p>Haavoittuvuudet löytänyt <a href="https://www.wiz.io/blog/php2shell-php-rce">Wiz Research</a> kertoo, että ne ulottuvat lähes kaikkiin PHP-versioihin aina 5.4:stä asti. Wiz osoitti toimivan hyökkäyksen WordPressiä, Drupalia ja Joomlaa vastaan. Kun PHP pyörittää valtaosaa verkkosivuista, haavoittuvien palvelimien määrä on valtava.</p>
<p>Teknisesti kyse on muistinhallinnan virheistä. Kun PHP:n muisti loppuu kesken pyynnön käsittelyn, sisäinen tila voi jäädä puolivalmiiksi tai viitata jo vapautettuun muistiin. Seuraava pyyntö samassa prosessissa voi sitten käyttää tätä rikkinäistä tilaa. Wizin mukaan samalla tavalla voi myös vuotaa muistin sisältöä, kuten salasanoja ja avaimia.</p>
<p>Tilannetta pahensi vuoto. Julkistuksen piti tapahtua torstaina 22.10., mutta <a href="https://www.huntress.com/blog/php2shell-leaked-critical-php-vulnerabilities">Huntressin mukaan</a> tiedot haavoittuvuuksista ilmestyivät Hacker Newsiin jo maanantaiaamuna 20.10. Viesti poistettiin, mutta kuvakaappaukset ehtivät levitä. PHP aikaisti julkaisua yhdellä päivällä ja ilmoitti korjausten tulevan keskiviikkona 21.10.</p>
<h2 id="mita-paikkaaminen-vaati">Mitä paikkaaminen vaati?</h2>
<p>Tämän tapauksen tärkein asia on se, että WordPressin, teeman tai lisäosien päivitys ei auta. Korjaus pitää asentaa palvelimelle, eli sen tekee ylläpitäjä tai hosting-palvelu.</p>
<ul>
<li><strong>Hallinnoidussa hostingissa</strong> palveluntarjoaja hoitaa päivityksen. Esimerkiksi <a href="https://seravo.com/en/critical-php-vulnerabilities-detected/">Seravo</a> ilmoitti, ettei sen asiakkaiden tarvitse tehdä mitään.</li>
<li><strong>Omalla palvelimella tai VPS:llä</strong> PHP pitää päivittää itse heti, kun käyttöjärjestelmän paketit ovat saatavilla. Sen jälkeen PHP-prosessit pitää käynnistää uudelleen.</li>
<li><strong>Vanhoilla PHP-versioilla</strong> tilanne on hankalin. PHP 8.1 ja sitä vanhemmat eivät saa enää virallisia päivityksiä. PHP julkaisi versioille 7.4–8.1 vain lähdekooditason korjaukset, joten käytännössä ainoa kestävä ratkaisu on nostaa PHP vähintään versioon 8.2.</li>
</ul>
<p><a href="https://www.php.net/archive/2026.php#2026-10-21-5">PHP:n tiedote</a> listaa asetuksia, jotka pienentävät riskiä, mutta painottaa, etteivät ne tee asennuksesta turvallista. Ainoa kunnollinen korjaus on päivitys.</p>
<h2 id="mita-paikkauksen-jalkeen-kannattaa-tarkistaa">Mitä paikkauksen jälkeen kannattaa tarkistaa?</h2>
<p>Kun PHP on päivitetty, uusia hyökkäyksiä näitä aukkoja vastaan ei enää voi tehdä. Jos sivusto oli kuitenkin haavoittuvana verkossa vuodon ja paikkauksen välillä, kannattaa tarkistaa jälkikäteen ainakin nämä:</p>
<ul>
<li>onko WordPressiin ilmestynyt uusia pääkäyttäjiä</li>
<li>onko palvelimelle tullut tiedostoja tai muuttunut koodia, jota et tunnista</li>
<li>näkyykö lokeissa poikkeavia pyyntöjä tai virheitä 20.–21.10. välillä.</li>
</ul>
<p>Koska haavoittuvuus voi vuotaa muistin sisältöä, mieti myös salaisuuksien vaihtamista: tietokannan salasana, <code>wp-config.php</code>:n avaimet sekä rajapinta-avaimet esimerkiksi maksupalveluun tai ERP:hen. Tiedot hyökkäyksistä ovat ristiriitaisia. <a href="https://watchtowr.com/intelligence/php-cve-2026-109618-faq/">watchTowr</a> kertoo havainneensa hyödyntämistä houkutuspalvelimillaan jo 21.10., kun taas Huntress ei ollut nähnyt hyökkäyksiä asiakkaillaan vielä saman päivän iltapäivänä. Kannattaa olettaa, että aukkoja yritetään hyödyntää. Tarkistukset kannattaa tehdä sen mukaan.</p>
<h2 id="kuinka-nopeasti-seuraava-aukko-loytyy">Kuinka nopeasti seuraava aukko löytyy?</h2>
<p>Todennäköisesti aiempaa nopeammin. Wiz kertoo käyttäneensä tekoälymalleja haavoittuvuuksien etsimiseen ja hyökkäyksen rakentamiseen ja yksi tutkija teki noin viikossa työn, johon olisi aiemmin mennyt huippuryhmältä kuukausia. Wiz arvioi myös, että samasta virhetyypistä on todennäköisesti muitakin muunnelmia.</p>
<p>Sama työkalu toimii molempiin suuntiin. Tekoäly auttaa löytämään vuosia piilossa olleita vikoja ennen kuin niitä käytetään hyväksi, mutta se myös lyhentää aikaa julkistuksesta toimivaan hyökkäykseen. Sivuston omistajalle tämä tarkoittaa sitä, että päivitykset pitää saada asennettua päivissä, ei kuukausissa.</p>
<h2 id="pitaisiko-wordpressista-ja-php-sta-luopua">Pitäisikö WordPressistä ja PHP:stä luopua?</h2>
<p>Minun vastaukseni on ei. Kriittisiä haavoittuvuuksia löytyy jokaisesta laajasti käytetystä alustasta. Javan Log4Shell vuonna 2021 on hyvä esimerkki siitä, että sama voi tapahtua missä tahansa. Alustan vaihtaminen ei poista riskiä, vaan vaihtaa sen toiseen.</p>
<p>Olennaisempaa on, miten sivustoa ylläpidetään. Tämän tapauksen jälkeen kysyisin omalta sivustoltani nämä asiat:</p>
<ol>
<li><strong>Onko PHP tuettu versio?</strong> PHP 8.2 saa tietoturvakorjauksia vain vuoden 2026 loppuun asti, joten 8.3 tai uudempi on parempi valinta jo nyt.</li>
<li><strong>Kuka päivittää palvelimen ja kuinka nopeasti?</strong> Hallinnoitu hosting, kuten <a href="/palvelut/wordpress-woocommerce">WordPress-sivustoille Seravo</a> tai <a href="/palvelut/laravel-palvelimet">Laravel-sovelluksille Laravel Cloud</a>, hoitaa tämän puolestasi. Omalla palvelimella sinun pitää tietää, kuka sen tekee.</li>
<li><strong>Seurataanko tilannetta?</strong> Joku seuraa tietoturvatiedotteita ja huomaa, kun on kiire.</li>
</ol>
<p>PHP:n tietoturvatiimi toimi tässä tapauksessa nopeasti: korjaukset julkaistiin noin vuorokausi vuodon jälkeen ja Linux-jakeluille ja tukipalveluille ne oli toimitettu etukäteen. Ongelma ei siis ollut PHP:n ylläpidossa vaan siinä, kuinka moni sivusto pyörii vanhalla versiolla tai palvelimella, jota kukaan ei aktiivisesti päivitä.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="korjaako-wordpressin-paivitys-php2shell-haavoittuvuuden">Korjaako WordPressin päivitys PHP2Shell-haavoittuvuuden?</h3>
<p>Ei. Haavoittuvuus on PHP:ssä, ei WordPressissä. PHP pitää päivittää palvelimelle versioon 8.5.12, 8.4.27, 8.3.36 tai 8.2.35 tai uudempaan. Kysy hosting-palvelultasi, onko päivitys tehty.</p>
<h3 id="mista-naen-mika-php-versio-sivustollani-on">Mistä näen, mikä PHP-versio sivustollani on?</h3>
<p>WordPressissä se näkyy kohdassa Työkalut → Sivuston terveys → Tiedot → Palvelin. Hosting-palvelun hallintapaneelissa näkyy yleensä myös käytössä oleva versio. Pelkkä versionumero, esimerkiksi 8.3, ei riitä, vaan tarkista myös viimeinen numero.</p>
<h3 id="riittaako-etta-sivusto-on-cloudflaren-takana">Riittääkö, että sivusto on Cloudflaren takana?</h3>
<p>Ei yksinään. Palomuuri voi torjua osan tunnetuista hyökkäysyrityksistä, mutta PHP:n mukaan ainoa täydellinen korjaus on päivitys.</p>
]]></content:encoded>
    </item>
    <item>
      <title>What's in the bag – työkalut, joilla teen verkkosivustoja</title>
      <link>https://peltopiri.com/blogi/whats-in-the-bag</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/whats-in-the-bag</guid>
      <pubDate>Wed, 21 Oct 2026 06:00:00 GMT</pubDate>
      <description>Editorit, tekoäly, paikallinen kehitysympäristö, apuohjelmat ja Chrome-lisäosat, joilla teen työni, sekä itse rakennettu Meet-tallennin.</description>
      <content:encoded><![CDATA[<p>Golfareilla on tapana esitellä, mitä mailoja laukussa on. Tässä on minun versioni: ohjelmat, palvelut ja Chrome-lisäosat, joilla teen verkkosivustoja, verkkokauppoja ja integraatioita. Mukana on myös yksi itse rakennettu työkalu, joka säästää eniten aikaa.</p>
<h2 id="editorit-ja-tekoaly">Editorit ja tekoäly</h2>
<ul>
<li><strong><a href="https://www.sublimetext.com/">Sublime Text</a></strong> – nopea ja kevyt editori, kun pitää avata tiedosto heti tai käsitellä isoja tiedostoja.</li>
<li><strong><a href="https://cursor.com/">Cursor</a></strong> – tekoälyä hyödyntävä koodieditori isompaan kehitystyöhön.</li>
<li><strong><a href="https://github.com/features/copilot">GitHub Copilot</a></strong> – koodiehdotukset suoraan editoriin.</li>
<li><strong><a href="https://claude.ai/">Claude</a></strong> – tekoälyavustaja ja Claude Code, jolla tämäkin sivusto on <a href="/blogi/sivusto-tekoalyn-avustuksella">rakennettu</a>.</li>
<li><strong><a href="https://chatgpt.com/">ChatGPT</a></strong> ja <strong><a href="https://gemini.google.com/">Gemini</a></strong> – toiset näkökulmat, haku ja vertailu. Eri mallit ovat vahvoja eri asioissa, joten käytän useampaa.</li>
</ul>
<figure class="figure">
  <img src="/assets/blog/witb/sublime-text.webp" alt="Sublime Text -editori, jossa on auki demo.js-tiedosto. Koodi luo sivun taustalle canvas-elementin, johon piirretään pisteitä ja pieniä koodisymboleita. Se huomioi käyttäjän vähennetyn liikkeen asetuksen." width="1400" height="846" loading="lazy">
  <figcaption>Sublime Text ja työn alla oleva taustaefekti.</figcaption>
</figure>

<h2 id="paikallinen-kehitysymparisto">Paikallinen kehitysympäristö</h2>
<ul>
<li><strong><a href="https://herd.laravel.com/">Laravel Herd</a></strong> – PHP- ja Laravel-kehitysympäristö Macille ja Windowsille. Eri PHP-versiot ja paikalliset sivustot ilman erillistä palvelinasennusta. Uusin lisäys on <a href="https://herd.laravel.com/docs/macos/herd-studio/overview">Herd Studio</a>: selainnäkymä, jossa Herdissä hostattua paikallista sivustoa tai sovellusta kehitetään tekoälyagentin kanssa <a href="/blogi/lovable-sivusto-tai-sovellus">Lovablen</a> tyyliin esikatselu vieressä.</li>
<li><strong><a href="https://dbngin.com/">DBngin</a></strong> – paikalliset tietokantapalvelimet, kuten MySQL ja PostgreSQL, päälle ja pois yhdellä klikkauksella.</li>
<li><strong><a href="https://sequel-ace.com/">Sequel Ace</a></strong> – MySQL- ja MariaDB-tietokantojen selaus ja muokkaus.</li>
<li><strong><a href="https://localwp.com/">Local</a></strong> – paikalliset WordPress-sivustot nopeasti pystyyn.</li>
</ul>
<figure class="figure">
  <img src="/assets/blog/witb/herd-kertotaulupeli.webp" alt="Herd Studio: vasemmalla chat, jossa agentti kertoo lisänneensä kertotaulupeliin kaksi uutta vaikeustasoa, oikealla pelin esikatselu. Violetilla taustalla putoavia numerokuplia ja kysymys Paljonko on 6 × 5?" width="1400" height="993" loading="lazy">
  <figcaption>Herd Studio ja kolmasluokkalaiselle tehty kertotaulupeli.</figcaption>
</figure>

<h2 id="palvelimet-ja-tiedostot">Palvelimet ja tiedostot</h2>
<ul>
<li><strong><a href="https://cloud.google.com/">Google Cloud</a></strong> – tämän sivuston Firebase-hosting ja Cloud Functions sekä Gemini-mallit Vertex AI:n kautta.</li>
<li><strong><a href="https://www.hetzner.com/">Hetzner</a></strong> + <strong><a href="https://www.cloudflare.com/">Cloudflare</a></strong> – staging-palvelin Hetznerin Suomen konesalissa Cloudflaren proxyn takana.</li>
<li><strong><a href="https://kehittajille.suomi.fi/palvelut/palveluvayla">Suomi.fi-palveluväylä</a></strong> – liityntäpalvelin Hetznerin Suomen konesalissa.</li>
<li><strong><a href="https://forge.laravel.com/">Laravel Forge</a></strong> + <strong>Hetzner</strong> – Laravel-sovellusten palvelimien asennus, julkaisut ja ylläpito.</li>
<li><strong><a href="https://cloud.laravel.com/">Laravel Cloud</a></strong> – Laravel-sovellusten hosting ilman omaa palvelinta.</li>
<li><strong><a href="https://panic.com/transmit/">Transmit</a></strong> – tiedostonsiirrot SFTP:llä ja pilvitallennuksiin.</li>
</ul>
<h2 id="pienet-apurit">Pienet apurit</h2>
<ul>
<li><strong><a href="https://www.renfei.org/snippets-lab/">SnippetsLab</a></strong> – oma kirjasto usein tarvittaville koodinpätkille.</li>
<li><strong><a href="https://imageoptim.com/">ImageOptim</a></strong> – kuvien pakkaus ennen kuin ne päätyvät sivustolle.</li>
<li><strong><a href="https://colorslurp.com/">ColorSlurp</a></strong> – värien poiminta ruudulta ja muuntaminen eri muotoihin.</li>
<li><strong>Omat pikatoiminnot macOS:ssä</strong> – useita itse tehtyjä Quick Actioneita toistuviin tehtäviin suoraan Finderista.</li>
</ul>
<h2 id="chrome-lisaosat">Chrome-lisäosat</h2>
<ul>
<li><strong>PerfectPixel</strong> – asettaa suunnittelijan kuvan sivun päälle läpinäkyvänä kerroksena, jolloin toteutusta voi verrata suunnitelmaan pikselin tarkkuudella.</li>
<li><strong>GoFullPage</strong> – kuvakaappaus koko sivusta yhdellä klikkauksella, myös siitä osasta, joka ei mahdu ruudulle.</li>
<li><strong>MeetRecorder</strong> – itse rakentamani lisäosa, josta lisää alla.</li>
</ul>
<h2 id="meetrecorder-palaverista-tehtavalistaksi">MeetRecorder: palaverista tehtävälistaksi</h2>
<p>Rakensin itselleni Chrome-lisäosan, joka tallentaa Google Meet -palaverin äänitiedostoksi. Palaverin jälkeen tallenteesta tehdään tekoälyllä tekstitys ja siitä poimitaan minulle tehtävälista: mitä sovittiin, mitä minun pitää tehdä ja mihin mennessä.</p>
<p>Hyöty on yksinkertainen. Palaverissa voi keskittyä keskusteluun eikä muistiinpanoihin ja mikään sovittu asia ei jää unohduksiin. Tämä on hyvä esimerkki siitä, millaisia pieniä <a href="/palvelut/tekoalyagentit">tekoälyagentteja</a> kannattaa rakentaa: selkeä, toistuva tehtävä, jossa lopputuloksen voi tarkistaa nopeasti itse.</p>
<p>Tallentamisesta pitää aina kertoa palaverin muille osallistujille.</p>
<h2 id="tietoturva">Tietoturva</h2>
<ul>
<li><strong><a href="https://1password.com/">1Password</a></strong> – salasanat ja tunnukset.</li>
<li><strong><a href="https://nordvpn.com/">NordVPN</a></strong> – suojattu yhteys julkisissa verkoissa.</li>
</ul>
<h2 id="miten-tyo-kulkee">Miten työ kulkee</h2>
<p>Kehitän ensin paikallisesti omalla koneellani. Kun muutos on valmis, se siirtyy Cloudflaren välityspalvelimen takana olevalle testipalvelimelle ja tarkistetaan siellä ennen tuotantoon viemistä. Testipalvelimelle työskentelen SSH-yhteyden yli.</p>
<p>Näin keskeneräinen työ ei koskaan näy sivuston oikeille kävijöille ja jokainen muutos on nähty ja testattu ennen julkaisua. Lisää siitä, miten rakennan sivustoja, löydät <a href="/palvelut/wordpress-woocommerce">WordPress- ja WooCommerce-palvelusta</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="mika-on-paras-editori-wordpress-kehitykseen">Mikä on paras editori WordPress-kehitykseen?</h3>
<p>Se, jota osaa käyttää hyvin. Itse käytän kevyttä Sublime Textiä nopeisiin muutoksiin ja tekoälyä hyödyntävää Cursoria isompaan kehitystyöhön.</p>
<h3 id="miksi-kehittaa-paikallisesti-eika-suoraan-palvelimella">Miksi kehittää paikallisesti eikä suoraan palvelimella?</h3>
<p>Paikallisesti voi kokeilla rauhassa ilman, että virhe näkyy sivuston kävijöille. Lisäksi työ on nopeampaa, kun jokainen muutos ei kulje verkon yli.</p>
<h3 id="voiko-meetrecorderin-saada-omaan-kayttoon">Voiko MeetRecorderin saada omaan käyttöön?</h3>
<p>Se on tehty omaan käyttööni. Jos haluat vastaavan työkalun yrityksellesi, voin rakentaa sellaisen sinun tarpeisiisi.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Tein oman sivustoni WCAG 2.2 AA -auditin. Tässä, mitä löytyi</title>
      <link>https://peltopiri.com/blogi/wcag-auditti-omalle-sivustolle</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/wcag-auditti-omalle-sivustolle</guid>
      <pubDate>Tue, 20 Oct 2026 09:00:00 GMT</pubDate>
      <description>Auditoin oman uuden sivustoni saavutettavuuden. Löytyi kontrastivirheitä, vaakavieritys 320 pikselin leveydellä ja animaatio, jota ei voinut pysäyttää.</description>
      <content:encoded><![CDATA[<p>Teen saavutettavuusauditteja asiakkaille, joten oman sivuston pitää olla kunnossa. Ajoin uudelle sivustolleni WCAG 2.2 AA -tason auditin heti julkaisun jälkeen. Automaattinen tarkistus löysi kaksi ongelmaa, mutta suurin osa löydöksistä tuli vasta käsin tehdyissä tarkistuksissa. Kaikki korjattiin samana päivänä. Tässä on lista löydöksistä, koska ne ovat juuri niitä virheitä, joita löydän asiakkaidenkin sivustoilta.</p>
<h2 id="miten-auditti-tehtiin">Miten auditti tehtiin?</h2>
<p>Auditissa oli kaksi osaa:</p>
<ol>
<li><strong>Automaattinen tarkistus.</strong> Ajoin <a href="https://github.com/dequelabs/axe-core">axe-core</a> -työkalun jokaiselle sivulle sekä työpöytä- että mobiilileveydellä. Se löytää muun muassa kontrastivirheet, puuttuvat kenttänimet ja virheelliset rakenteet.</li>
<li><strong>Käsin tehdyt tarkistukset.</strong> Kävin sivuston läpi pelkällä näppäimistöllä, kapeimmalla 320 pikselin leveydellä ja suurennetuilla tekstiväleillä. Lisäksi tarkistin kosketuskohteiden koot ja liikkuvan sisällön.</li>
</ol>
<p>Automaattinen tarkistus löytää tyypillisesti vain osan ongelmista. Tässä se löysi yhden kontrastivirheen ja rakennevirheen, jossa sivupalkkialueita (aside) oli sisäkkäin. Kaikki muu alla oleva löytyi käsin.</p>
<h2 id="kontrasti-punainen-teksti-ei-riittanyt">Kontrasti: punainen teksti ei riittänyt</h2>
<p>Sivuston aksenttiväri on punainen. Kahdessa kohdassa sitä oli käytetty tekstinä, eikä kontrasti riittänyt:</p>
<ul>
<li>Etusivun animaatiossa punainen teksti tummalla taustalla: kontrasti 3,4:1, kun <a href="https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html">vaatimus</a> on 4,5:1.</li>
<li>Lomakkeen virheilmoitus vaalealla taustalla: 4,0:1.</li>
</ul>
<p>Jälkimmäistä automaattinen tarkistus ei löytänyt, koska virheilmoitus ei ollut näkyvissä testin aikana. Löysin sen laskemalla kontrastit kaikille väriyhdistelmille. Korjaus oli yksinkertainen: tummalle taustalle vaaleampi punainen, vaalealle tummempi. Nyt sivuston ohjeissa on sääntö, että punaista käytetään tekstinä vain näillä kahdella sävyllä.</p>
<h2 id="vaakavieritys-320-pikselin-leveydella">Vaakavieritys 320 pikselin leveydellä</h2>
<p><a href="https://www.w3.org/WAI/WCAG22/Understanding/reflow.html">WCAG 1.4.10</a> edellyttää, että sivua voi lukea 320 pikselin leveydellä ilman vaakavieritystä. Tämä vastaa tilannetta, jossa käyttäjä suurentaa sivun 400 prosenttiin. Minun sivustollani oli kaksi ongelmaa:</p>
<ul>
<li>Yläpalkin valikko ei mahtunut logon viereen.</li>
<li>Pitkät suomen sanat eivät mahtuneet otsikoihin. &quot;Verkkosivustoja,&quot; ja &quot;saavutettavuusauditit&quot; ovat isolla fontilla leveämpiä kuin kapea näyttö.</li>
</ul>
<p>Suomi on tässä hankala kieli, koska yhdyssanat ovat pitkiä. Korjasin valikon rivittymään ja otin otsikoissa käyttöön tavutuksen, jolloin selain katkaisee pitkät sanat oikeasta kohdasta tavuviivalla.</p>
<h2 id="animaatio-jota-ei-voinut-pysayttaa">Animaatio, jota ei voinut pysäyttää</h2>
<p>Etusivulla on animaatio, jossa auditin löydöksiä korjataan yksi kerrallaan. Se pyöri loputtomiin, eikä sitä voinut pysäyttää. <a href="https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html">WCAG 2.2.2</a> edellyttää, että yli viiden sekunnin ajan jatkuvan liikkeen voi pysäyttää. Liike voi häiritä keskittymistä ja lukemista erityisesti silloin, kun käyttäjällä on tarkkaavaisuuden vaikeuksia.</p>
<p>Sivustolla oli jo huomioitu käyttöjärjestelmän asetus, jolla liikettä voi vähentää. Se ei kuitenkaan riitä, koska kaikki eivät tiedä asetuksesta. Animaatioon tuli pysäytyspainike. Sama korjaus tehtiin myös logoriville, joka liukuu jatkuvasti.</p>
<h2 id="muut-loydokset">Muut löydökset</h2>
<ul>
<li><strong>Evästeilmoitus peitti kohdistuksen.</strong> Mobiilissa ruudun alalaidassa oleva evästeilmoitus saattoi peittää elementin, johon näppäimistön kohdistus siirtyi (<a href="https://www.w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum.html">WCAG 2.4.11</a>, uusi kriteeri versiossa 2.2). Lisäksi ilmoitus oli sivun lopussa, joten näppäimistön käyttäjä pääsi siihen vasta koko sivun jälkeen. Nyt ilmoitus on heti alussa, sen voi sulkea Esc-näppäimellä ja sivu jättää sille tilaa.</li>
<li><strong>Pienet kosketuskohteet.</strong> Muutama erillinen linkki ja painike oli 22–23 pikseliä korkea. Uusi <a href="https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html">kriteeri 2.5.8</a> edellyttää vähintään 24 pikseliä tai riittävää tyhjää tilaa ympärillä. Väli olisi riittänyt, mutta nostin koot silti.</li>
<li><strong>Englanninkielinen teksti.</strong> Footerissa on nimike &quot;Freelance Web Developer&quot;. Ilman kielimerkintää ruudunlukija lukee sen suomen ääntämyksellä.</li>
<li><strong>Ristiriitainen painikkeen tila.</strong> Pysäytyspainikkeessa sekä teksti että ruudunlukijalle kerrottu tila vaihtuivat, mikä tuotti sekavan ilmoituksen.</li>
<li><strong>Pakolliset kentät.</strong> Lomakkeessa ei kerrottu, että kaikki kentät ovat pakollisia.</li>
<li><strong>Uuteen välilehteen avautuvat linkit.</strong> Referenssien linkit avautuvat uuteen välilehteen. Siitä kerrotaan nyt ruudunlukijalle.</li>
</ul>
<h2 id="mita-tasta-voi-oppia">Mitä tästä voi oppia?</h2>
<p>Ensinnäkin automaattinen tarkistus ei riitä. Tässä se löysi vain kaksi ongelmaa ja kaikki muut löytyivät käsin. Toiseksi WCAG 2.2:n uudet kriteerit, kuten kohdistuksen peittyminen ja kosketuskohteiden koko, jäävät helposti huomaamatta, koska vanhat tarkistuslistat eivät sisällä niitä. Kolmanneksi suomenkielinen sivusto tarvitsee tavutuksen, jos otsikot ovat isoja.</p>
<p>Yksi asia jäi vielä tekemättä: sivustoa ei ole testattu oikealla ruudunlukijalla. Teen sen seuraavaksi, koska rakenne voi olla teknisesti oikein, vaikka lukukokemus ontuu.</p>
<p>Jos haluat saman läpikäynnin omalle sivustollesi, se kuuluu <a href="/palvelut/seo-geo-saavutettavuusauditit">SEO-, GEO- ja saavutettavuusauditteihin</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="riittaako-automaattinen-saavutettavuustarkistus">Riittääkö automaattinen saavutettavuustarkistus?</h3>
<p>Ei. Automaattinen työkalu löytää osan virheistä, kuten kontrastit ja puuttuvat nimet, mutta ei esimerkiksi sitä, peittyykö kohdistus tai voiko animaation pysäyttää. Tässä auditissa suurin osa löydöksistä löytyi vasta käsin.</p>
<h3 id="mita-uutta-wcag-2-2-toi">Mitä uutta WCAG 2.2 toi?</h3>
<p>Muun muassa kriteerit kohdistuksen näkyvyydestä, kosketuskohteiden vähimmäiskoosta, raahaamisen vaihtoehdoista ja siitä, ettei käyttäjää pakoteta syöttämään samoja tietoja uudelleen. W3C:n sivulla <a href="https://www.w3.org/WAI/standards-guidelines/wcag/new-in-22/">What&#39;s New in WCAG 2.2</a> on koko lista.</p>
<h3 id="kuinka-kauan-korjaukset-kestivat">Kuinka kauan korjaukset kestivät?</h3>
<p>Tällä pienellä sivustolla kaikki löydökset korjattiin samana päivänä. Isommalla sivustolla korjausten määrä ja laajuus riippuvat siitä, toistuuko sama virhe sivupohjassa vai onko se jokaisessa sisällössä erikseen.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Rakensin sivustoni testiksi tekoälyn avustuksella. Mitä se teki hyvin ja missä tarvittiin ihmistä</title>
      <link>https://peltopiri.com/blogi/sivusto-tekoalyn-avustuksella</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/sivusto-tekoalyn-avustuksella</guid>
      <pubDate>Tue, 20 Oct 2026 07:00:00 GMT</pubDate>
      <description>Tein tämän sivuston kokeeksi tekoälyn kanssa. Kerron, mitä tekoäly hoiti hyvin, mitä se teki väärin ja mihin tarvittiin edelleen ihmistä.</description>
      <content:encoded><![CDATA[<p>Tämä sivusto on rakennettu tekoälyn avustuksella. Sivun alalaidassa on siitä maininta ja tässä artikkelissa kerron tarkemmin, mitä se tarkoittaa. Lyhyesti: tekoäly kirjoitti suurimman osan koodista ja tekstiluonnoksista, tarkisti ja julkaisi sivuston. Ihmistä tarvittiin päätöksiin, faktoihin, kieleen ja makuun. Tein sivuston osittain kokeena, koska haluan tietää, mihin tekoälyagentit oikeasti pystyvät, ennen kuin suosittelen niitä asiakkaille.</p>
<h2 id="miten-sivusto-tehtiin">Miten sivusto tehtiin?</h2>
<p>Aloitin Clauden chat-käyttöliittymässä, jossa syntyi ensimmäinen versio: rakenne, tyylit ja etusivu. Sen jälkeen siirryin <a href="https://www.anthropic.com/claude-code">Claude Codeen</a>, joka toimii omalla koneellani. Siinä tekoäly pystyy muokkaamaan tiedostoja, ajamaan komentoja, testaamaan sivua selaimessa ja julkaisemaan muutokset Firebaseen.</p>
<p>Työtapa oli yksinkertainen: kirjoitin, mitä haluan, esimerkiksi &quot;lisää referensseihin asiakas ja suunnittelu&quot; tai &quot;logoticker kahdessa rivissä vastakkaisiin suuntiin&quot;. Tekoäly teki muutoksen, testasi sen ja julkaisi sen. Sitten katsoin tuloksen ja annoin palautetta.</p>
<h2 id="mita-tekoaly-teki-hyvin">Mitä tekoäly teki hyvin?</h2>
<ul>
<li><strong>Rakenteen ja koodin.</strong> Sivusto on staattinen ja blogi ja palvelusivut generoidaan Markdown-tiedostoista. Tekoäly kirjoitti build-skriptin, sivupohjat, sivukartan, RSS-syötteen ja rakenteisen datan.</li>
<li><strong>Taustapalvelut.</strong> Yhteydenottolomake lähettää viestit Cloud Functionin ja Resendin kautta. Tekoäly rakensi funktion, testasi sen paikallisesti valeavaimella ja julkaisi sen.</li>
<li><strong>Tarkistukset.</strong> Se testasi muutokset selaimessa eri leveyksillä, mittasi animaatioiden korkeuksia ja ajoi <a href="/palvelut/seo-geo-saavutettavuusauditit">saavutettavuusauditin</a> koko sivustolle.</li>
<li><strong>Virheiden löytämisen.</strong> Kun pyysin tarkistamaan, oliko chat-vaiheessa tehty jotain tyhmästi, se löysi muun muassa referenssien kuvakaappaukset, jotka olivat moninkertaisesti liian isoja. Ne kutistuivat 7,8 megatavusta 2,3 megatavuun.</li>
<li><strong>Faktojen tarkistamisen.</strong> Blogiartikkeleita varten se haki tiedot lähteistä ja kertoi, kun lähteet olivat ristiriidassa.</li>
</ul>
<h2 id="missa-se-teki-virheita">Missä se teki virheitä?</h2>
<p>Virheitä tuli ja ne kannattaa kertoa:</p>
<ul>
<li>Chat-vaiheessa tekoäly ei pystynyt ajamaan koodia, joten yksi riippuvuus puuttui ja ensimmäinen julkaisu epäonnistui.</li>
<li>Ensimmäinen yritys pakata kuvia tuotti isompia tiedostoja kuin alkuperäiset. Tekoäly huomasi sen itse ja vaihtoi työkalua.</li>
<li>Evästesuostumuksen peruminen jätti aluksi yhden evästeen poistamatta. Virhe löytyi testissä ja korjattiin.</li>
<li>Julkaisu jäi kerran odottamaan vastausta kysymykseen, jota kukaan ei nähnyt. Nyt julkaisuskripti ei kysy mitään.</li>
</ul>
<p>Yhteistä näille on, että ne löytyivät, koska tekoäly testasi omat muutoksensa. Ilman testausta ne olisivat päätyneet tuotantoon.</p>
<h2 id="missa-tarvittiin-ihmista">Missä tarvittiin ihmistä?</h2>
<ul>
<li><strong>Faktat omasta työstä.</strong> Tekoäly ei voi tietää, kuka oli referenssin asiakas tai millä teemalla sivusto on tehty. Se kysyi, eikä arvannut.</li>
<li><strong>Kieli.</strong> Ensimmäisissä teksteissä oli kömpelöä suomea, kuten &quot;Kerro, mitä on tekeillä&quot; ja &quot;konsultoin, missä niistä on hyötyä&quot;. Huomasin ne ja pyysin korjaamaan, minkä jälkeen tekoäly kävi kaikki tekstit läpi.</li>
<li><strong>Makuasiat.</strong> Animaation ensimmäinen versio oli kömpelö ja etusivun pääotsikkoa muotoiltiin kahdesti, ennen kuin kirjoitin sen lopulta itse. Tekoäly tekee järkeviä oletuksia, mutta sivustosta tulee omannäköinen vasta, kun joku kertoo, mikä ei toimi.</li>
<li><strong>Päätökset.</strong> Mitä julkaistaan, milloin ja millä päiväyksellä. Kun pyysin päivämäärää, joka olisi tehnyt artikkelista harhaanjohtavan, tekoäly huomautti siitä ja kysyi.</li>
<li><strong>Tunnukset.</strong> API-avaimet ja kirjautumiset hoidin itse. Tekoäly ei nähnyt avaimia missään vaiheessa.</li>
</ul>
<h2 id="mita-tasta-opin">Mitä tästä opin?</h2>
<p>Tekoäly ei korvaa kehittäjää, mutta se muuttaa työn. Minun aikani meni päätöksiin, tarkistamiseen ja palautteeseen, ei koodin kirjoittamiseen. Sivusto valmistui murto-osassa siitä ajasta, jonka se olisi muuten vienyt.</p>
<p>Kaksi asiaa ratkaisi lopputuloksen. Ensinnäkin tekoälyllä oli pääsy oikeisiin työkaluihin: se pystyi ajamaan koodia, testaamaan ja julkaisemaan. Chat-vaiheessa, jossa sitä ei voinut tehdä, syntyi eniten virheitä. Toiseksi tekoälyllä oli kirjalliset ohjeet projektista: värit, sävy, julkaisukäytäntö ja säännöt, kuten &quot;kysy referenssin asiakas ennen lisäämistä&quot;. Ilman niitä jokainen keskustelu olisi alkanut alusta.</p>
<p>Samat asiat pätevät, kun rakennan <a href="/palvelut/tekoalyagentit">tekoälyagentteja</a> asiakkaille: agentti tarvitsee oikeat työkalut, selkeät rajat ja ihmisen hyväksymään tärkeät päätökset.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="voiko-tekoalylla-tehda-verkkosivuston-ilman-kehittajaa">Voiko tekoälyllä tehdä verkkosivuston ilman kehittäjää?</h3>
<p>Yksinkertaisen sivun voi. Kun mukana on lomakkeita, taustapalveluita, julkaisu ja saavutettavuus, tarvitaan joku, joka ymmärtää tekoälyn tekemiset ja huomaa sen virheet.</p>
<h3 id="kirjoittiko-tekoaly-myos-tekstit">Kirjoittiko tekoäly myös tekstit?</h3>
<p>Se kirjoitti luonnokset ja minä korjasin ja hyväksyin ne. Artikkeleissa tekoäly haki faktat lähteistä, mutta julkaisupäätös on aina minun.</p>
<h3 id="onko-tekoalylla-tehty-sivusto-huonompi">Onko tekoälyllä tehty sivusto huonompi?</h3>
<p>Ei tarvitse olla. Tämä sivusto läpäisi saavutettavuusauditin ja on nopea. Laatu riippuu samoista asioista kuin ennenkin: testaamisesta, tarkistamisesta ja siitä, että joku välittää yksityiskohdista.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Sivuston tai sovelluksen rakentaminen Lovablella</title>
      <link>https://peltopiri.com/blogi/lovable-sivusto-tai-sovellus</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/lovable-sivusto-tai-sovellus</guid>
      <pubDate>Fri, 16 Oct 2026 06:00:00 GMT</pubDate>
      <description>Lovablella verkkopalvelun voi rakentaa kuvailemalla sen. Esittelen kaksi sillä tehtyä verkkokauppapalvelua ja sen, mihin kannattaa kiinnittää huomiota.</description>
      <content:encoded><![CDATA[<p><a href="https://lovable.dev/">Lovable</a> on tekoälypalvelu, jossa verkkosivusto tai -sovellus rakennetaan kuvailemalla se tavallisella kielellä. Lovable kirjoittaa koodin, luo tietokannan ja käyttäjätunnistuksen ja julkaisee sovelluksen. Alla on kaksi oikeaa verkkopalvelua, jotka ”entinen asiakkaani” 😅 rakensi Lovablen avulla itse. Ne näyttävät, miten raskaasta ja kehittäjävetoisesta WooCommerce-projektista voi siirtyä ketterästi tällaiselle alustalle, jossa omistaja kehittää palveluaan itse.</p>
<h2 id="mika-lovable-on">Mikä Lovable on?</h2>
<p>Lovablen <a href="https://docs.lovable.dev/introduction/welcome">oman kuvauksen</a> mukaan se on full-stack-alusta, joka tuottaa käyttöliittymän, taustapalvelun, tietokannan, kirjautumisen ja integraatiot. Kaikki on muokattavaa koodia. Sovellukset ovat React-sovelluksia ja taustapalvelu on joko Lovablen oma, Supabaseen perustuva <a href="https://docs.lovable.dev/integrations/cloud">Cloud</a> tai oma Supabase-projekti.</p>
<p>Koodi on käyttäjän omaa. Projektin voi synkronoida <a href="https://docs.lovable.dev/integrations/git-sync-overview">GitHubiin tai muuhun Git-palveluun</a>, jolloin kehittäjä voi jatkaa sitä tavallisilla työkaluilla ja muutokset kulkevat molempiin suuntiin. Sovellus ei siis jää lukkoon yhden palveluntarjoajan alustalle, toisin kuin suljetuissa kotisivukoneissa.</p>
<h2 id="esimerkki-1-reddy">Esimerkki 1: Reddy</h2>
<figure class="shots">
  <img src="/assets/blog/lovable/reddy-desktop.webp" alt="Reddyn etusivu työpöydällä: otsikko Avaa oma kauppasi ja myy collegeita, alla neljä etua kortteina." width="1200" height="750" loading="lazy">
  <img src="/assets/blog/lovable/reddy-mobiili.webp" alt="Reddyn etusivu puhelimella." width="600" height="1299" loading="lazy">
  <figcaption><a href="https://reddyshop.co/">reddyshop.co</a> – print-on-demand-alusta oman paitakaupan avaamiseen.</figcaption>
</figure>

<p><a href="https://reddyshop.co/">Reddy</a> on palvelu, jolla kuka tahansa voi avata oman paita- ja merch-kaupan ilman varastoa. Käyttäjä rekisteröityy, valitsee tuotteet, lisää omat painatuksensa ja muokkaa kaupan värit ja fontit. Reddy hoitaa tuotannon, maksut ja toimitukset. Etusivulla on interaktiivinen esikatselu, jossa kaupan ulkoasua voi kokeilla ennen rekisteröitymistä. Siellä on myös laskuri, joka näyttää myyjän katteen.</p>
<p>Kyse on kokonaisesta sovelluksesta, jossa on käyttäjätilit, kauppojen hallinta ja tilausten käsittely.</p>
<h2 id="esimerkki-2-kaupunkipaidat">Esimerkki 2: Kaupunkipaidat</h2>
<figure class="shots">
  <img src="/assets/blog/lovable/kaupunkipaidat-desktop.webp" alt="Kaupunkipaitojen etusivu: otsikko Sinun paikkasi ja kuvakaruselli, jossa Helsinki-karttapaita." width="800" height="783" loading="lazy">
  <img src="/assets/blog/lovable/kaupunkipaidat-mobiili.webp" alt="Kaupunkipaitojen etusivu puhelimella." width="600" height="1300" loading="lazy">
  <figcaption><a href="https://kaupunkipaidat.fi/">kaupunkipaidat.fi</a> – verkkokauppa, jossa on painatuksia tuhansista suomalaisista paikoista.</figcaption>
</figure>

<p><a href="https://kaupunkipaidat.fi/">Kaupunkipaidat</a> on verkkokauppa, jossa myydään painatuksia satojen suomalaisten kaupunkien ja kuntien sekä tuhansien paikkojen teemalla. Asiakas voi lisäksi suunnitella oman karttapaidan.</p>
<h2 id="mita-lovable-tekee-hyvin">Mitä Lovable tekee hyvin?</h2>
<ul>
<li><strong>Nopeus.</strong> Toimiva ensimmäinen versio syntyy tunneissa ja muutokset saa julkaistua heti.</li>
<li><strong>Ulkoasu.</strong> Lopputulos on nykyaikainen ja toimii puhelimella ilman erillistä suunnittelutyötä.</li>
<li><strong>Taustapalvelut valmiina.</strong> Tietokanta, kirjautuminen ja tiedostojen tallennus saadaan ilman palvelinten pystyttämistä.</li>
<li><strong>Omistaja kehittää itse.</strong> Uusi ominaisuus ei vaadi tarjouspyyntöä ja kehitysjonoa, vaan sen voi kuvata ja kokeilla heti.</li>
<li><strong>Koodi on omaa.</strong> Sovellusta voi jatkaa myös ilman Lovablea.</li>
</ul>
<h2 id="mihin-kannattaa-kiinnittaa-huomiota">Mihin kannattaa kiinnittää huomiota?</h2>
<p><strong>Tietoturva.</strong> Vuonna 2025 tietoturvatutkija löysi yli sata Lovablella tehtyä sovellusta, joiden tietokantaan pääsi käsiksi ilman kirjautumista, koska tietokannan käyttöoikeussäännöt puuttuivat. Tapaus sai tunnisteen <a href="https://nvd.nist.gov/vuln/detail/CVE-2025-48757">CVE-2025-48757</a>. Lovable kiistää vastuunsa, koska säännöt ovat kunkin sovelluksen tekijän vastuulla. Siksi jokaisen taulun käyttöoikeudet kannattaa tarkistaa ennen kuin sovellukseen tallennetaan asiakastietoja.</p>
<p><strong>Hakunäkyvyys.</strong> Sivujen otsikot, kuvaukset, rakenteinen data ja sivukartta kannattaa määritellä erikseen, kuten millä tahansa alustalla. Lisää aiheesta artikkelissa <a href="/blogi/geo-ja-rakenteinen-data">GEO ja rakenteinen data</a>.</p>
<p><strong>Maksut ja integraatiot.</strong> Maksunvälitys, kirjanpito ja toimitukset kannattaa testata huolellisesti myös virhetilanteissa, kuten keskeytyneen maksun tai epäonnistuneen tilauksen siirron kohdalla.</p>
<p><strong>Ylläpito.</strong> Kun sovellusta kehitetään pitkään kehotteilla, koodia kannattaa välillä siivota ja yhtenäistää. Sen voi tehdä kehittäjä tai juuri tähän työhön erikoistunut tekoäly.</p>
<h2 id="milloin-lovable-kannattaa">Milloin Lovable kannattaa?</h2>
<ul>
<li><strong>Palvelu, jota omistaja haluaa kehittää itse ja nopeasti.</strong> Juuri tässä Lovable on vahvimmillaan.</li>
<li><strong>Sovellus, jossa on kirjautuminen ja omaa logiikkaa</strong>, kuten Reddyn kaltainen alusta.</li>
<li><strong>Uuden palvelun kokeilu</strong> oikeilla käyttäjillä ennen isompaa investointia.</li>
<li><strong>Sisäiset työkalut</strong>, joita käyttää pieni joukko ihmisiä.</li>
</ul>
<p>Sisältöpainotteiseen yrityssivustoon tai verkkokauppaan, jota päivittää moni ihminen ja jossa tarvitaan monikielisyyttä tai valmiita integraatioita, WordPress ja WooCommerce ovat usein edelleen varmempi valinta. Hyvä yhdistelmä voi olla myös Lovablella tehty sovellus WordPress-sivuston rinnalla.</p>
<p>Jos rakennat palvelua Lovablella ja haluat käydä läpi tietoturvan, hakunäkyvyyden tai integraatiot, autan mielelläni. Lue lisää <a href="/palvelut/tekoalyagentit">tekoälyratkaisuista</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="voiko-lovablella-tehda-oikean-verkkokaupan">Voiko Lovablella tehdä oikean verkkokaupan?</h3>
<p>Voi, kuten Reddy ja Kaupunkipaidat osoittavat. Maksut, toimitukset ja käyttöoikeudet kannattaa testata huolellisesti ennen avaamista, kuten minkä tahansa verkkokaupan kohdalla.</p>
<h3 id="kuka-omistaa-lovablella-tehdyn-koodin">Kuka omistaa Lovablella tehdyn koodin?</h3>
<p>Lovablen mukaan koodi on käyttäjän omaa. Kun projekti synkronoidaan GitHubiin, kopio on omassa hallinnassa ja kehittäjä voi jatkaa työtä ilman Lovablea.</p>
<h3 id="voiko-woocommerce-kaupan-siirtaa-lovableen">Voiko WooCommerce-kaupan siirtää Lovableen?</h3>
<p>Voi. Tuotteet, asiakkaat ja tilaushistoria viedään WooCommercesta ja tuodaan uuteen tietokantaan ja vanhoista osoitteista tehdään uudelleenohjaukset, jotta hakunäkyvyys säilyy. Käytännössä kauppa rakennetaan uudelleen, mutta Lovablella se onnistuu nopeasti.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Shopify ja Winpos samaan tahtiin: integraatio Google Cloudin Python-funktioilla</title>
      <link>https://peltopiri.com/blogi/shopify-winpos-integraatio</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/shopify-winpos-integraatio</guid>
      <pubDate>Thu, 08 Oct 2026 06:00:00 GMT</pubDate>
      <description>Shopify-verkkokaupan ja Winpos-kassan integraatio Google Cloudin Python-funktioilla: varastosaldot, maksetut tilaukset, jono ja virheiden käsittely.</description>
      <content:encoded><![CDATA[<p>Rakensin integraation, joka yhdistää Shopify-verkkokaupan ja myymälän Winpos-kassajärjestelmän. Winposista siirtyvät varastosaldot verkkokauppaan ja verkkokaupan maksetut tilaukset Winposiin automaattisesti. Integraatio on kaksi pientä Python-funktiota Google Cloudissa ilman omaa palvelinta. Funktiot pyörivät Googlen konesalissa Haminassa.</p>
<h2 id="lahtotilanne">Lähtötilanne</h2>
<p>Myymälässä myynti, varasto ja kirjanpidon pohjatiedot ovat Winposissa. Verkkokauppa toimii Shopifyssa. Ilman integraatiota saldot pitäisi päivittää verkkokauppaan käsin ja jokainen verkkotilaus kirjata kassaan erikseen. Se vie aikaa ja virheen sattuessa verkkokauppa myy tuotetta, jota ei enää ole.</p>
<h2 id="miksi-serverless-funktiot-google-cloudissa">Miksi serverless-funktiot Google Cloudissa?</h2>
<p>Integraatiossa on kaksi selkeästi rajattua tehtävää: saldojen haku ja tilausten vienti. Niihin ei tarvita omaa palvelinta eikä sovellusta, joten valitsin Google Cloud Functions -funktiot. Ne käynnistyvät tarvittaessa, laskutus perustuu käyttöön, eikä ylläpidettävää palvelinta ole. Vertailin integraatioiden ajoympäristöjä tarkemmin <a href="/palvelut/integraatiot">integraatiopalvelun sivulla</a>.</p>
<p>Winposin kassa tarjoaa REST-rajapinnan, jonka kautta tuotteet luetaan ja tilaukset viedään. Shopifyn puolella käytetään Shopifyn webhookeja ja Admin API:a.</p>
<h2 id="osa-1-varastosaldot-winposista-shopifyyn">Osa 1: varastosaldot Winposista Shopifyyn</h2>
<p>Ensimmäinen funktio hakee Winposista kaikki tuotteet saldoineen. Ajastus käynnistää haun kahdesti päivässä, kello 6 ja 18.</p>
<ul>
<li><strong>Sivutus.</strong> Tuotteita on paljon, joten ne haetaan rajapinnasta sata kerrallaan, kunnes kaikki on haettu.</li>
<li><strong>Saldojen yhteenlasku.</strong> Tuotteella voi olla saldoa useammassa varastossa. Funktio laskee ne yhteen ja poimii vain tarvittavat tiedot: EAN-koodin, tuotekoodin ja kokonaissaldon.</li>
<li><strong>Välimuisti.</strong> Koko tuotelistan haku Winposista kestää minuutteja. Siksi tulos tallennetaan Google Cloud Storageen ja Shopifyn puoli lukee saldot sieltä. Vastaus on nopea, eikä kassajärjestelmää kuormiteta joka kerta.</li>
</ul>
<h2 id="osa-2-maksetut-tilaukset-shopifysta-winposiin">Osa 2: maksetut tilaukset Shopifysta Winposiin</h2>
<p>Kun tilaus on maksettu, Shopify lähettää ilmoituksen toiselle funktiolle, joka vie tilauksen Winposiin. Siinä on enemmän tarkkuutta vaativia kohtia.</p>
<h3 id="ilmoituksen-aitous">Ilmoituksen aitous</h3>
<p>Funktion osoite on julkinen, joten jokaisen pyynnön aitous tarkistetaan. Shopify allekirjoittaa jokaisen webhookin ja funktio laskee allekirjoituksen itse ja vertaa sitä. Väärennetty pyyntö hylätään ennen kuin mitään tehdään.</p>
<h3 id="viiden-sekunnin-saanto-ja-jono">Viiden sekunnin sääntö ja jono</h3>
<p><a href="https://shopify.dev/docs/apps/build/webhooks/troubleshooting">Shopifyn ohjeiden</a> mukaan webhookiin pitää vastata viidessä sekunnissa. Muuten Shopify tulkitsee toimituksen epäonnistuneeksi ja yrittää uudelleen. Winposin rajapinta voi vastata hitaammin, joten tilausta ei viedä heti. Se siirretään ensin Google Cloud Tasks -jonoon ja Shopify saa vastauksen saman tien.</p>
<p>Jonolla on kaksi muutakin etua:</p>
<ul>
<li><strong>Uudelleenyritykset.</strong> Jos Winpos ei vastaa tai hylkää tilauksen, jono yrittää uudelleen kasvavin välein useamman kerran.</li>
<li><strong>Ei tuplatilauksia.</strong> Jonon tehtävä nimetään Shopifyn webhook-tunnisteen mukaan. Jos Shopify lähettää saman ilmoituksen uudelleen, sitä ei lisätä jonoon toista kertaa.</li>
</ul>
<h3 id="tilauksen-muuntaminen-winposin-muotoon">Tilauksen muuntaminen Winposin muotoon</h3>
<p>Shopify ja Winpos kuvaavat tilauksen eri tavoin, joten suurin osa koodista on muunnosta:</p>
<ul>
<li><strong>Tuotteiden tunnistus viivakoodilla.</strong> Shopifyn tilausilmoituksessa ei ole tuotteen viivakoodia, joten funktio hakee sen Shopifyn rajapinnasta tuotteen versioiden tiedoista. Winposissa tuote tunnistetaan juuri viivakoodilla.</li>
<li><strong>Alennukset.</strong> Winposin erillinen alennusrivi vaatisi kassan oman alennustaulukon tunnisteen, jota Shopifyssa ei ole. Siksi alennus netotetaan tuoterivin hintaan.</li>
<li><strong>Toimituskulut.</strong> Winposissa toimituskulut ovat oma tuotteensa, joten ne viedään tuoterivinä.</li>
<li><strong>Asiakas- ja maksutiedot.</strong> Asiakkaan nimi, osoite ja yhteystiedot siirtyvät tilauksen otsikkotietoihin ja maksurivi kirjataan sovitulle maksutavalle.</li>
</ul>
<h2 id="kun-jokin-menee-pieleen">Kun jokin menee pieleen</h2>
<p>Integraatio on rakennettu niin, ettei virhe jää huomaamatta:</p>
<ul>
<li><strong>Puuttuva viivakoodi.</strong> Jos tuotteelta puuttuu viivakoodi, riviä ei voi viedä Winposiin. Muut rivit viedään, tilaukseen lisätään huomautusrivi ja minulle lähtee sähköpostihälytys, jossa luetellaan puuttuvat tuotteet.</li>
<li><strong>Winpos hylkää tilauksen.</strong> Funktio tarkistaa Winposin vastauksesta, hyväksyttiinkö tilaus. Jos ei hyväksytty, tehtävä palautuu jonoon ja sitä yritetään uudelleen.</li>
<li><strong>Lokit.</strong> Jokaisen tilauksen Shopify-tiedot, Winposiin lähetetty tilaus ja Winposin vastaus kirjataan Google Cloudin lokiin, joten ongelmatilanteen voi selvittää jälkikäteen.</li>
</ul>
<h2 id="mita-tasta-kannattaa-ottaa-mukaan">Mitä tästä kannattaa ottaa mukaan</h2>
<ul>
<li><strong>Sovi kassan asetukset etukäteen.</strong> Kassanumero, varasto, kustannuspaikka ja maksutapa sovitaan Winpos-käyttäjän kanssa ennen kuin ensimmäinen tilaus viedään.</li>
<li><strong>Tuotetiedot ratkaisevat.</strong> Integraatio on yhtä luotettava kuin viivakoodit. Kun ne ovat kunnossa molemmissa järjestelmissä, tilaukset kulkevat ilman käsityötä.</li>
<li><strong>Pieni integraatio ei tarvitse palvelinta.</strong> Kaksi rajattua funktiota, ajastus ja jono riittävät. Jos järjestelmiä tulee lisää, sama logiikka siirtyy tarvittaessa omaksi sovelluksekseen.</li>
</ul>
<p>Jos haluat verkkokaupan ja kassan tai toiminnanohjauksen keskustelemaan keskenään, lue lisää <a href="/palvelut/integraatiot">integraatioista</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="voiko-shopifyn-yhdistaa-winposiin">Voiko Shopifyn yhdistää Winposiin?</h3>
<p>Voi. Winposin REST-rajapinnan kautta saldot saa verkkokauppaan ja verkkotilaukset kassaan. Ennen toteutusta kannattaa selvittää, mitkä rajapinnan ominaisuudet omassa Winpos-ympäristössä ovat käytössä.</p>
<h3 id="kuinka-usein-varastosaldot-paivittyvat">Kuinka usein varastosaldot päivittyvät?</h3>
<p>Tässä toteutuksessa kahdesti päivässä. Tiheys on asetus, jota voi muuttaa tarpeen mukaan. Tihein mahdollinen päivitysväli riippuu siitä, kuinka paljon kuormaa kassajärjestelmän rajapinta kestää.</p>
<h3 id="mita-tapahtuu-jos-winpos-ei-ole-tavoitettavissa">Mitä tapahtuu, jos Winpos ei ole tavoitettavissa?</h3>
<p>Tilaus jää jonoon ja sitä yritetään uudelleen automaattisesti. Shopifyn puolella tilaus on jo vastaanotettu, joten asiakkaan ostokseen katkos ei vaikuta.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Miksi WooCommerce-kauppa hidastuu ja miten se korjataan</title>
      <link>https://peltopiri.com/blogi/woocommerce-hidas</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/woocommerce-hidas</guid>
      <pubDate>Thu, 17 Sep 2026 06:00:00 GMT</pubDate>
      <description>Hidas verkkokauppa johtuu harvoin yhdestä asiasta. Käyn läpi yleisimmät syyt: lisäosat, tietokanta, välimuisti, hosting ja monikielisyys.</description>
      <content:encoded><![CDATA[<p>WooCommerce-kauppa hidastuu yleensä vähitellen: lisäosia kertyy, tietokanta paisuu ja kävijämäärä kasvaa samalla palvelimella, jolla kauppa avattiin. Hitaus johtuu harvoin yhdestä asiasta, joten korjaus alkaa mittaamisesta, ei uuden välimuistilisäosan asentamisesta. Tässä artikkelissa käyn läpi yleisimmät löytämäni syyt ja niiden korjaukset.</p>
<h2 id="miksi-verkkokauppa-on-hitaampi-kuin-tavallinen-wordpress-sivusto">Miksi verkkokauppa on hitaampi kuin tavallinen WordPress-sivusto?</h2>
<p>Tavallisen sivuston sivut voi tallentaa välimuistiin kokonaisina. Verkkokaupassa se ei onnistu kaikkialla: ostoskori, kassa ja oma tili ovat jokaiselle kävijälle erilaisia, joten ne lasketaan joka kerta palvelimella. Lisäksi tuotteilla on paljon lisätietoja, varianteja ja hintoja, joita haetaan tietokannasta. Siksi kauppa paljastaa heikon palvelimen tai raskaan lisäosan nopeammin kuin esittelysivusto.</p>
<h2 id="lisaosat-montako-on-liikaa">Lisäosat: montako on liikaa?</h2>
<p>Lisäosien määrä ei ratkaise, vaan se, mitä ne tekevät jokaisella sivulatauksella. Yksi huonosti tehty lisäosa voi ajaa kymmeniä tietokantakyselyjä joka sivulla, kun taas kymmenen kevyttä ei näy missään.</p>
<p>Käytän mittaamiseen <a href="https://wordpress.org/plugins/query-monitor/">Query Monitor</a> -lisäosaa testiympäristössä. Se näyttää, mikä lisäosa tekee eniten kyselyjä ja mitkä kyselyt ovat hitaita. Usein syyllinen löytyy nopeasti: unohtunut tilastolisäosa, raskas sivunrakentaja tai lisäosa, joka lataa omat tiedostonsa jokaiselle sivulle, vaikka sitä käytetään vain yhdellä.</p>
<h2 id="tietokanta-paisuu-huomaamatta">Tietokanta paisuu huomaamatta</h2>
<p>Kolme asiaa kasvattaa WooCommerce-kaupan tietokantaa eniten:</p>
<ul>
<li><strong>Tilausten tallennustapa.</strong> WooCommerce siirtyi versiossa 8.2 uuteen <a href="https://developer.woocommerce.com/docs/features/high-performance-order-storage/">High-Performance Order Storage</a> -tallennukseen (HPOS), jossa tilaukset ovat omissa tauluissaan. Uusissa kaupoissa se on oletuksena päällä, mutta vanhoissa kaupoissa se pitää ottaa käyttöön itse. Jos kauppasi on avattu ennen syksyä 2023, tarkista tilanne kohdasta WooCommerce → Asetukset → Lisäasetukset → Ominaisuudet.</li>
<li><strong>Ajastettujen tehtävien loki.</strong> WooCommerce ja monet lisäosat käyttävät Action Scheduler -jonoa. Valmiiden tehtävien lokit jäävät tauluihin ja vilkkaassa kaupassa niitä voi olla satojatuhansia rivejä.</li>
<li><strong>Automaattisesti ladattavat asetukset.</strong> WordPress lataa osan asetuksista jokaisella sivulatauksella. Kun lisäosat tallentavat sinne isoja tietoja, jokainen sivu hidastuu. WordPress 6.6 lisäsi Sivuston terveys -työkaluun <a href="https://make.wordpress.org/core/2024/06/18/options-api-disabling-autoload-for-large-options/">tarkistuksen</a>, joka varoittaa, kun näitä tietoja on yhteensä noin 800 kt.</li>
</ul>
<p>Tietokannan siivoaminen tarkoittaa käytännössä rivien poistamista, joten se tehdään aina varmuuskopion kanssa ja ensin testiympäristössä.</p>
<h2 id="kuinka-monta-variaatiota-on-liikaa">Kuinka monta variaatiota on liikaa?</h2>
<p>WooCommercessa jokainen tuotteen muunnelma, eli variaatio, on tietokannassa oma tuotteensa: sillä on oma rivi sekä omat hinta-, varasto-, tuotekoodi- ja ominaisuustietonsa. Kun paidalla on viisi kokoa ja kuusi väriä, variaatioita on 30. Kun mukaan tulee vielä materiaali ja painatus, määrä kasvaa nopeasti satoihin.</p>
<p>WooCommerce varautuu tähän itse. <a href="https://woocommerce.com/document/change-limit-on-number-of-variations-for-dynamic-variable-product-dropdowns/">Sen ohjeiden mukaan</a> tuotesivun käytös muuttuu, kun variaatioita on yli 30:</p>
<ul>
<li><strong>Enintään 30 variaatiota: valikot ovat dynaamisia.</strong> Kun T-paidalla on ominaisuudet Koko ja Väri ja asiakas valitsee koon, värivalikko päivittyy näyttämään vain ne värit, joita valitussa koossa on saatavilla.</li>
<li><strong>Yli 30 variaatiota: valikot ovat staattisia.</strong> Värivalikko näyttää kaikki värit, vaikka osaa niistä ei olisi valitussa koossa. Asiakas huomaa sen vasta valittuaan, kun sivulle tulee ilmoitus, ettei yhdistelmää löydy ja pitää valita toinen.</li>
</ul>
<p>Raja on olemassa suorituskyvyn takia. Jos saatavilla olevat yhdistelmät pitää laskea uudelleen jokaisen valinnan jälkeen, se hidastaa tuotesivua sitä enemmän, mitä enemmän variaatioita on.</p>
<p>Rajaa voi muuttaa suodattimella <code>woocommerce_ajax_variation_threshold</code>, esimerkiksi teeman <code>functions.php</code>-tiedostossa:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-php">add_filter( &#39;woocommerce_ajax_variation_threshold&#39;, function ( $qty, $product ) {
	return 50;
}, 10, 2 );
</code></pre>
<p>WooCommerce neuvoo valitsemaan pienimmän arvon, joka kaupalle riittää, koska suurempi raja hidastaa tuotesivuja. Esimerkki nostaa rajan kaikille tuotteille. Suodatin saa parametrina myös tuotteen, joten rajan voi nostaa vain niille tuotteille, jotka sitä oikeasti tarvitsevat.</p>
<p>Muutama kymmenen variaatiota toimii hyvin. Satojen kohdalla tuotesivu ja tuotteen muokkaus hallintapaneelissa hidastuvat selvästi. Olen törmännyt kauppoihin, joissa yhdellä päätuotteella oli noin tuhat variaatiota. Silloin palvelin on kovilla jokaisella tuotesivun latauksella ja yksikin tuotteen tallennus voi kestää pitkään.</p>
<p>Ratkaisuja on useita:</p>
<ul>
<li><strong>Variaatio vain, kun se on tarpeen.</strong> Variaatio kannattaa tehdä vain silloin, kun yhdistelmällä on oma hinta, varasto tai tuotekoodi. Valinnat, jotka eivät vaikuta näihin, kuten kaiverrusteksti tai lahjapaketointi, kannattaa toteuttaa tuotteen lisäkenttinä.</li>
<li><strong>Jaa tuote useaksi tuotteeksi.</strong> Esimerkiksi jokainen malli tai materiaali voi olla oma tuotteensa, jonka sisällä valitaan koko ja väri. Tuotteet linkitetään toisiinsa, jotta asiakas löytää vaihtoehdot.</li>
<li><strong>Laske hinta säännöllä.</strong> Mittatilaustuotteissa ja konfiguraattoreissa jokaista yhdistelmää ei kannata luoda valmiiksi. Hinta lasketaan asiakkaan valintojen perusteella vasta, kun valinnat on tehty. Tähän sopivat esimerkiksi WooCommercen oma maksullinen <a href="https://woocommerce.com/products/product-add-ons/">Product Add-Ons</a> tai ilmainen <a href="https://wordpress.org/plugins/woocommerce-product-addon/">PPOM</a>, joiden avulla tuotteeseen lisätään valintoja, joilla on oma hintansa, ilman että jokaisesta yhdistelmästä tulee variaatio.</li>
<li><strong>Älä nosta rajaa sokeasti.</strong> Jos 30 variaation raja tulee vastaan, se on merkki tuoterakenteen tarkistamisesta, ei pelkästä asetuksen muuttamisesta.</li>
</ul>
<h2 id="valimuisti-sivu-objektit-ja-selain">Välimuisti: sivu, objektit ja selain</h2>
<p>Välimuisteja on kolmea tasoa ja kauppa tarvitsee yleensä niitä kaikkia:</p>
<ol>
<li><strong>Sivuvälimuisti</strong> tallentaa valmiit sivut. Tuote- ja kategoriasivuille se sopii hyvin, mutta ostoskori, kassa ja oma tili pitää jättää sen ulkopuolelle.</li>
<li><strong>Objektivälimuisti</strong> (esimerkiksi Redis) tallentaa tietokantakyselyjen tulokset muistiin. Siitä on eniten hyötyä juuri niillä sivuilla, joita ei voi tallentaa kokonaisina.</li>
<li><strong>Selainvälimuisti</strong> ja kuvien optimointi huolehtivat siitä, ettei kävijän selain lataa samoja tiedostoja uudelleen.</li>
</ol>
<p>Pelkkä välimuistilisäosa ei korjaa hidasta palvelinta. Se piilottaa ongelman etusivulta, mutta kassa on edelleen hidas ja juuri siellä kauppa tehdään.</p>
<h2 id="hosting-ratkaisee-enemman-kuin-moni-luulee">Hosting ratkaisee enemmän kuin moni luulee</h2>
<p>Halvassa webhotellissa kauppa jakaa palvelimen kymmenien muiden sivustojen kanssa. Kun naapurilla on ruuhkaa, sinunkin kassasi hidastuu. WordPressiin erikoistunut hallinnoitu hosting, kuten <a href="https://seravo.com/fi/">Seravo</a>, hoitaa valmiiksi palvelimen välimuistin, PHP-version ja päivitykset. Ennen kuin kauppaa optimoidaan viikkoja, kannattaa tarkistaa, onko palvelin edes riittävä.</p>
<h2 id="wpml-monikielisyyden-superhidastaja">WPML: monikielisyyden superhidastaja</h2>
<p>Monikielinen kauppa on oma lukunsa. Omassa työssäni WPML on toistuvasti ollut yksi suurimmista yksittäisistä hidastajista. Se on monipuolinen ja kattaa lähes kaiken, mutta se tuo mukanaan omat tietokantataulunsa, merkkijonojen käännökset ja lisää kyselyjä jokaiselle sivulle. WooCommercen kanssa tarvitaan vielä erillinen WooCommerce Multilingual -lisäosa, joka lisää kuormaa entisestään.</p>
<p>Mittaukset vaihtelevat sivustoittain, eikä riippumatonta vertailua ole. WPML:n oma tuki on myös kiistänyt joissakin tapauksissa merkittävän hidastuksen. Siksi mittaan aina kyseisen kaupan omilla tuotesivuilla, enkä luota yleistyksiin.</p>
<h2 id="miksi-suosittelen-polylangia">Miksi suosittelen Polylangia?</h2>
<p>Uusiin monikielisiin kauppoihin suosittelen <a href="https://polylang.pro/">Polylangia</a>. Se käyttää WordPressin omia rakenteita kielten ja käännösten tallentamiseen, joten se on kevyempi ja ennustettavampi. WooCommerce-kauppaan tarvitaan maksullinen Polylang for WooCommerce -lisäosa, joka kääntää kaupan sivut, sähköpostit ja tuoteominaisuudet sekä synkronoi muun muassa varastosaldot kieliversioiden välillä.</p>
<p>Polylangilla on omat rajoituksensa: siinä ei ole valmista valuutanvaihtoa ja hyvin monimutkaisissa tuotevalikoimissa WPML:n laajemmat työkalut voivat olla tarpeen. Vaihto WPML:stä Polylangiin on lisäksi aina oma projektinsa, koska käännökset pitää siirtää. Siksi teen vaihdon vain, kun mittaus osoittaa, että hyöty on todellinen.</p>
<h2 id="mista-aloittaa">Mistä aloittaa?</h2>
<ol>
<li>Mittaa nykytila: sivun latausaika, palvelimen vasteaika ja kassan nopeus.</li>
<li>Katso Sivuston terveys -työkalusta, onko varoituksia. Tarkista myös, onko HPOS käytössä.</li>
<li>Etsi Query Monitorilla raskaimmat lisäosat ja hitaimmat kyselyt testiympäristössä.</li>
<li>Tarkista, onko kaupassa tuotteita, joilla on satoja variaatioita.</li>
<li>Varmista, että palvelin ja objektivälimuisti ovat kunnossa.</li>
<li>Vasta sitten optimoi kuvat, skriptit ja muut yksityiskohdat.</li>
</ol>
<p>Jos kauppasi kaipaa tällaista läpikäyntiä, se kuuluu <a href="/palvelut/wordpress-woocommerce">WordPress- ja WooCommerce-työhöni</a>. Nopeus ja tekninen rakenne käydään läpi myös <a href="/palvelut/seo-geo-saavutettavuusauditit">SEO- ja GEO-auditissa</a>, jos haluat arvion koko sivustosta.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="nopeuttaako-valimuistilisaosa-woocommerce-kauppaa">Nopeuttaako välimuistilisäosa WooCommerce-kauppaa?</h3>
<p>Osittain. Se nopeuttaa tuote- ja kategoriasivuja, mutta ostoskoria, kassaa ja omaa tiliä ei voi tallentaa välimuistiin. Niiden nopeus riippuu palvelimesta, tietokannasta ja lisäosista.</p>
<h3 id="pitaisiko-hpos-ottaa-kayttoon-vanhassa-kaupassa">Pitäisikö HPOS ottaa käyttöön vanhassa kaupassa?</h3>
<p>Yleensä kyllä, kunhan kaikki käytössä olevat lisäosat tukevat sitä. WooCommerce näyttää yhteensopimattomat lisäosat asetuksissa. Siirto tehdään ensin testiympäristössä ja tilaukset synkronoidaan vanhan ja uuden tallennuksen välillä, kunnes kaikki toimii.</p>
<h3 id="montako-variaatiota-yhdella-tuotteella-voi-olla">Montako variaatiota yhdellä tuotteella voi olla?</h3>
<p>Teknistä ylärajaa ei ole, mutta WooCommerce käsittelee tuotesivulla oletuksena dynaamisesti vain 30 variaatiota. Muutama kymmenen toimii hyvin. Jos variaatioita on satoja, tuoterakenne kannattaa miettiä uudelleen.</p>
<h3 id="kannattaako-wpml-vaihtaa-polylangiin">Kannattaako WPML vaihtaa Polylangiin?</h3>
<p>Ei automaattisesti. Jos kauppa on hidas ja mittaus osoittaa WPML:n olevan suuri osa ongelmaa, vaihto voi kannattaa. Uudessa monikielisessä kaupassa valitsen yleensä Polylangin alusta asti.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Hintaseuranta ja automaattinen hinnoittelu: Winpos, WooCommerce ja PriceShape</title>
      <link>https://peltopiri.com/blogi/winpos-priceshape-hintaseuranta</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/winpos-priceshape-hintaseuranta</guid>
      <pubDate>Tue, 08 Sep 2026 06:00:00 GMT</pubDate>
      <description>Kevyt integraatio WooCommerce-palvelimella vie tuotteet Winposista PriceShapeen ja päivittää kilpailijahintojen perusteella hinnat kauppaan ja kassaan.</description>
      <content:encoded><![CDATA[<p>Kaikki integraatiot eivät tarvitse omaa palvelua. Tein elektroniikkaa myyvälle kaupalle integraation, joka vie puhelimet, tabletit ja älykellot Winpos-kassajärjestelmästä <a href="https://priceshape.com/">PriceShapen</a> hintaseurantaan ja päivittää kilpailijatiedon perusteella hinnat takaisin sekä verkkokauppaan että kassaan. Molemmat osat ajetaan kaupan omalla WooCommerce-palvelimella WP-CLI-komentoina palvelimen cronilla.</p>
<h2 id="mita-tarvittiin">Mitä tarvittiin?</h2>
<p>PriceShape on tanskalainen hinnoittelupalvelu, joka seuraa kilpailijoiden hintoja. Sitä varten se tarvitsee kaupan tuotteet ja tässä kaupassa tuotteiden ja hintojen päälähde on Winpos-kassa. Kun kilpailijoiden hinnat tiedetään, hinta pitää päivittää kahteen paikkaan: WooCommerce-verkkokauppaan ja Winposiin, jotta myymälässä ja verkossa on sama hinta.</p>
<p>Seurantaan otettiin tuoteryhmät, joissa hintakilpailu on kovinta: puhelimet, tabletit ja älykellot.</p>
<h2 id="osa-1-tuotteet-winposista-priceshapeen">Osa 1: tuotteet Winposista PriceShapeen</h2>
<ol>
<li><strong>Haku Winposista sivu kerrallaan.</strong> Tuotteet haetaan Winposin REST-rajapinnasta sata kerrallaan, kunnes kaikki on käyty läpi.</li>
<li><strong>Suodatus tuoteryhmän mukaan.</strong> Mukaan otetaan vain Winposin osastot, joihin puhelimet, tabletit ja älykellot kuuluvat.</li>
<li><strong>Tarvittavat tiedot.</strong> Jokaisesta tuotteesta poimitaan EAN-koodi, tuotekoodi, nimi, osasto ja alaosasto, hinta, tuotetyyppi ja verokanta.</li>
<li><strong>Syöte tiedostoon.</strong> Tuotteet kirjoitetaan JSON-tiedostoksi, josta PriceShape lukee ne.</li>
</ol>
<p>Winposissa on tuhansia tuotteita. Jotta PHP:n muisti ei lopu, jokaisen sivun tuotteet kirjoitetaan tiedostoon heti ja muisti vapautuu ennen seuraavaa sivua. Jos Winpos palauttaa jollekin sivulle virheen, siitä lähtee minulle sähköposti ja muut sivut käsitellään normaalisti.</p>
<h2 id="osa-2-hinnat-priceshapesta-takaisin-kauppaan">Osa 2: hinnat PriceShapesta takaisin kauppaan</h2>
<p>Toinen osa on WordPress-lisäosa, joka lisää palvelimelle WP-CLI-komennon. Komento hakee PriceShapen hintaviennin ja päivittää hinnat.</p>
<h3 id="hinnoittelusaanto">Hinnoittelusääntö</h3>
<p>Jokaiselle tuotteelle etsitään halvin hinta PriceShapen seuraamista kaupoista ja se pyöristetään ylöspäin täysiin euroihin. Hinta päivitetään vain, jos se päättyy yhdeksään, eli esimerkiksi 349 €. Muihin tuotteisiin ei kosketa. Sääntö pitää automaattisesti päivittyvät hinnat kaupan tutussa ...9 euron muodossa.</p>
<p>Tällaisia sääntöjä kannattaa miettiä tarkkaan yhdessä kauppiaan kanssa, koska ne muuttavat hintoja ilman, että kukaan katsoo niitä etukäteen.</p>
<h3 id="paivitys-woocommerceen-ja-winposiin">Päivitys WooCommerceen ja Winposiin</h3>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-php">foreach ( $targets as $sku =&gt; $new_price ) {
	// WooCommerce: vain jos hinta oikeasti muuttuu
	if ( isset( $woo_map[ $sku ] ) &amp;&amp; (string) $woo_map[ $sku ][&#39;price&#39;] !== (string) $new_price ) {
		$this-&gt;update_woo_price( $woo_map[ $sku ][&#39;id&#39;], $new_price );
	}
	// Winpos: haetaan nykyinen hinta ja päivitetään, jos se poikkeaa
	$this-&gt;update_winpos_price( $sku, $new_price );
}
</code></pre>
<ul>
<li><strong>WooCommerce.</strong> Hinta tallennetaan WooCommercen omien toimintojen kautta, jotta välimuistit tyhjenevät ja muut lisäosat, kuten hakukonelisäosa, saavat tiedon muutoksesta.</li>
<li><strong>Winpos.</strong> Integraatio hakee tuotteen nykyiset tiedot kassasta ja lähettää uuden hinnan vain, jos se poikkeaa nykyisestä.</li>
<li><strong>Loki.</strong> Jokainen muutos kirjataan lokiin vanhan ja uuden hinnan kanssa ja ajon lopuksi tulostetaan yhteenveto päivitetyistä tuotteista.</li>
</ul>
<h3 id="muisti-ja-nopeus">Muisti ja nopeus</h3>
<p>WordPress ja WooCommerce on tehty ennen kaikkea sivulatauksia varten ja tuhansien tuotteiden käsittely yhdellä ajolla kuluttaa helposti kaiken muistin. Siksi komento:</p>
<ul>
<li>etsii tuotteet tuotekoodin (SKU) perusteella yhdellä tietokantakyselyllä 500 tuotetta kerrallaan sen sijaan, että jokainen tuote haettaisiin erikseen</li>
<li>lataa WooCommercen tuoteolion vain niille tuotteille, joiden hinta oikeasti muuttuu</li>
<li>tyhjentää WordPressin välimuistin ajon aikana ja raportoi lopuksi muistin enimmäiskäytön.</li>
</ul>
<h2 id="miksi-woocommerce-palvelimelle">Miksi WooCommerce-palvelimelle?</h2>
<ul>
<li><strong>Tehtävät ovat selkeitä.</strong> Syötteen kirjoitus ja hintojen päivitys ajastetusti. Jonoja tai erillistä tietokantaa ei tarvita.</li>
<li><strong>Palvelin on jo olemassa.</strong> Erillistä pilvipalvelua ei tarvitse perustaa, maksaa eikä ylläpitää.</li>
<li><strong>Suora pääsy kauppaan.</strong> Hinnat päivittyvät WooCommercen omien toimintojen kautta samalla tavalla kuin hallintapaneelista.</li>
<li><strong>Ajo ei hidasta kauppaa.</strong> Ajot käynnistää palvelimen cron eikä WordPressin sivulatauksiin sidottu WP-Cron, joten ne eivät vaikuta kävijöiden sivulatauksiin.</li>
</ul>
<p>Vertailin integraatioiden ajoympäristöjä tarkemmin <a href="/palvelut/integraatiot">integraatiopalvelun sivulla</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="muuttaako-integraatio-hintoja-ilman-ihmista">Muuttaako integraatio hintoja ilman ihmistä?</h3>
<p>Muuttaa, mutta vain sovitun säännön mukaan ja vain seurattavissa tuoteryhmissä. Jokainen muutos kirjataan lokiin, joten muutokset voi tarkistaa jälkikäteen.</p>
<h3 id="miksi-hinnat-paivitetaan-seka-verkkokauppaan-etta-kassaan">Miksi hinnat päivitetään sekä verkkokauppaan että kassaan?</h3>
<p>Jotta asiakas saa saman hinnan myymälässä ja verkossa. Jos hinta päivittyisi vain verkkokauppaan, myymälän hinta jäisi jälkeen.</p>
<h3 id="miksi-seurantaan-otettiin-vain-osa-tuotteista">Miksi seurantaan otettiin vain osa tuotteista?</h3>
<p>Hintavertailu on hyödyllisintä tuotteissa, joita myydään monessa kaupassa samalla EAN-koodilla ja joiden hintoja asiakkaat vertailevat. Puhelimet, tabletit ja älykellot ovat juuri sellaisia.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Mitä GEO tarkoittaa käytännössä ja tarvitseeko pieni yritys rakenteista dataa?</title>
      <link>https://peltopiri.com/blogi/geo-ja-rakenteinen-data</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/geo-ja-rakenteinen-data</guid>
      <pubDate>Wed, 26 Aug 2026 06:00:00 GMT</pubDate>
      <description>GEO on sivuston optimointia tekoälyhakuja varten. Selitän selkokielellä, mitä se vaatii, mitä JSON-LD tekee ja mistä pienen yrityksen kannattaa aloittaa.</description>
      <content:encoded><![CDATA[<p>GEO (generative engine optimization) tarkoittaa sivuston optimointia niin, että tekoälyhaut, kuten ChatGPT, Gemini, Claude ja Googlen AI Overviews, ymmärtävät sen oikein ja voivat käyttää sitä lähteenä vastauksissaan. Käytännössä kyse on samoista perusasioista kuin hyvässä hakukoneoptimoinnissa: sivuston pitää olla löydettävissä, sisällön pitää vastata kysymyksiin suoraan ja yrityksen tietojen pitää olla johdonmukaisia. Rakenteinen data (JSON-LD) on yksi työkalu tähän, mutta ei taikatemppu.</p>
<h2 id="mista-geo-termi-tulee">Mistä GEO-termi tulee?</h2>
<p>Termi tulee vuonna 2023 julkaistusta <a href="https://arxiv.org/abs/2311.09735">tutkimusartikkelista</a>, jossa tutkittiin, miten sisällön muokkaaminen vaikuttaa siihen, kuinka usein tekoälyhakukone viittaa siihen. Sittemmin termiä on käytetty laajemmin kaikesta työstä, jolla sivustoa parannetaan tekoälyhakuja varten. Uutta tieteenalaa se ei ole: suurin osa toimenpiteistä on tuttuja hakukoneoptimoinnista.</p>
<h2 id="mita-geo-on-kaytannossa">Mitä GEO on käytännössä?</h2>
<p>Kun auditoin sivustoa tekoälyhakujen näkökulmasta, käyn läpi neljä asiaa:</p>
<ol>
<li><strong>Pääsevätkö tekoälyhakujen botit sivustolle?</strong> Tekoälypalveluilla on omat botit ja ne voi estää robots.txt-tiedostossa. Tärkeää on erottaa, mikä botti tekee mitä. Esimerkiksi OpenAI:n <a href="https://developers.openai.com/api/docs/bots">ohjeiden mukaan</a> OAI-SearchBot ratkaisee, näkyykö sivusto ChatGPT:n hakutuloksissa, kun taas GPTBot kerää aineistoa mallien koulutukseen. Googlen <a href="https://developers.google.com/search/docs/crawling-indexing/google-common-crawlers">Google-Extended</a> puolestaan koskee Gemini-mallien koulutusta, eikä sen estäminen Googlen mukaan vaikuta Google-hakuun. Näkyvyyttä voi siis menettää vahingossa, jos estää väärän botin.</li>
<li><strong>Vastaako sisältö kysymyksiin suoraan?</strong> Tekoäly poimii sivulta kohtia, jotka vastaavat kysymykseen. Jos vastaus on piilotettu kolmannen kappaleen loppuun markkinointitekstin sekaan, sitä ei löydetä. Hyvä rakenne on yksinkertainen: kysymys väliotsikkona, suora vastaus heti sen alla.</li>
<li><strong>Ovatko yrityksen tiedot johdonmukaisia?</strong> Nimen, osoitteen, palvelujen ja yhteystietojen pitää olla samat sivustolla, Googlen yritysprofiilissa ja muissa palveluissa.</li>
<li><strong>Onko väitteille lähteet?</strong> Tekoäly luottaa sisältöön, jossa on tarkkoja tietoja ja viittauksia, enemmän kuin yleiseen ylistykseen.</li>
</ol>
<h2 id="mita-json-ld-tekee">Mitä JSON-LD tekee?</h2>
<p>JSON-LD on tapa kertoa koneelle sivun sisällöstä rakenteisesti. Ihmiselle sivu näyttää samalta, mutta sivun koodissa on lisäksi esimerkiksi tieto siitä, että kyse on yrityksestä, jolla on tietty nimi, osoite ja palvelut, tai artikkelista, jolla on kirjoittaja ja julkaisupäivä.</p>
<p>Tältä se näyttää pelkistettynä:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-json">{
  &quot;@context&quot;: &quot;https://schema.org&quot;,
  &quot;@type&quot;: &quot;ProfessionalService&quot;,
  &quot;name&quot;: &quot;Esimerkki Oy&quot;,
  &quot;address&quot;: { &quot;@type&quot;: &quot;PostalAddress&quot;, &quot;addressLocality&quot;: &quot;Kurikka&quot; },
  &quot;telephone&quot;: &quot;+358 40 123 4567&quot;
}
</code></pre>
<p>Sanasto tulee <a href="https://schema.org/">Schema.orgista</a>, jota Google, Microsoft ja muut hakukoneet käyttävät yhteisesti.</p>
<h2 id="auttaako-rakenteinen-data-nakymaan-tekoalyhauissa">Auttaako rakenteinen data näkymään tekoälyhauissa?</h2>
<p>Rehellinen vastaus: se auttaa koneita ymmärtämään sivua, mutta mikään tietty rakenne ei takaa näkyvyyttä. Googlen <a href="https://developers.google.com/search/docs/appearance/ai-features">ohjeissa tekoälyominaisuuksista</a> ei vaadita mitään erityistä tekoälyä varten tehtyä rakennetta. Ohjeet korostavat, että rakenteisen datan pitää vastata sivulla näkyvää tekstiä.</p>
<p>On myös hyvä tietää, että rakenteisen datan hyödyt muuttuvat. Google rajasi FAQ-rikastetut tulokset vuonna 2023 <a href="https://developers.google.com/search/blog/2023/08/howto-faq-changes">vain viranomais- ja terveyssivustoille</a> ja <a href="https://www.searchenginejournal.com/google-drops-faq-rich-results/574429/">Search Engine Journalin mukaan</a> ne poistuivat hausta kokonaan kesällä 2026. FAQ-rakenteesta ei siis enää saa näyttävää hakutulosta. Rakenteena se kertoo edelleen selvästi, mitkä kysymykset ja vastaukset sivulla on.</p>
<h2 id="tarvitseeko-pieni-yritys-rakenteista-dataa">Tarvitseeko pieni yritys rakenteista dataa?</h2>
<p>Kyllä, mutta vähän. Pienelle yritykselle riittää yleensä:</p>
<ul>
<li><strong>Yrityksen perustiedot</strong> (Organization tai LocalBusiness): nimi, osoite, yhteystiedot ja aukioloajat.</li>
<li><strong>Palvelut</strong> (Service) palvelusivuille.</li>
<li><strong>Artikkelit</strong> (BlogPosting), jos sivustolla on blogi.</li>
<li><strong>Murupolku</strong> (BreadcrumbList), jos sivustolla on useampi taso.</li>
</ul>
<p>WordPressissä nämä saa usein hakukonelisäosalla. Tärkeintä on tarkistaa, että tiedot ovat oikein ja samat kuin sivulla, koska lisäosan oletusasetukset tuottavat helposti puutteellista tai ristiriitaista dataa. Tarkistukseen sopii Googlen <a href="https://search.google.com/test/rich-results">Rich Results Test</a> tai Schema.orgin <a href="https://validator.schema.org/">validaattori</a>.</p>
<h2 id="mista-aloittaa">Mistä aloittaa?</h2>
<ol>
<li>Tarkista robots.txt: estätkö vahingossa jonkin hakubotin?</li>
<li>Kirjoita palvelusivujen ensimmäinen kappale niin, että se vastaa suoraan kysymykseen &quot;mitä te teette ja kenelle&quot;.</li>
<li>Lisää yrityksen perustiedot rakenteisena datana ja tarkista ne validaattorilla.</li>
<li>Varmista, että yrityksen tiedot ovat samat kaikkialla verkossa.</li>
</ol>
<p>Jos haluat, että joku käy tämän läpi puolestasi, se kuuluu <a href="/palvelut/seo-geo-saavutettavuusauditit">SEO-, GEO- ja saavutettavuusauditteihin</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="korvaako-geo-hakukoneoptimoinnin">Korvaako GEO hakukoneoptimoinnin?</h3>
<p>Ei. GEO rakentuu hakukoneoptimoinnin päälle. Jos sivusto ei näy tavallisessa haussa, se tuskin näkyy tekoälyhauissakaan, koska moni tekoälyhaku hakee tietonsa juuri hakukoneiden kautta.</p>
<h3 id="pitaisiko-tekoalybotit-estaa">Pitäisikö tekoälybotit estää?</h3>
<p>Se riippuu siitä, mitä haluat. Jos haluat näkyä tekoälyhakujen vastauksissa, älä estä hakuun käytettäviä botteja. Mallien koulutukseen käytettävät botit voi halutessaan estää erikseen, eikä se vaikuta hakunäkyvyyteen.</p>
<h3 id="voiko-rakenteisen-datan-lisata-itse">Voiko rakenteisen datan lisätä itse?</h3>
<p>Perustiedot onnistuvat yleensä hakukonelisäosan asetuksista. Kun dataa tarvitaan palveluille, tuotteille tai omille sisältötyypeille, se kannattaa rakentaa teemaan tai lisäosaan, jotta se päivittyy automaattisesti sisällön mukana.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Lovable, Framer, v0 ja muut – tekoälytyökalut oman sivuston rakentamiseen</title>
      <link>https://peltopiri.com/blogi/tekoaly-sivustotyokalut-vertailu</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/tekoaly-sivustotyokalut-vertailu</guid>
      <pubDate>Tue, 04 Aug 2026 06:00:00 GMT</pubDate>
      <description>Vertailen Lovablea, Frameria, v0:aa, Boltia, Base44:ää ja Figma Makea: mihin kukin sopii, kuka omistaa koodin ja mihin kannattaa varautua.</description>
      <content:encoded><![CDATA[<p>Tekoälyllä sivuston tai sovelluksen saa nyt rakennettua kuvailemalla sen, mutta työkalut eivät ole keskenään samanlaisia. Framer on markkinointisivustojen suunnittelutyökalu, jossa tekoäly auttaa. Lovable, v0, Bolt ja Base44 rakentavat kokonaisia sovelluksia. Figma Make vie suunnittelijan kuvat toimiviksi prototyypeiksi. Valinta riippuu siitä, tarvitsetko näyttävän sivuston vai sovelluksen ja siitä, haluatko koodin omaan hallintaasi.</p>
<h2 id="kaksi-eri-lajia-sivustotyokalut-ja-sovelluskoneet">Kaksi eri lajia: sivustotyökalut ja sovelluskoneet</h2>
<p>Kannattaa erottaa kaksi ryhmää:</p>
<ul>
<li><strong>Sivustotyökalut</strong>, kuten Framer. Lopputulos on julkaistu sivusto palvelun omalla alustalla. Sisällönhallinta, hosting ja ulkoasun muokkaus ovat samassa paikassa, mutta koodia ei saa ulos.</li>
<li><strong>Sovelluskoneet</strong>, kuten Lovable, v0, Bolt ja Base44. Ne kirjoittavat oikeaa koodia (yleensä Reactia) ja tarjoavat tietokannan, kirjautumisen ja julkaisun. Niillä voi tehdä myös sivuston, mutta vahvuus on toiminnallisuudessa.</li>
</ul>
<h2 id="lovable-koko-sovellus-kuvailemalla">Lovable: koko sovellus kuvailemalla</h2>
<p><a href="https://lovable.dev/">Lovable</a> tuottaa React-sovelluksen, jonka taustapalveluna on Supabaseen perustuva Lovable Cloud tai oma Supabase-projekti. Projektin voi synkronoida GitHubiin, joten koodi on käyttäjän omaa ja kehittäjä voi jatkaa sitä tavallisilla työkaluilla. Kahdesta Lovablella tehdystä verkkokaupasta kerron tarkemmin artikkelissa <a href="/blogi/lovable-sivusto-tai-sovellus">Sivuston tai sovelluksen rakentaminen Lovablella</a>.</p>
<p><strong>Sopii</strong>, kun omistaja haluaa kehittää palveluaan itse ja palvelussa on kirjautumista tai omaa logiikkaa.</p>
<h2 id="framer-nayttava-sivusto-suunnittelijan-tyokalulla">Framer: näyttävä sivusto suunnittelijan työkalulla</h2>
<p><a href="https://www.framer.com/">Framer</a> on alun perin suunnittelutyökalu, josta on tullut sivustoalusta. Sen <a href="https://www.framer.com/ai/">tekoälyominaisuuksiin</a> kuuluu agentti, joka luo sivuja ja osioita kehotteesta, sekä agentit sisällönhallintaan, omiin koodikomponentteihin ja julkaisua edeltävään tarkistukseen. Tarkistusagentti etsii esimerkiksi kontrastiongelmia, puuttuvia kuvien vaihtoehtoisia tekstejä ja SEO-puutteita.</p>
<p>Framerin oman <a href="https://www.framer.com/help/articles/can-i-export-my-website-to-html-and-self-host-it/">ohjeen mukaan</a> sivustoa ei voi viedä HTML-tiedostoina omalle palvelimelle, koska julkaisu nojaa Framerin omiin taustapalveluihin. Sivusto pysyy siis Framerissa.</p>
<p><strong>Sopii</strong> markkinointisivustoon, jonka ulkoasu on tärkein ja jota suunnittelija päivittää itse.</p>
<h2 id="v0-vercelin-tyokalu-react-ja-next-js-koodiin">v0: Vercelin työkalu React- ja Next.js-koodiin</h2>
<p><a href="https://v0.app/">v0</a> on Vercelin tekoälyagentti, joka rakentaa käyttöliittymiä ja kokonaisia sovelluksia. <a href="https://v0.app/docs">Dokumentaation</a> mukaan se käyttää muun muassa Next.js:ää, Tailwindia ja shadcn/ui-komponentteja ja julkaisu tapahtuu yhdellä klikkauksella Verceliin. GitHub-yhteydessä v0 <a href="https://v0.app/docs/github">tekee muutokset omaan haaraansa</a> eikä koskaan suoraan päähaaraan, joten muutokset tulevat tarkistettaviksi pull requestina.</p>
<p><strong>Sopii</strong>, kun projektissa on jo kehittäjä tai Next.js-sovellus ja tekoälyä halutaan käyttää osana tavallista kehitystyötä.</p>
<h2 id="bolt-nopea-alku-selaimessa">Bolt: nopea alku selaimessa</h2>
<p><a href="https://bolt.new/">Bolt</a> rakentaa sivustoja, sovelluksia ja prototyyppejä keskustelemalla. Bolt Cloud tarjoaa hostingin, omat verkkotunnukset, tietokannat ja käyttäjien kirjautumisen. Projektin voi aloittaa myös Figma-suunnitelmasta tai GitHub-projektista.</p>
<p><strong>Sopii</strong> prototyyppeihin ja demoihin, joissa tärkeintä on päästä nopeasti näyttämään jotain toimivaa.</p>
<h2 id="base44-wixin-sovelluskone">Base44: Wixin sovelluskone</h2>
<p><a href="https://base44.com/">Base44</a> on israelilainen palvelu, jolla rakennetaan sovelluksia tavallisella kielellä. Wix <a href="https://www.wix.com/press-room/home/post/wix-further-expands-into-vibe-coding-with-acquisition-of-base44-a-hyper-growth-startup-that-simplif">osti sen kesäkuussa 2025</a> ja se jatkaa omana tuotteenaan. Base44 sisältää taustapalvelut valmiina, joten se sopii esimerkiksi sisäisiin työkaluihin ja pieniin liiketoimintasovelluksiin.</p>
<p><strong>Sopii</strong>, kun tarvitset toimivan sovelluksen nopeasti etkä halua miettiä taustapalveluita lainkaan.</p>
<h2 id="figma-make-suunnitelmasta-toimivaksi-prototyypiksi">Figma Make: suunnitelmasta toimivaksi prototyypiksi</h2>
<p><a href="https://www.figma.com/make/">Figma Make</a> tekee kehotteista, Figma-kehyksistä ja suunnittelujärjestelmistä toimivia prototyyppejä ja sovelluksia. Siinä on myös sisällönhallinta, joka perustuu Payload CMS:ään. Figman sivun mukaan suoraan tuotantoon julkaiseminen on vasta tulossa, joten tällä hetkellä se on ennen kaikkea suunnittelijan työkalu.</p>
<p><strong>Sopii</strong> tiimille, jonka suunnittelu on jo Figmassa ja joka haluaa testata ideoita toimivina ennen toteutusta.</p>
<h2 id="mita-kaikissa-kannattaa-tarkistaa">Mitä kaikissa kannattaa tarkistaa?</h2>
<p><strong>Kuka omistaa koodin?</strong> Lovablessa ja v0:ssa koodin saa omaan GitHub-varastoon. Framerissa sivusto pysyy alustalla. Muissa työkaluissa vientimahdollisuudet kannattaa tarkistaa ennen aloittamista. Jos palvelun hinta tai ehdot muuttuvat, tämä ratkaisee, kuinka helposti pääset pois.</p>
<p><strong>Tietoturva.</strong> Sovelluskoneet luovat tietokannan ja kirjautumisen, mutta käyttöoikeussäännöt ovat edelleen tekijän vastuulla. Lovablella tehdyistä sovelluksista löytyi vuonna 2025 yli sata, joiden tietokantaan pääsi ilman kirjautumista. Sama riski koskee kaikkia näitä työkaluja.</p>
<p><strong>Hinta käytännössä.</strong> Hinnoittelu perustuu yleensä krediitteihin tai viestien määrään. Kuukausihinta on helppo vertailla, mutta todellinen kulu riippuu siitä, kuinka paljon korjauskierroksia tarvitaan. Tarkista ajantasaiset hinnat palveluiden omilta sivuilta.</p>
<p><strong>Hakunäkyvyys ja saavutettavuus.</strong> Otsikot, kuvaukset, <a href="/blogi/geo-ja-rakenteinen-data">rakenteinen data</a>, otsikkorakenne ja kontrastit pitää tarkistaa kuten millä tahansa alustalla. Tekoäly tekee hyvän näköisen pohjan, mutta ei automaattisesti hyvää rakennetta.</p>
<h2 id="mika-tyokalu-kannattaa-valita">Mikä työkalu kannattaa valita?</h2>
<ul>
<li><strong>Framer</strong>, kun tarvitset näyttävän markkinointisivuston ja suunnittelija päivittää sitä itse.</li>
<li><strong>Lovable</strong>, kun omistaja haluaa rakentaa ja kehittää sovellusta itse.</li>
<li><strong>v0</strong>, kun mukana on kehittäjä ja koodi elää GitHubissa ja Vercelissä.</li>
<li><strong>Bolt</strong> nopeisiin prototyyppeihin ja demoihin.</li>
<li><strong>Base44</strong>, kun tarvitset sisäisen työkalun nopeasti.</li>
<li><strong>Figma Make</strong>, kun suunnitelma pitää saada testattavaksi ennen toteutusta.</li>
</ul>
<p>Sisältöpainotteiseen yrityssivustoon tai verkkokauppaan, jota päivittää moni ihminen ja jossa tarvitaan monikielisyyttä ja valmiita integraatioita, valitsen edelleen useimmiten <a href="/palvelut/wordpress-woocommerce">WordPressin ja WooCommercen</a>. Markkinointisivustojen vertailun löydät myös artikkelista <a href="/blogi/webflow-vai-wordpress">Webflow vai WordPress</a>.</p>
<p>Tämä sivusto on rakennettu tekoälyn avustuksella ja kokemuksista kerron artikkelissa <a href="/blogi/sivusto-tekoalyn-avustuksella">Rakensin sivustoni testiksi tekoälyn avustuksella</a>. Jos rakennat palvelua jollain näistä työkaluista ja haluat käydä läpi tietoturvan, hakunäkyvyyden tai integraatiot, autan mielelläni. Lue lisää <a href="/palvelut/tekoalyagentit">tekoälyratkaisuista</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="mika-on-paras-tekoalytyokalu-oman-sivuston-tekemiseen">Mikä on paras tekoälytyökalu oman sivuston tekemiseen?</h3>
<p>Riippuu siitä, mitä teet. Pelkkään markkinointisivustoon Framer on helpoin. Jos sivustossa on kirjautumista, tietokanta tai omaa logiikkaa, Lovable, v0, Bolt tai Base44 ovat parempia.</p>
<h3 id="voiko-tekoalylla-tehdyn-sivuston-siirtaa-myohemmin-muualle">Voiko tekoälyllä tehdyn sivuston siirtää myöhemmin muualle?</h3>
<p>Riippuu työkalusta. Lovablesta ja v0:sta koodin saa GitHubiin ja voi julkaista muualla. Framerista sivustoa ei voi viedä ulos, vaan se pitää rakentaa uudelleen.</p>
<h3 id="tarvitaanko-kehittajaa-enaa-ollenkaan">Tarvitaanko kehittäjää enää ollenkaan?</h3>
<p>Yksinkertaiseen sivustoon ei välttämättä. Kun mukana on asiakastietoja, maksuja, integraatioita tai saavutettavuusvaatimuksia, joku pitää tarkistaa, että lopputulos on turvallinen ja toimii.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Laravel Cloud vai oma palvelin Forgella? Milloin kumpikin kannattaa</title>
      <link>https://peltopiri.com/blogi/laravel-cloud-vai-forge</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/laravel-cloud-vai-forge</guid>
      <pubDate>Tue, 14 Jul 2026 06:00:00 GMT</pubDate>
      <description>Laravel Cloud hoitaa palvelimet puolestasi, Forgella hallitset omaa palvelinta. Vertailen, kumpi sopii millaiseenkin Laravel-sovellukseen.</description>
      <content:encoded><![CDATA[<p>Laravel-sovelluksen voi ajaa kahdella Laravelin omalla tavalla: <a href="https://laravel.com/cloud">Laravel Cloudissa</a>, joka on täysin hallinnoitu alusta, tai omalla palvelimella, jota hallitaan <a href="https://laravel.com/forge">Laravel Forgella</a>. Suosittelen nykyään useimpiin uusiin sovelluksiin Laravel Cloudia, koska palvelimen ylläpito jää kokonaan pois. Forge on edelleen hyvä valinta, kun tarvitaan täyttä hallintaa palvelimesta, sovellus pyörii jatkuvasti täydellä kuormalla tai data pitää sijoittaa tiettyyn maahan.</p>
<h2 id="mika-ero-laravel-cloudilla-ja-forgella-on">Mikä ero Laravel Cloudilla ja Forgella on?</h2>
<p>Ero on siinä, kuka omistaa palvelimen ja vastaa siitä.</p>
<ul>
<li><strong>Laravel Cloud</strong> on alusta, jossa et näe palvelinta lainkaan. Yhdistät koodivaraston, valitset alueen ja resurssit ja Cloud hoitaa ajoympäristön, skaalauksen, tietokannat, jonot ja SSL-varmenteet. Taustalla on Amazonin AWS.</li>
<li><strong>Forge</strong> on hallintatyökalu omalle palvelimelle. Palvelin vuokrataan esimerkiksi DigitalOceanilta, Hetzneriltä tai AWS:ltä ja Forge asentaa ja konfiguroi sen, hoitaa julkaisut ja SSL-varmenteet. Palvelin on silti sinun ja käyttöjärjestelmän päivitykset, levytila ja valvonta ovat sinun vastuullasi.</li>
</ul>
<h2 id="milloin-laravel-cloud-kannattaa">Milloin Laravel Cloud kannattaa?</h2>
<p><strong>Kun et halua ylläpitää palvelinta.</strong> Tämä on Cloudin suurin etu. Käyttöjärjestelmän päivityksiä, PHP-version vaihtoa tai levyn täyttymistä ei tarvitse seurata.</p>
<p><strong>Kun kuorma vaihtelee.</strong> Cloud skaalautuu kuorman mukaan ja pienet sovellukset voivat mennä lepotilaan, kun käyttäjiä ei ole. Silloin laskutetaan vain siitä ajasta, kun sovellus on käytössä. Tämä sopii hyvin esimerkiksi sisäisiin työkaluihin, joita käytetään vain virka-aikaan.</p>
<p><strong>Kun tarvitaan esikatseluympäristöjä.</strong> Cloud voi luoda jokaiselle kehityshaaralle oman ympäristön, jossa muutoksen voi testata ennen julkaisua.</p>
<p><strong>Kun tietokanta saa olla hallinnoitu.</strong> Cloudissa on valmiina MySQL ja serverless-PostgreSQL, välimuisti ja jonot. Niitä ei tarvitse asentaa tai varmuuskopioida itse.</p>
<h2 id="milloin-oma-palvelin-forgella-on-parempi">Milloin oma palvelin Forgella on parempi?</h2>
<p><strong>Kun tarvitaan täyttä hallintaa.</strong> Omalle palvelimelle voi asentaa mitä tahansa: erikoisia PHP-laajennuksia, omia taustapalveluita tai muita kuin Laravel-sovelluksia samalle koneelle.</p>
<p><strong>Kun data pitää sijaita tietyssä maassa.</strong> Laravel Cloudin lähimmät alueet ovat Frankfurtissa, Irlannissa ja Lontoossa. Jos asiakkaan vaatimus on, että data pysyy Suomessa, palvelin voidaan vuokrata esimerkiksi Hetznerin Helsingin konesalista ja hallita sitä Forgella.</p>
<p><strong>Kun kuorma on tasainen ja suuri.</strong> Jos sovellus on jatkuvasti täydessä käytössä, kiinteähintainen oma palvelin voi tulla edullisemmaksi kuin käyttöön perustuva laskutus. Tämä kannattaa laskea tapauskohtaisesti.</p>
<p><strong>Kun samalla palvelimella on monta pientä sivustoa.</strong> Forgella yhdelle palvelimelle voi sijoittaa useita sovelluksia ja kustannus jakautuu niiden kesken.</p>
<h2 id="miten-hinnoittelu-eroaa">Miten hinnoittelu eroaa?</h2>
<p>Laravel Cloudissa maksetaan kuukausimaksu ja sen päälle käytöstä: laskentatehosta, tietokannasta, tallennustilasta ja tiedonsiirrosta. Kuukausikulutukselle voi asettaa ylärajan, jolloin lasku ei voi yllättää. Forgessa maksetaan kiinteä kuukausimaksu Forgelle ja erikseen palvelimen vuokra palveluntarjoajalle.</p>
<p>Hinnat muuttuvat, joten tarkista ajantasaiset hinnat <a href="https://laravel.com/cloud/pricing">Laravel Cloudin</a> ja <a href="https://laravel.com/forge/pricing">Forgen</a> sivuilta. Pienelle sovellukselle, joka on suurimman osan ajasta lepotilassa, Cloud on yleensä halvempi. Jatkuvasti kuormitetulle sovellukselle oma palvelin voi olla edullisempi, mutta siihen pitää lisätä oma ylläpitotyö.</p>
<h2 id="mita-siirto-cloudiin-vaatii-kaytannossa">Mitä siirto Cloudiin vaatii käytännössä?</h2>
<p>Jos sovellus siirretään omalta palvelimelta Laravel Cloudiin, käyn läpi ainakin nämä:</p>
<ul>
<li><strong>Tiedostot.</strong> Käyttäjien lataamat tiedostot eivät voi olla palvelimen levyllä, koska Cloudin palvelimet vaihtuvat. Ne siirretään objektitallennukseen.</li>
<li><strong>Ajastetut tehtävät ja jonot.</strong> Ne määritellään Cloudin asetuksissa palvelimen cron-ajojen sijaan.</li>
<li><strong>Tietokanta.</strong> Tietokanta siirretään hallinnoituun tietokantaan ja samalla tarkistetaan, toimiiko sovellus myös PostgreSQL:llä, jos vaihdetaan MySQL:stä.</li>
<li><strong>Palvelimelle asennetut lisät.</strong> Jos sovellus käyttää jotain palvelimelle erikseen asennettua ohjelmaa, sille pitää löytää korvaaja.</li>
</ul>
<h2 id="mita-mina-valitsen">Mitä minä valitsen?</h2>
<p>Uudessa projektissa lähtöoletukseni on Laravel Cloud. Säästetty ylläpitotyö on yleensä arvokkaampaa kuin mahdollinen ero kuukausilaskussa. Valitsen Forgen, kun jokin yllä mainituista syistä painaa: datan sijainti, erikoisvaatimukset tai tasainen suuri kuorma.</p>
<p>Vanhaa sovellusta ei kannata siirtää vain siirtämisen vuoksi. Jos oma palvelin toimii ja sitä ylläpidetään, siirto Cloudiin kannattaa yleensä vasta, kun palvelin pitäisi muutenkin uusia.</p>
<p>Molemmissa vaihtoehdoissa autan valinnassa, käyttöönotossa ja ylläpidossa. Lisää <a href="/palvelut/laravel-palvelimet">Laravel- ja palvelinpalveluista</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="voiko-sovelluksen-siirtaa-forgesta-laravel-cloudiin-myohemmin">Voiko sovelluksen siirtää Forgesta Laravel Cloudiin myöhemmin?</h3>
<p>Voi. Laravel-sovellus toimii molemmissa samalla koodilla. Siirrossa pitää huomioida tietokannan, tiedostojen ja ympäristömuuttujien siirto sekä se, käyttääkö sovellus jotain palvelimelle erikseen asennettua, jota Cloudissa ei ole.</p>
<h3 id="onko-laravel-cloud-serverless-palvelu">Onko Laravel Cloud serverless-palvelu?</h3>
<p>Ei samalla tavalla kuin esimerkiksi Laravel Vapor. Cloud ajaa sovellusta tavallisilla palvelimilla, jotka se hallitsee puolestasi ja skaalaa kuorman mukaan. Pienet sovellukset voivat kuitenkin mennä lepotilaan ja herätä seuraavasta pyynnöstä.</p>
<h3 id="toimiiko-wordpress-laravel-cloudissa">Toimiiko WordPress Laravel Cloudissa?</h3>
<p>Laravel Cloud on tehty Laravel- ja Symfony-sovelluksille, ei WordPressille. WordPress-sivustoille suosittelen WordPressiin erikoistunutta hallinnoitua hostingia, kuten <a href="https://seravo.com/fi/">Seravoa</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Chatbot vai tekoälyagentti, valmis palvelu vai itse rakennettu?</title>
      <link>https://peltopiri.com/blogi/chatbot-vai-tekoalyagentti</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/chatbot-vai-tekoalyagentti</guid>
      <pubDate>Tue, 09 Jun 2026 06:00:00 GMT</pubDate>
      <description>Mikä ero on chatbotilla ja tekoälyagentilla, milloin valmis palvelu riittää ja mitä itse rakennettu vaatii: RAG, pgvector ja WordPress-synkronointi.</description>
      <content:encoded><![CDATA[<p>Chatbot vastaa kysymyksiin, tekoälyagentti hoitaa tehtäviä. Useimmille yrityksille paras ensimmäinen askel on chatbot, joka vastaa oikein yrityksen omien tietojen perusteella. Agentti tarvitaan, kun botin pitää myös tehdä jotain, kuten tarkistaa tilauksen tila tai varata aika. Valmis palvelu riittää usein yksinkertaiseen käyttöön. Kun botin pitää tuntea verkkokaupan tuotteet, varastosaldot ja hinnat ajantasaisesti, tarvitaan itse rakennettu ratkaisu ja siinä on enemmän osia kuin moni odottaa.</p>
<h2 id="mika-ero-on-chatbotilla-ja-tekoalyagentilla">Mikä ero on chatbotilla ja tekoälyagentilla?</h2>
<p><strong>Chatbot</strong> keskustelee. Hyvä chatbot hakee vastauksen yrityksen omasta aineistosta, kuten sivustolta, ohjeista ja tuotetiedoista. Se myös kertoo, mistä tieto on peräisin.</p>
<p><strong>Tekoälyagentti</strong> käyttää lisäksi työkaluja. Se voi hakea tietoa järjestelmistä, esimerkiksi tilauksen tilan WooCommercesta. Se voi myös tehdä toimenpiteitä, kuten luoda tukipyynnön. Siksi agentin oikeudet pitää rajata tarkasti ja tärkeät toimenpiteet jätetään ihmisen hyväksyttäviksi.</p>
<h2 id="riittaako-valmis-palvelu">Riittääkö valmis palvelu?</h2>
<p>Valmiissa chatbot-palveluissa annetaan sivuston osoite tai ladataan dokumentteja ja botti on käytössä samana päivänä. Ne sopivat, kun:</p>
<ul>
<li>sisältö muuttuu harvoin, esimerkiksi ohjeet ja usein kysytyt kysymykset</li>
<li>botin ei tarvitse tietää mitään asiakaskohtaista</li>
<li>riittää, että vastaukset ovat suurin piirtein oikein.</li>
</ul>
<p>Ongelmat alkavat verkkokaupassa. Hinta, varastosaldo ja tuotevalikoima muuttuvat päivittäin ja valmis palvelu lukee sivuston uudelleen omassa tahdissaan. Silloin botti voi kertoa, että tuotetta on varastossa, vaikka se loppui eilen.</p>
<h2 id="miksi-quot-rakenna-mulle-chatbot-quot-ei-riita">Miksi &quot;rakenna mulle chatbot&quot; ei riitä?</h2>
<p>Tekoälyltä voi pyytää chatbotin ja se tekee toimivan näköisen version nopeasti. Pyynnöstä jää kuitenkin puuttumaan kaikki se, mikä tekee botista luotettavan: mistä tieto tulee, miten se pysyy ajan tasalla, mitä botti saa tehdä ja miten virheet huomataan. Tuotantokelpoinen botti on enemmän tiedonhallintaa kuin keskustelua.</p>
<h2 id="mita-itse-rakennettu-chatbot-vaatii">Mitä itse rakennettu chatbot vaatii?</h2>
<h3 id="rag-eli-haku-ennen-vastausta">RAG eli haku ennen vastausta</h3>
<p>Kielimalli ei tunne yrityksesi tuotteita. RAG-mallissa (retrieval-augmented generation) jokaisen kysymyksen kohdalla haetaan ensin sopivat tekstinpätkät omasta aineistosta ja annetaan ne mallille vastauksen pohjaksi. Ratkaisun laatu riippuu lähes kokonaan tästä hausta.</p>
<h3 id="aineiston-pilkkominen-ja-vektorit">Aineiston pilkkominen ja vektorit</h3>
<p>Sisältö pilkotaan sopivan kokoisiksi paloiksi ja jokaisesta lasketaan vektori eli numeerinen esitys sen merkityksestä. Kysymykselle lasketaan samanlainen vektori ja haku etsii merkitykseltään lähimmät palat. Palojen rajat vaikuttavat vastausten laatuun: jos tuotteen nimi ja hinta päätyvät eri paloihin, botti voi yhdistää väärät tiedot.</p>
<h3 id="postgresql-ja-pgvector">PostgreSQL ja pgvector</h3>
<p>Vektorit tallennetaan tietokantaan. Erillistä vektoritietokantaa ei yleensä tarvita: <a href="https://github.com/pgvector/pgvector">pgvector</a> on PostgreSQL-laajennus, joka tallentaa vektorit tavallisen tiedon rinnalle ja tukee nopeita hakuindeksejä. Siitä on kaksi isoa etua:</p>
<ul>
<li>Vektorihaun voi yhdistää tavalliseen suodatukseen samassa kyselyssä, esimerkiksi &quot;vain varastossa olevat tuotteet, suomenkieliset tekstit, hinta alle 100 euroa&quot;.</li>
<li>Vektorihaun voi yhdistää perinteiseen tekstihakuun. Tuotekoodit ja mallinimet löytyvät tekstihaulla paremmin kuin merkityksen perusteella.</li>
</ul>
<h3 id="synkronointi-wordpressista-ja-woocommercesta">Synkronointi WordPressistä ja WooCommercesta</h3>
<p>Tieto pitää saada tietokantaan ja pitää se ajan tasalla. Teen tähän yleensä oman WordPress-lisäosan, joka:</p>
<ul>
<li>avaa rajapinnan, joka palauttaa sisällön ja tuotteet botille sopivassa muodossa. Pohjana on <a href="https://developer.wordpress.org/rest-api/">WordPressin REST API</a> ja vain tarvittavat kentät palautetaan.</li>
<li>ilmoittaa muutoksista heti. Kun tuote tai sivu tallennetaan tai poistetaan, lisäosa lähettää tiedon botin taustapalveluun, joka päivittää vektorit. Poistot ovat tärkeitä: poistetusta tuotteesta ei saa enää vastata.</li>
<li>huomioi monikielisyyden ja näkyvyyden. Luonnoksia, salasanasuojattuja sivuja tai piilotettuja tuotteita ei viedä botille.</li>
</ul>
<p>Varastosaldot ja hinnat kannattaa usein hakea suoraan <a href="https://woocommerce.github.io/woocommerce-rest-api-docs/">WooCommercen rajapinnasta</a> vastaushetkellä eikä tallentaa vektoreihin, koska ne muuttuvat jatkuvasti.</p>
<h3 id="agentin-tyokalut-ja-oikeudet">Agentin työkalut ja oikeudet</h3>
<p>Kun botti saa työkaluja, jokainen työkalu on oma rajapintansa, jolla on tarkat oikeudet. Tilauksen tilan saa tarkistaa vain tunnistettu käyttäjä ja vain omasta tilauksestaan. Agentti ei saa käyttää ylläpitäjän tunnuksia.</p>
<h3 id="tietoturva-ja-kehoteinjektiot">Tietoturva ja kehoteinjektiot</h3>
<p>Tekoälysovellusten yleisin uhka on kehoteinjektio, joka on <a href="https://genai.owasp.org/llm-top-10/">OWASP:n LLM-riskilistan</a> kärjessä. Siinä käyttäjä tai jokin aineistoon päätynyt teksti yrittää saada mallin toimimaan ohjeiden vastaisesti. Siksi agentin oikeudet rajataan niin, ettei se voi tehdä mitään vahingollista, vaikka injektio onnistuisi.</p>
<h3 id="lokit-arviointi-ja-kustannukset">Lokit, arviointi ja kustannukset</h3>
<p>Jokainen kysymys, haetut lähteet ja vastaus kirjataan lokiin. Lisäksi tehdään testikysymysten sarja, jolla tarkistetaan, ettei botti huonone, kun aineisto tai malli vaihtuu. Kustannukset muodostuvat kielimallin käytöstä, vektorien laskennasta ja palvelimesta. Ne kannattaa arvioida etukäteen todellisella kysymysmäärällä.</p>
<h3 id="tietosuoja">Tietosuoja</h3>
<p>Selvitä, mihin maahan ja kenelle data lähtee, onko palveluntarjoajan kanssa tietojenkäsittelysopimus ja käytetäänkö keskusteluja mallien koulutukseen. Asiakastietoja ei viedä vektoreihin ollenkaan, vaan ne haetaan tarvittaessa rajapinnasta käyttäjän luvalla.</p>
<h2 id="kumpi-kannattaa-valita">Kumpi kannattaa valita?</h2>
<ul>
<li><strong>Valmis palvelu</strong>, jos haluat kokeilla nopeasti, sisältö on pääosin pysyvää eikä botin tarvitse tehdä mitään.</li>
<li><strong>Itse rakennettu chatbot</strong>, jos botin pitää tuntea verkkokaupan ajantasaiset tiedot, toimia usealla kielellä tai yhdistyä muihin järjestelmiin.</li>
<li><strong>Agentti</strong>, kun botin pitää hoitaa tehtäviä. Aloita yhdellä selkeällä tehtävällä ja laajenna vasta, kun se toimii.</li>
</ul>
<p>Autan valinnassa ja rakennan ratkaisun. Lue lisää <a href="/palvelut/tekoalyagentit">tekoälyagenteista</a> ja <a href="/palvelut/integraatiot">integraatioista</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="tarvitaanko-erillinen-vektoritietokanta">Tarvitaanko erillinen vektoritietokanta?</h3>
<p>Yleensä ei. PostgreSQL ja pgvector riittävät useimpiin yritysten tarpeisiin ja tiedot pysyvät samassa tietokannassa muun sovelluksen kanssa. Erillinen vektoritietokanta voi olla perusteltu, kun aineistoa on hyvin paljon.</p>
<h3 id="voiko-botti-vastata-vaarin">Voiko botti vastata väärin?</h3>
<p>Voi. Siksi botti näyttää lähteet, jolloin käyttäjä voi tarkistaa ne. Lisäksi botti ohjeistetaan kertomaan, kun vastausta ei löydy aineistosta. Testikysymyksillä seurataan, kuinka usein virheitä tulee.</p>
<h3 id="toimiiko-tama-wordpress-sivustolla-ilman-verkkokauppaa">Toimiiko tämä WordPress-sivustolla ilman verkkokauppaa?</h3>
<p>Toimii. Synkronointi toimii samalla tavalla sivuille, artikkeleille ja omille sisältötyypeille, esimerkiksi ACF:llä tehdyille kentille.</p>
]]></content:encoded>
    </item>
    <item>
      <title>GSAP on nyt ilmainen kaikille – ja muut kirjastot sivuston animaatioihin</title>
      <link>https://peltopiri.com/blogi/gsap-ja-animaatiokirjastot</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/gsap-ja-animaatiokirjastot</guid>
      <pubDate>Tue, 19 May 2026 06:00:00 GMT</pubDate>
      <description>GSAP lisäosineen on ilmainen myös kaupalliseen käyttöön. Esittelen sen ja muita animaatio- ja WebGL-kirjastoja pienillä esimerkeillä.</description>
      <content:encoded><![CDATA[<p><a href="https://gsap.com/">GSAP</a> on yksi käytetyimmistä JavaScript-animaatiokirjastoista ja se on ollut huhtikuun 2025 lopusta lähtien täysin ilmainen myös kaupalliseen käyttöön. Muutos tuli Webflow&#39;n ansiosta: Webflow osti GSAP:n syksyllä 2024 ja versiossa 3.13 <a href="https://gsap.com/blog/3-13/">kaikki aiemmin maksulliset lisäosat</a>, kuten SplitText ja MorphSVG, avattiin kaikille. Käytän GSAP:ia esimerkiksi Fyran sivustolla. Tässä artikkelissa näytän, mitä sillä voi tehdä. Esittelen myös muita kirjastoja, joilla sivustoon saa liikettä tai kolmiulotteisuutta.</p>
<h2 id="mita-gsap-n-maksuttomuus-tarkoittaa-kaytannossa">Mitä GSAP:n maksuttomuus tarkoittaa käytännössä?</h2>
<p>Ennen moni hienoimmista ominaisuuksista oli maksullisen Club GSAP -jäsenyyden takana. Nyt kaikki on samassa <code>gsap</code>-paketissa, eikä erillistä lisenssiä tarvita asiakasprojekteihin. Esimerkiksi tekstin pilkkominen sanoiksi tai kirjaimiksi animaatiota varten (SplitText) ja SVG-muotojen muuntaminen toisiksi (MorphSVG) ovat nyt ilmaisia. GSAP:n mukaan SplitText kirjoitettiin samalla uusiksi ja se huomioi nyt myös ruudunlukijat.</p>
<h2 id="pieni-esimerkki-kortit-liukuvat-esiin-vieritettaessa">Pieni esimerkki: kortit liukuvat esiin vieritettäessä</h2>
<p>ScrollTrigger-lisäosalla animaatio käynnistyy, kun elementti tulee näkyviin:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-js">gsap.registerPlugin(ScrollTrigger);

gsap.from(&quot;.kortti&quot;, {
  y: 40,
  opacity: 0,
  stagger: 0.15, // kortit tulevat yksi kerrallaan
  scrollTrigger: { trigger: &quot;.kortit&quot;, start: &quot;top 80%&quot; },
});
</code></pre>
<p>Ja otsikko, jonka sanat nousevat paikoilleen:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-js">const split = SplitText.create(&quot;h1&quot;, { type: &quot;words&quot; });
gsap.from(split.words, { y: 20, opacity: 0, stagger: 0.05 });
</code></pre>
<h2 id="kokeile-teksti-joka-animoituu-vieritettaessa">Kokeile: teksti, joka animoituu vieritettäessä</h2>
<p>Alla oleva teksti on sidottu sivun vieritykseen ScrollTriggerin <code>scrub</code>-asetuksella. Kirjaimet animoituvat esiin sitä mukaa kuin vierität ja punainen alleviivaus ja alareunan palkki seuraavat perässä. Vieritä takaisin ylös, niin animaatio kelautuu taaksepäin.</p>
<figure class="demo">
<div class="scroll-demo">
<p class="scroll-demo__kicker">GSAP + ScrollTrigger + SplitText</p>
<p class="scroll-demo__text"><span class="visually-hidden">Hyvä animaatio ohjaa katsetta, näyttää järjestyksen ja pysähtyy, kun asia on sanottu.</span><span class="scroll-demo__split" aria-hidden="true">Hyvä animaatio ohjaa katsetta, näyttää järjestyksen ja <span class="scroll-demo__mark">pysähtyy</span>, kun asia on sanottu.</span></p>
<span class="scroll-demo__bar" aria-hidden="true"></span>
</div>
<figcaption>Jos laitteessasi on valittu vähennetty liike, teksti näkyy valmiina ilman animaatiota.</figcaption>
</figure>
<script type="module" src="/demot/gsap-teksti.js"></script>

<p>Koodia tarvitaan vähän. Animaatio ajetaan vain, jos käyttäjä ei ole pyytänyt vähennettyä liikettä:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-js">gsap.matchMedia().add(&quot;(prefers-reduced-motion: no-preference)&quot;, () =&gt; {
  const split = SplitText.create(&quot;.teksti&quot;, { type: &quot;words, chars&quot; });

  gsap.timeline({
    scrollTrigger: { trigger: &quot;.demo&quot;, start: &quot;top 75%&quot;, end: &quot;bottom 35%&quot;, scrub: 0.6 },
  })
    .from(split.chars, { opacity: 0.15, yPercent: 30, stagger: 0.02 })
    .from(&quot;.korostus&quot;, { backgroundSize: &quot;0% 0.12em&quot; });

  return () =&gt; split.revert(); // palauttaa alkuperäisen tekstin
});
</code></pre>
<h2 id="muut-kirjastot-ja-mihin-ne-sopivat">Muut kirjastot ja mihin ne sopivat</h2>
<p><strong><a href="https://motion.dev/">Motion</a></strong> on Framer Motionin seuraaja. Se toimii Reactin lisäksi tavallisella JavaScriptillä ja on avointa lähdekoodia (MIT-lisenssi). Se sopii hyvin käyttöliittymän pieniin liikkeisiin, kuten painikkeen palautteeseen:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-js">import { animate } from &quot;motion&quot;;
animate(&quot;.nappi&quot;, { scale: [1, 1.06, 1] }, { duration: 0.4 });
</code></pre>
<p><strong><a href="https://animejs.com/">anime.js</a></strong> on kevyt yleiskirjasto, jonka versio 4 toi muun muassa jousifysiikan. Se on hyvä valinta, kun GSAP tuntuu liian raskaalta pieneen tarpeeseen.</p>
<p><strong><a href="https://threejs.org/">three.js</a></strong> on tunnetuin kirjasto 3D-grafiikkaan selaimessa. Pyörivä kuutio vaatii vain muutaman rivin:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-js">import * as THREE from &quot;three&quot;;

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, innerWidth / innerHeight, 0.1, 100);
camera.position.z = 3;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.append(renderer.domElement);

const cube = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshNormalMaterial());
scene.add(cube);
renderer.setAnimationLoop(() =&gt; {
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.015;
  renderer.render(scene, camera);
});
</code></pre>
<p>Oikeassa projektissa kuution tilalla on esimerkiksi tuotteen 3D-malli tai vaikkapa asunnon pohjakuva, jota kävijä voi pyörittää. Alla on sellainen: seinät ja lattiat ovat three.js:n peruslaatikoita, kamera liikkuu OrbitControlsilla ja klikattu huone tunnistetaan Raycasterilla, joka laskee, mihin 3D-objektiin osoitin osuu.</p>
<figure class="demo">
<div class="floorplan" data-floorplan>
<ul class="floorplan__ui" aria-label="Pohjakuvan huoneet" hidden></ul>
<div class="floorplan__scene"></div>
<section class="floorplan__info" aria-label="Valitun huoneen tiedot" aria-live="polite" hidden>
<div class="floorplan__head"><p class="floorplan__title"></p><button class="floorplan__close" type="button" aria-label="Sulje huoneen tiedot">✕</button></div>
<dl><div><dt>Pinta-ala</dt><dd class="floorplan__area"></dd></div><div><dt>Lattia</dt><dd class="floorplan__material"></dd></div></dl>
<p class="floorplan__desc"></p>
</section>
<p class="floorplan__fallback" hidden>3D-demo ei toimi tässä selaimessa, koska se tarvitsee WebGL:n.</p>
<noscript><p class="floorplan__fallback">3D-demo tarvitsee JavaScriptin.</p></noscript>
</div>
<figcaption>Pyöritä pohjakuvaa vetämällä ja valitse huone klikkaamalla tai napeista. three.js ladataan vasta, kun demo tulee näkyviin.</figcaption>
</figure>
<script type="module" src="/demot/pohjakuva.js"></script>

<p><strong><a href="https://github.com/tweenjs/tween.js">tween.js</a></strong> on pieni kirjasto arvojen pehmeään muuttamiseen. Sitä käytetään usein three.js:n kanssa, esimerkiksi kameran liu&#39;uttamiseen kohteesta toiseen.</p>
<p><strong><a href="https://airbnb.io/lottie/">Lottie</a></strong> toistaa After Effectsillä tehtyjä animaatioita kevyinä JSON-tiedostoina. Se sopii ikoneihin ja kuvituksiin, jotka suunnittelija tekee valmiiksi.</p>
<p><strong><a href="https://rive.app/">Rive</a></strong> on Lottien kaltainen, mutta sen animaatiot voivat reagoida käyttäjään tilakoneiden avulla. Se sopii esimerkiksi interaktiivisiin hahmoihin ja painikkeisiin.</p>
<p><strong><a href="https://github.com/darkroomengineering/lenis">Lenis</a></strong> pehmentää sivun vierityksen. Se on suosittu näyttävillä markkinointisivuilla, mutta sitä kannattaa käyttää harkiten, koska se muuttaa selaimen omaa vierityskäytöstä.</p>
<h2 id="joskus-kirjastoa-ei-tarvita-ollenkaan">Joskus kirjastoa ei tarvita ollenkaan</h2>
<p>Selaimet osaavat yhä enemmän itse. CSS:n vieritykseen sidotuilla animaatioilla tehdään esimerkiksi lukemisen edistymispalkki ilman JavaScriptiä:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-css">.lukupalkki {
  position: fixed; top: 0; left: 0; width: 100%; height: 4px;
  background: #d43a2e; transform-origin: 0 50%;
  animation: kasva linear;
  animation-timeline: scroll();
}
@keyframes kasva { from { transform: scaleX(0); } to { transform: scaleX(1); } }
</code></pre>
<p>Tuki ei ole vielä kaikissa selaimissa, erityisesti Firefoxissa, joten tarkista tilanne <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline">MDN:stä</a> ja tee niin, että sivu toimii ilmankin. Toinen hyödyllinen selaimen oma ominaisuus on <a href="https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API">View Transitions API</a>, jolla sivujen tai näkymien vaihtumiseen saa pehmeän siirtymän.</p>
<h2 id="muista-saavutettavuus">Muista saavutettavuus</h2>
<p>Liike voi aiheuttaa joillekin pahoinvointia tai vaikeuttaa keskittymistä. Siksi:</p>
<ul>
<li><strong>Kunnioita käyttäjän asetusta.</strong> Kun käyttöjärjestelmässä on valittu vähennetty liike, animaatiot pitää jättää pois tai tehdä hyvin hillityiksi. GSAP:ssa tähän sopii <code>gsap.matchMedia()</code>, CSS:ssä <code>@media (prefers-reduced-motion: reduce)</code>.</li>
<li><strong>Anna mahdollisuus pysäyttää.</strong> Jos liike jatkuu yli viiden sekunnin ajan, sen pitää voida pysäyttää.</li>
<li><strong>Älä piilota sisältöä animaation taakse.</strong> Jos animaatio ei käynnisty, sisällön pitää silti näkyä.</li>
</ul>
<p>Tarkistan nämä asiat <a href="/palvelut/seo-geo-saavutettavuusauditit">saavutettavuusauditissa</a> yhdessä muiden WCAG-vaatimusten kanssa.</p>
<h2 id="mika-kirjasto-kannattaa-valita">Mikä kirjasto kannattaa valita?</h2>
<ul>
<li><strong>GSAP</strong>, kun animaatioita on paljon, ne on sidottu vieritykseen tai ajoitus on tärkeää.</li>
<li><strong>Motion tai anime.js</strong> käyttöliittymän pieniin liikkeisiin.</li>
<li><strong>three.js</strong> 3D:hen ja WebGL-efekteihin.</li>
<li><strong>Lottie tai Rive</strong>, kun suunnittelija tekee animaation valmiiksi.</li>
<li><strong>Pelkkä CSS</strong>, kun se riittää. Se on aina kevyin vaihtoehto.</li>
</ul>
<p>Animaatiot kuuluvat räätälöityihin <a href="/palvelut/wordpress-woocommerce">WordPress-toteutuksiini</a>, mutta ne toimivat millä tahansa alustalla, myös <a href="/blogi/webflow-vai-wordpress">Webflow&#39;ssa</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="onko-gsap-ilmainen-myos-asiakasprojekteissa">Onko GSAP ilmainen myös asiakasprojekteissa?</h3>
<p>Kyllä. GSAP:n mukaan koko kirjasto lisäosineen on ilmainen, myös kaupallisessa käytössä. Tarkista ajantasaiset lisenssiehdot GSAP:n sivuilta ennen käyttöä.</p>
<h3 id="hidastavatko-animaatiot-sivustoa">Hidastavatko animaatiot sivustoa?</h3>
<p>Huonosti tehtynä kyllä. Animoi ensisijaisesti ominaisuuksia <code>transform</code> ja <code>opacity</code>, joita selain pystyy käsittelemään kevyesti. Lataa raskaat kirjastot, kuten three.js, vain sivuille, joilla niitä tarvitaan.</p>
<h3 id="toimiiko-gsap-wordpressissa">Toimiiko GSAP WordPressissä?</h3>
<p>Toimii. Sen voi ladata teeman skripteihin tai lisätä animaatiot omiin lohkoihin, jolloin sisällön päivittäjä voi käyttää niitä ilman koodia.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Webflow vai WordPress? Vertailu yrityksen sivustoon</title>
      <link>https://peltopiri.com/blogi/webflow-vai-wordpress</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/webflow-vai-wordpress</guid>
      <pubDate>Tue, 28 Apr 2026 06:00:00 GMT</pubDate>
      <description>Webflow on visuaalinen sivustotyökalu hostingeineen, WordPress avoin alusta. Vertailen, kumpi sopii millaiseenkin yrityksen sivustoon.</description>
      <content:encoded><![CDATA[<p>Webflow sopii hyvin visuaalisesti näyttäviin markkinointisivustoihin, joita suunnittelija haluaa rakentaa ja muokata itse ilman koodia. WordPress on parempi valinta, kun sivustolla on paljon sisältöä, verkkokauppa, useita kieliä tai yhteyksiä muihin järjestelmiin, tai kun haluat omistaa sivustosi ja voida siirtää sen minne tahansa. Teen itse pääasiassa WordPress-sivustoja, mutta kerron tässä rehellisesti, missä Webflow on vahvempi.</p>
<h2 id="mika-webflow-on">Mikä Webflow on?</h2>
<p><a href="https://webflow.com/">Webflow</a> on selaimessa toimiva visuaalinen työkalu, jossa sivusto suunnitellaan ja rakennetaan samassa paikassa. Hosting, varmuuskopiot ja päivitykset sisältyvät palveluun. Webflow tuottaa siistiä HTML- ja CSS-koodia ja sen käyttöliittymä on lähellä CSS:n omaa logiikkaa, joten se sopii suunnittelijalle, joka ymmärtää verkkosivujen rakennetta.</p>
<h2 id="missa-webflow-on-vahvempi">Missä Webflow on vahvempi?</h2>
<ul>
<li><strong>Visuaalinen suunnittelu.</strong> Suunnittelija voi toteuttaa sivun tarkasti ilman kehittäjää. Animaatiot ja vuorovaikutus tehdään samassa työkalussa.</li>
<li><strong>Ei ylläpitoa.</strong> Lisäosia, teemoja tai palvelinta ei tarvitse päivittää. Tietoturvasta huolehtii Webflow.</li>
<li><strong>Nopea alku.</strong> Pieni markkinointisivusto voi olla valmis nopeammin, kun sama ihminen suunnittelee ja toteuttaa.</li>
</ul>
<h2 id="missa-wordpress-on-vahvempi">Missä WordPress on vahvempi?</h2>
<ul>
<li><strong>Omistajuus ja siirrettävyys.</strong> WordPress on avointa lähdekoodia. Sivuston voi siirtää mihin tahansa hostingiin ja kaikki sisältö ja koodi ovat sinun. Webflow&#39;ssa sivusto on Webflow&#39;n palvelussa. Koodin voi viedä ulos, mutta <a href="https://www.lowcode.agency/blog/webflow-limitations">viennistä puuttuvat</a> dynaamiset osat, kuten CMS-sisältö ja lomakkeet.</li>
<li><strong>Sisällön määrä ja rakenne.</strong> Webflow&#39;n CMS:ssä on suunnitelmakohtaiset rajat kokoelmien, kenttien ja sisältöjen määrälle. WordPressissä vastaavia rajoja ei ole ja omat sisältötyypit ja kentät, esimerkiksi <a href="/palvelut/wordpress-woocommerce">ACF:llä</a>, voi rakentaa vapaasti.</li>
<li><strong>Verkkokauppa.</strong> WooCommerce on kattava verkkokauppa, johon saa suomalaiset maksutavat, kuljetusyhtiöt ja yhteydet kirjanpitoon tai toiminnanohjaukseen. Webflow&#39;n verkkokauppa sopii suppeampaan käyttöön.</li>
<li><strong>Monikielisyys.</strong> WordPressissä monikielisyys hoituu esimerkiksi Polylangilla. Webflow&#39;ssa se on lisäpalvelu, jolla on omia rajoituksiaan.</li>
<li><strong>Integraatiot.</strong> WordPressiin voi tehdä oman lisäosan, joka avaa rajapinnan tai yhdistää sivuston muihin järjestelmiin. Webflow&#39;ssa integraatiot tehdään sen rajapinnan kautta, jolla on suunnitelmakohtaiset rajat.</li>
<li><strong>Kustannukset pitkällä aikavälillä.</strong> WordPressin hosting ja ylläpito maksavat, mutta hinnoittelu ei riipu sivujen tai muokkaajien määrästä samalla tavalla kuin Webflow&#39;ssa.</li>
</ul>
<h2 id="miten-hinnoittelu-eroaa">Miten hinnoittelu eroaa?</h2>
<p>Webflow&#39;ssa maksetaan kahdesta asiasta: sivustokohtaisesta suunnitelmasta, joka määrää muun muassa CMS:n rajat ja liikennemäärät, sekä työtilan paikoista niille, jotka rakentavat ja muokkaavat sivustoa. Monikielisyys ja verkkokauppa ovat omia lisäpalveluitaan tai suunnitelmiaan. Hinnat muuttuvat, joten tarkista ajantasaiset tiedot <a href="https://webflow.com/pricing">Webflow&#39;n sivuilta</a>.</p>
<p>WordPressissä maksetaan hostingista, mahdollisista maksullisista lisäosista ja ylläpidosta. Muokkaajien tai sivujen määrä ei vaikuta hintaan. Kokonaiskustannuksia kannattaa verrata viiden vuoden ajalle, ei ensimmäisen kuukauden laskulle.</p>
<h2 id="enta-tietoturva">Entä tietoturva?</h2>
<p>Webflow&#39;n etu on, ettei hyökkäyspintaa ole juuri lainkaan, koska lisäosia ei ole. WordPressin tietoturva riippuu ylläpidosta: päivitetyt lisäosat, hyvä hosting ja varmuuskopiot. Hallinnoitu WordPress-hosting, kuten <a href="https://seravo.com/fi/">Seravo</a>, hoitaa ison osan tästä. Huolimattomasti ylläpidetty WordPress on riski, hyvin ylläpidetty ei ole.</p>
<h2 id="kumpi-kannattaa-valita">Kumpi kannattaa valita?</h2>
<p><strong>Valitse Webflow, jos:</strong></p>
<ul>
<li>sivusto on pääasiassa markkinointisivusto, jossa on vähän sisältöä</li>
<li>suunnittelija haluaa toteuttaa ja muokata sitä itse</li>
<li>et halua huolehtia ylläpidosta.</li>
</ul>
<p><strong>Valitse WordPress, jos:</strong></p>
<ul>
<li>sivustolla on paljon sisältöä tai omia sisältötyyppejä</li>
<li>tarvitset verkkokaupan, useita kieliä tai integraatioita</li>
<li>haluat omistaa sivustosi ja pystyä vaihtamaan hostingia tai kehittäjää vapaasti.</li>
</ul>
<p>Usein valinta ratkeaa sen mukaan, kuka sivustoa päivittää ja mihin se on menossa viiden vuoden päästä. Jos sivuston pitää kasvaa verkkokaupaksi tai yhdistyä muihin järjestelmiin, siirto Webflow&#39;sta WordPressiin myöhemmin on käytännössä uusi projekti.</p>
<p>Jos harkitset headless-ratkaisua, vertailin sitä artikkelissa <a href="/blogi/storyblok-vai-wordpress">Storyblok vai WordPress</a>.</p>
<p>Autan valinnassa ja WordPress-puolella myös toteutuksessa. Lisää <a href="/palvelut/wordpress-woocommerce">WordPress- ja WooCommerce-palvelusta</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="onko-webflow-parempi-hakukoneoptimoinnissa-kuin-wordpress">Onko Webflow parempi hakukoneoptimoinnissa kuin WordPress?</h3>
<p>Ei lähtökohtaisesti. Molemmilla saa tehtyä hakukoneystävällisen sivuston. Ratkaisevaa on sisältö, rakenne ja nopeus, ei alusta. WordPressissä hakukoneoptimointi on helpompi laajentaa esimerkiksi rakenteisella datalla.</p>
<h3 id="voiko-webflow-sivuston-siirtaa-wordpressiin">Voiko Webflow-sivuston siirtää WordPressiin?</h3>
<p>Voi, mutta käytännössä sivusto rakennetaan uudelleen. Sisällön voi viedä CSV-tiedostoina ja tuoda WordPressiin, mutta ulkoasu ja toiminnallisuus toteutetaan alusta.</p>
<h3 id="pystyyko-wordpressia-paivittamaan-yhta-helposti-kuin-webflow-39-ta">Pystyykö WordPressiä päivittämään yhtä helposti kuin Webflow&#39;ta?</h3>
<p>Kyllä, jos sivusto on rakennettu hyvin. Räätälöidyillä lohkoilla ja kentillä sisältöä päivitetään WordPressin editorissa ilman, että ulkoasu hajoaa.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Storyblok vai WordPress? Headless-CMS vai perinteinen sivusto</title>
      <link>https://peltopiri.com/blogi/storyblok-vai-wordpress</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/storyblok-vai-wordpress</guid>
      <pubDate>Thu, 12 Mar 2026 06:00:00 GMT</pubDate>
      <description>Storyblok on headless-CMS visuaalisella editorilla, WordPress kokonainen sivustoalusta. Vertailen, milloin kumpikin on oikea valinta.</description>
      <content:encoded><![CDATA[<p>Storyblok sopii yritykselle, jolla on oma kehitystiimi ja tarve julkaista samaa sisältöä useaan kanavaan, kuten verkkosivulle, sovellukseen ja myymälän näytöille. WordPress on parempi valinta useimmille pienille ja keskisuurille yrityksille, koska sivusto, hallintapaneeli ja hosting ovat yhdessä paketissa, eikä erillistä sovelluskehitystä tarvita. Ero ei ole siinä, kumpi on parempi sisällönhallinta, vaan siinä, kuinka paljon kehitystä ja ylläpitoa ollaan valmiita tekemään.</p>
<h2 id="mika-on-headless-cms">Mikä on headless-CMS?</h2>
<p>Perinteisessä sisällönhallinnassa, kuten WordPressissä, sama järjestelmä tallentaa sisällön ja näyttää sen sivustona. Headless-CMS hoitaa vain sisällön: sisältö haetaan rajapinnan kautta ja sivusto tai sovellus rakennetaan erikseen esimerkiksi Next.js-, Nuxt- tai Astro-kehyksellä. Nimi tulee siitä, että järjestelmästä puuttuu &quot;pää&quot; eli näkyvä sivusto.</p>
<h2 id="mika-storyblok-on">Mikä Storyblok on?</h2>
<p><a href="https://www.storyblok.com/">Storyblok</a> on itävaltalainen headless-CMS, jonka vahvuus on visuaalinen editori. Toisin kuin monessa headless-järjestelmässä, sisällön muokkaaja näkee muutokset sivun esikatselussa reaaliajassa. Sisältö rakennetaan komponenteista, joten samaa tuotekorttia tai banneria voi käyttää eri sivuilla ja kanavissa. Koska yritys on eurooppalainen, EU-alueelle sijoitettu data on helppo järjestää, mikä helpottaa tietosuojakysymyksiä.</p>
<h2 id="missa-storyblok-on-vahvempi">Missä Storyblok on vahvempi?</h2>
<ul>
<li><strong>Monikanavaisuus.</strong> Sama sisältö verkkosivulle, mobiilisovellukseen ja muihin kanaviin yhdestä paikasta.</li>
<li><strong>Kehittäjän vapaus.</strong> Sivusto voidaan tehdä millä tahansa nykyaikaisella kehyksellä ja se voi olla hyvin nopea, koska se julkaistaan esimerkiksi staattisena tai reunapalvelimilta.</li>
<li><strong>Tietoturva.</strong> Julkinen sivusto ja sisällönhallinta ovat erillään. Hallintapaneeli ei ole samassa osoitteessa, eikä sivustolla ole lisäosia, joihin hyökätä.</li>
<li><strong>Komponentit.</strong> Sisältö pysyy rakenteisena ja johdonmukaisena isossakin organisaatiossa.</li>
</ul>
<h2 id="missa-wordpress-on-vahvempi">Missä WordPress on vahvempi?</h2>
<ul>
<li><strong>Kokonaisuus.</strong> WordPressissä on valmiina sivusto, hallinta, käyttäjät, haku, lomakkeet ja tuhansia lisäosia. Headless-ratkaisussa jokainen näistä pitää rakentaa tai liittää erikseen.</li>
<li><strong>Kustannukset.</strong> Headless-sivustossa maksetaan sisällönhallinnasta, sivuston hostingista ja jatkuvasta kehityksestä. Storyblokin hinnoittelu riippuu muun muassa käyttäjien määrästä ja liikenteestä. WordPress-sivusto on yleensä edullisempi rakentaa ja ylläpitää.</li>
<li><strong>Verkkokauppa.</strong> WooCommerce on valmis verkkokauppa. Storyblokin kanssa kauppa toteutetaan erillisellä verkkokauppa-alustalla ja yhdistetään siihen.</li>
<li><strong>Itsenäisyys.</strong> WordPress-sivustoa voi päivittää ja kehittää moni toimija. Headless-sivusto on sidottu siihen kehyskoodiin, jonka joku on kirjoittanut, joten kehittäjän vaihto on raskaampaa.</li>
</ul>
<h2 id="mita-headless-projekti-vaatii">Mitä headless-projekti vaatii?</h2>
<p>Storyblokin hinta on vain osa kokonaisuutta. Headless-sivustossa pitää rakentaa tai valita erikseen ainakin nämä:</p>
<ul>
<li><strong>Sivuston koodi</strong> valitulla kehyksellä, esimerkiksi Next.js:llä tai Astrolla ja jokaiselle sisältökomponentille sitä vastaava osa koodiin.</li>
<li><strong>Hosting sivustolle</strong>, joka on eri palvelu kuin sisällönhallinta.</li>
<li><strong>Esikatselu</strong>, jotta visuaalinen editori näyttää muutokset oikein.</li>
<li><strong>Lomakkeet, haku ja sivukartta</strong>, jotka WordPressissä tulevat valmiina tai lisäosana.</li>
<li><strong>Julkaisuputki</strong>, joka päivittää sivuston, kun sisältöä muutetaan.</li>
</ul>
<p>Mikään näistä ei ole vaikeaa kokeneelle kehittäjälle, mutta ne kaikki pitää tehdä ja ylläpitää.</p>
<h2 id="enta-headless-wordpress">Entä headless WordPress?</h2>
<p>WordPressiäkin voi käyttää headless-tyyppisesti: sisältö haetaan sen rajapinnasta ja sivusto tehdään erikseen. Tämä yhdistää WordPressin tutun hallinnan ja vapaan kehyksen, mutta samalla menetetään osa WordPressin eduista, kuten lisäosien toiminnot ja editorin esikatselu. Käytän sitä yleensä vain, kun WordPress on jo käytössä ja sisältöä tarvitaan myös sovelluksessa.</p>
<h2 id="kumpi-kannattaa-valita">Kumpi kannattaa valita?</h2>
<p><strong>Valitse Storyblok, jos:</strong></p>
<ul>
<li>julkaiset samaa sisältöä useaan kanavaan</li>
<li>sinulla on kehitystiimi tai pitkäaikainen kehityskumppani</li>
<li>tarvitset hyvin nopean, nykyaikaisella kehyksellä tehdyn sivuston.</li>
</ul>
<p><strong>Valitse WordPress, jos:</strong></p>
<ul>
<li>tarvitset sivuston tai verkkokaupan, jota voi päivittää ja kehittää ilman jatkuvaa kehitystiimiä</li>
<li>haluat valmiita toimintoja lisäosina</li>
<li>budjetti on rajallinen.</li>
</ul>
<p>Pienempien alustojen vertailun löydät artikkelista <a href="/blogi/wix-squarespace-vai-wordpress">Wix ja Squarespace vai WordPress</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="onko-headless-sivusto-nopeampi-kuin-wordpress">Onko headless-sivusto nopeampi kuin WordPress?</h3>
<p>Usein on, koska se voidaan julkaista valmiiksi rakennettuina sivuina. Hyvin tehty WordPress-sivusto hyvällä hostingilla on kuitenkin myös nopea ja nopeusero näkyy lähinnä raskaissa sivustoissa.</p>
<h3 id="pystyyko-sisallontuottaja-kayttamaan-storyblokia-ilman-kehittajaa">Pystyykö sisällöntuottaja käyttämään Storyblokia ilman kehittäjää?</h3>
<p>Sisällön päivittäminen onnistuu visuaalisessa editorissa hyvin. Uudet sivutyypit ja komponentit tarvitsevat kuitenkin kehittäjän, koska ne pitää toteuttaa myös sivuston koodiin.</p>
<h3 id="voiko-wordpressista-siirtya-storyblokiin">Voiko WordPressistä siirtyä Storyblokiin?</h3>
<p>Voi. Sisältö siirretään rajapintojen kautta ja sivusto rakennetaan uudelleen valitulla kehyksellä. Siirto on käytännössä uusi sivustoprojekti.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Wix ja Squarespace vai WordPress? Mitä kotisivukoneen helppous maksaa</title>
      <link>https://peltopiri.com/blogi/wix-squarespace-vai-wordpress</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/wix-squarespace-vai-wordpress</guid>
      <pubDate>Tue, 24 Feb 2026 06:00:00 GMT</pubDate>
      <description>Wix ja Squarespace ovat helppoja aloittaa, WordPress joustavampi ja siirrettävämpi. Vertailen, milloin kotisivukone riittää ja milloin ei.</description>
      <content:encoded><![CDATA[<p>Wix ja Squarespace riittävät hyvin pienelle yritykselle, joka tarvitsee nopeasti siistin esittelysivuston ja haluaa tehdä sen itse. WordPress kannattaa, kun sivuston pitää kasvaa: lisää sisältöä, verkkokauppa, monikielisyys tai yhteyksiä muihin järjestelmiin. Suurin ero ei näy aloittaessa vaan muutaman vuoden päästä, kun sivustoa pitäisi laajentaa tai siirtää muualle.</p>
<h2 id="mita-wix-ja-squarespace-ovat">Mitä Wix ja Squarespace ovat?</h2>
<p><a href="https://www.wix.com/">Wix</a> ja <a href="https://www.squarespace.com/">Squarespace</a> ovat kotisivukoneita: sivusto tehdään selaimessa valmiiden pohjien päälle ja hosting, tietoturva ja päivitykset kuuluvat kuukausimaksuun. Squarespacen pohjat ovat tunnettuja tyylikkyydestään. Wix on joustavampi ja siinä on enemmän lisätoimintoja sovelluskaupasta.</p>
<h2 id="missa-kotisivukoneet-ovat-vahvoja">Missä kotisivukoneet ovat vahvoja?</h2>
<ul>
<li><strong>Helppous.</strong> Sivuston saa pystyyn päivässä ilman teknistä osaamista.</li>
<li><strong>Ei ylläpitoa.</strong> Päivityksistä ja tietoturvasta vastaa palveluntarjoaja.</li>
<li><strong>Ennustettava hinta.</strong> Yksi kuukausimaksu kattaa hostingin ja työkalut.</li>
<li><strong>Valmiit pohjat.</strong> Etenkin Squarespacessa pohjat näyttävät hyviltä sellaisinaan.</li>
</ul>
<h2 id="missa-kotisivukoneet-rajoittavat">Missä kotisivukoneet rajoittavat?</h2>
<p><strong>Sivusto on vuokralla.</strong> Et omista sivustoa samalla tavalla kuin WordPress-sivustoa. Jos palvelun hinta nousee tai ehdot muuttuvat, vaihtoehdot ovat vähissä.</p>
<p><strong>Siirtäminen on vaikeaa.</strong> Tämä yllättää useimmat. Wixistä ei voi viedä koko sivustoa muualle, joten siirto tarkoittaa käytännössä <a href="https://www.hostinger.com/tutorials/wix-to-wordpress/">sivuston rakentamista uudelleen</a>. Blogin artikkelit saa siirrettyä, mutta sivut ja ulkoasu eivät siirry. Squarespacen <a href="https://support.squarespace.com/hc/en-us/articles/206566687-Exporting-your-site">vienti</a> tuottaa WordPress-muotoisen tiedoston, mutta mukaan tulevat vain tavalliset sivut ja yksi blogi. Esimerkiksi kauppasivut, tuotteet, portfoliosivut, video- ja äänisisältö, tyylit ja oma CSS jäävät pois.</p>
<p><strong>Laajentaminen on rajattua.</strong> Kun tarvitaan jotain, mitä palvelussa ei ole valmiina, esimerkiksi oma sisältötyyppi, yhteys toiminnanohjaukseen tai erikoinen hinnoittelulogiikka verkkokauppaan, vaihtoehtoja on vähän. WordPressiin sen voi rakentaa.</p>
<p><strong>Suomalaiset tarpeet.</strong> WordPressiin ja WooCommerceen löytyvät valmiina suomalaiset maksutavat, kuljetusyhtiöt ja kirjanpidon integraatiot. Kotisivukoneissa valikoima riippuu siitä, mitä palvelu tukee.</p>
<h2 id="enta-hakukoneet">Entä hakukoneet?</h2>
<p>Wixin ja Squarespacen sivustot näkyvät hakukoneissa nykyään hyvin ja perusasiat, kuten otsikot, kuvaukset ja sivukartta, onnistuvat niissä. Rajat tulevat vastaan, kun halutaan tarkempaa hallintaa, esimerkiksi omaa rakenteista dataa, tarkkoja uudelleenohjauksia tai laajaa sisältöä hyvin rakennettuna. WordPressissä nämä ovat kokonaan omassa hallinnassa.</p>
<p>Jos nykyisen sivustosi näkyvyys hakukoneissa ja tekoälyhauissa mietityttää, sen voi selvittää alustasta riippumatta <a href="/palvelut/seo-geo-saavutettavuusauditit">SEO- ja GEO-auditilla</a>.</p>
<h2 id="mita-wordpress-vaatii-vastineeksi">Mitä WordPress vaatii vastineeksi?</h2>
<p>WordPress vaatii ylläpitoa: päivitykset, varmuuskopiot ja hyvän hostingin. Sen voi hoitaa itse, ostaa hallinnoidulta hosting-palvelulta, kuten <a href="https://seravo.com/fi/">Seravolta</a>, tai sopia ylläpidosta kehittäjän kanssa. Ilman ylläpitoa WordPress-sivusto vanhenee ja muuttuu tietoturvariskiksi. Tämä on rehellinen hinta joustavuudesta.</p>
<h2 id="mita-siirto-wordpressiin-vaatii">Mitä siirto WordPressiin vaatii?</h2>
<p>Jos päätät siirtyä, siirto kannattaa tehdä suunnitellusti, jotta hakunäkyvyys ei katoa:</p>
<ol>
<li><strong>Kartoita nykyiset osoitteet.</strong> Listaa kaikki sivut ja artikkelit, myös ne, joihin muut sivustot linkittävät.</li>
<li><strong>Siirrä sisältö.</strong> Tekstit, kuvat ja blogin artikkelit siirretään ja tarkistetaan. Tässä vaiheessa kannattaa samalla siivota vanhentunut sisältö pois.</li>
<li><strong>Rakenna uusi sivusto.</strong> Ulkoasu ja toiminnallisuus toteutetaan WordPressiin ja lomakkeet, analytiikka ja evästeasetukset otetaan uudelleen käyttöön.</li>
<li><strong>Tee uudelleenohjaukset.</strong> Jokainen vanha osoite ohjataan vastaavaan uuteen osoitteeseen. Tämä on hakunäkyvyyden kannalta tärkein vaihe.</li>
<li><strong>Seuraa julkaisun jälkeen.</strong> Google Search Consolesta näkee, löytyykö rikkinäisiä linkkejä tai puuttuvia sivuja.</li>
</ol>
<h2 id="kumpi-kannattaa-valita">Kumpi kannattaa valita?</h2>
<p><strong>Wix tai Squarespace riittää, jos:</strong></p>
<ul>
<li>tarvitset esittelysivuston, jossa on muutama sivu</li>
<li>haluat tehdä ja päivittää sen itse</li>
<li>et tarvitse integraatioita tai laajaa verkkokauppaa.</li>
</ul>
<p><strong>Valitse WordPress, jos:</strong></p>
<ul>
<li>sivuston pitää kasvaa tai siinä on paljon sisältöä</li>
<li>tarvitset verkkokaupan suomalaisilla maksutavoilla ja kuljetuksilla tai yhteyksiä muihin järjestelmiin</li>
<li>haluat omistaa sivustosi ja voida vaihtaa hostingia tai kehittäjää vapaasti.</li>
</ul>
<p>Jos olet jo kotisivukoneessa ja seinä tulee vastaan, autan siirrossa WordPressiin niin, että hakunäkyvyys säilyy. Lisää <a href="/palvelut/wordpress-woocommerce">WordPress- ja WooCommerce-palvelusta</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="onko-wordpress-kalliimpi-kuin-wix-tai-squarespace">Onko WordPress kalliimpi kuin Wix tai Squarespace?</h3>
<p>Alussa usein on, koska sivuston rakentamiseen käytetään enemmän työtä ja ylläpito maksaa. Pitkällä aikavälillä ero kapenee ja WordPressissä ei tarvitse aloittaa alusta, kun tarpeet kasvavat.</p>
<h3 id="voiko-wix-sivuston-siirtaa-wordpressiin">Voiko Wix-sivuston siirtää WordPressiin?</h3>
<p>Voi, mutta sivusto rakennetaan käytännössä uudelleen. Blogin artikkelit voidaan siirtää ja vanhoista osoitteista tehdään uudelleenohjaukset uusiin, jotta hakunäkyvyys säilyy.</p>
<h3 id="voinko-paivittaa-wordpress-sivustoa-itse-yhta-helposti">Voinko päivittää WordPress-sivustoa itse yhtä helposti?</h3>
<p>Voit, jos sivusto on rakennettu sitä ajatellen. Rakennan sivustot niin, että tekstit, kuvat ja tuotteet päivittyvät editorissa ilman koodia ja ilman, että ulkoasu hajoaa.</p>
]]></content:encoded>
    </item>
    <item>
      <title>WordPress-lohkon rakentaminen tekoälyn avulla – kolme tapaa ja niiden sudenkuopat</title>
      <link>https://peltopiri.com/blogi/wordpress-lohko-tekoalylla</link>
      <guid isPermaLink="true">https://peltopiri.com/blogi/wordpress-lohko-tekoalylla</guid>
      <pubDate>Tue, 27 Jan 2026 06:00:00 GMT</pubDate>
      <description>Tekoäly tekee WordPress-lohkon nopeasti. Vertailen kolmea tapaa: build-prosessi, ACF Blocks ja kevyt zip-lisäosa, sekä mitä tehdä, kun sivusto kaatuu.</description>
      <content:encoded><![CDATA[<p>Tekoäly osaa tehdä WordPressin editoriin oman lohkon muutamassa minuutissa. Siihen on kolme tapaa: virallinen JavaScript-lohko build-prosessilla, ACF Blocks PHP-pohjalla tai kevyt lisäosa, joka toimii ilman build-vaihetta ja asennetaan zip-tiedostona. Ne sopivat eri tilanteisiin. Ennen kuin tekoälyn tekemää koodia asentaa tuotantosivustolle, kannattaa kuitenkin tietää, mitä tehdä sivuston kaatuessa ja kuka vastaa koodin tietoturvasta.</p>
<h2 id="tapa-1-oikea-lohko-build-prosessilla">Tapa 1: oikea lohko build-prosessilla</h2>
<p>WordPressin <a href="https://developer.wordpress.org/block-editor/getting-started/quick-start-guide/">virallinen tapa</a> on luoda lohkolle oma lisäosa <code>create-block</code>-työkalulla:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-bash">npx @wordpress/create-block@latest yhteystietokortti
cd yhteystietokortti
npm start
</code></pre>
<p>Työkalu luo valmiin rakenteen: <code>block.json</code> kuvaa lohkon, <code>edit.js</code> määrittää lohkon ulkoasun editorissa ja <code>save.js</code> sivulle tallennettavan sisällön. Tekoälylle annetaan tehtäväksi kuvata lohko, esimerkiksi &quot;yhteystietokortti, jossa on kuva, nimi, titteli ja puhelinnumero. Kuvan voi vaihtaa sivupalkista.&quot; Tekoäly muokkaa nämä tiedostot. Lopuksi <code>npm run build</code> kääntää koodin ja <code>npm run plugin-zip</code> paketoi lisäosan asennettavaksi.</p>
<p><strong>Sopii</strong>, kun lohkossa on paljon vuorovaikutusta editorissa, se on osa isompaa teemaa tai lisäosaa ja koodia ylläpidetään versionhallinnassa.</p>
<p><strong>Haittana</strong> on Node.js-ympäristö ja build-vaihe, jota ilman koodia ei voi muuttaa. Jos tiedostoja muokataan suoraan palvelimella, muutos ei vaikuta mihinkään.</p>
<h2 id="tapa-2-acf-blocks">Tapa 2: ACF Blocks</h2>
<p><a href="/palvelut/wordpress-woocommerce">ACF:llä</a> lohko tehdään PHP:llä ja kentillä. Editorin puoli syntyy ACF:n kenttäryhmästä, joten JavaScriptiä ei tarvita. ACF 6.0:sta alkaen lohko määritellään samalla <code>block.json</code>-tiedostolla kuin WordPressin omat lohkot ja ACF:n asetukset ovat <code>acf</code>-avaimen alla:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-json">{
  &quot;name&quot;: &quot;acf/yhteystietokortti&quot;,
  &quot;title&quot;: &quot;Yhteystietokortti&quot;,
  &quot;category&quot;: &quot;widgets&quot;,
  &quot;acf&quot;: { &quot;mode&quot;: &quot;preview&quot;, &quot;renderTemplate&quot;: &quot;template.php&quot; }
}
</code></pre>
<p>Lohkon HTML kirjoitetaan PHP-sivupohjaan:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-php">&lt;div class=&quot;yhteystietokortti&quot;&gt;
  &lt;h3&gt;&lt;?php echo esc_html( get_field( &#39;nimi&#39; ) ); ?&gt;&lt;/h3&gt;
  &lt;a href=&quot;tel:&lt;?php echo esc_attr( get_field( &#39;puhelin&#39; ) ); ?&gt;&quot;&gt;
    &lt;?php echo esc_html( get_field( &#39;puhelin&#39; ) ); ?&gt;
  &lt;/a&gt;
&lt;/div&gt;
</code></pre>
<p>Lohko rekisteröidään teemassa tai lisäosassa <code>register_block_type()</code>-funktiolla ja kentät luodaan ACF:n hallintanäkymässä.</p>
<p><strong>Sopii</strong>, kun sisältö on rakenteista ja päivittäjän pitää täyttää vain tietyt kentät. Tekoäly tuottaa ACF-lohkon luotettavasti, koska rakenne on yksinkertainen.</p>
<p><strong>Haittana</strong> on, että ACF Blocks vaatii ACF PRO -lisenssin ja editorin esikatselu on hieman jäykempi kuin JavaScript-lohkossa.</p>
<h2 id="tapa-3-kevyt-lohko-ilman-build-vaihetta-zip-tiedostona">Tapa 3: kevyt lohko ilman build-vaihetta, zip-tiedostona</h2>
<p>Yksinkertaisen lohkon voi tehdä tavallisella JavaScriptillä, joka käyttää suoraan WordPressin editorin valmiita kirjastoja. Lisäosassa on neljä tiedostoa samassa kansiossa:</p>
<p><strong>lainauslaatikko.php</strong></p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-php">&lt;?php
/**
 * Plugin Name: Lainauslaatikko
 * Description: Yksinkertainen lainauslohko.
 * Version: 1.0.0
 */
add_action( &#39;init&#39;, function () {
	register_block_type( __DIR__ );
} );
</code></pre>
<p><strong>block.json</strong></p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-json">{
  &quot;apiVersion&quot;: 3,
  &quot;name&quot;: &quot;peltopiri/lainauslaatikko&quot;,
  &quot;title&quot;: &quot;Lainauslaatikko&quot;,
  &quot;category&quot;: &quot;text&quot;,
  &quot;attributes&quot;: {
    &quot;teksti&quot;: { &quot;type&quot;: &quot;string&quot;, &quot;source&quot;: &quot;html&quot;, &quot;selector&quot;: &quot;p&quot; }
  },
  &quot;editorScript&quot;: &quot;file:./index.js&quot;
}
</code></pre>
<p><strong>index.asset.php</strong> kertoo WordPressille, mitä kirjastoja skripti tarvitsee:</p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-php">&lt;?php return array( &#39;dependencies&#39; =&gt; array( &#39;wp-blocks&#39;, &#39;wp-element&#39;, &#39;wp-block-editor&#39; ), &#39;version&#39; =&gt; &#39;1.0.0&#39; );
</code></pre>
<p><strong>index.js</strong></p>
<pre tabindex="0" aria-label="Koodiesimerkki"><code class="language-js">( function ( blocks, element, blockEditor ) {
	const el = element.createElement;
	const { RichText, useBlockProps } = blockEditor;

	blocks.registerBlockType( &#39;peltopiri/lainauslaatikko&#39;, {
		edit: ( { attributes, setAttributes } ) =&gt;
			el( &#39;div&#39;, useBlockProps( { className: &#39;lainauslaatikko&#39; } ),
				el( RichText, {
					tagName: &#39;p&#39;,
					value: attributes.teksti,
					onChange: ( teksti ) =&gt; setAttributes( { teksti } ),
					placeholder: &#39;Kirjoita lainaus…&#39;,
				} )
			),
		save: ( { attributes } ) =&gt;
			el( &#39;div&#39;, useBlockProps.save( { className: &#39;lainauslaatikko&#39; } ),
				el( RichText.Content, { tagName: &#39;p&#39;, value: attributes.teksti } )
			),
	} );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor );
</code></pre>
<p>Kansio pakataan zipiksi (<code>zip -r lainauslaatikko.zip lainauslaatikko</code>) ja asennetaan kohdasta Lisäosat → Lisää uusi → Lataa lisäosa.</p>
<p><strong>Sopii</strong> pieneen, yksittäiseen lohkoon, jonka haluaa sivustolle nopeasti ilman kehitysympäristöä.</p>
<p><strong>Haittana</strong> on, että koodi on kömpelömpää kirjoittaa kuin JSX:llä ja lohkon kasvaessa siitä tulee nopeasti vaikea ylläpitää.</p>
<h2 id="sudenkuoppa-1-sivusto-kaatuu">Sudenkuoppa 1: sivusto kaatuu</h2>
<p>Tekoälyn tekemä lisäosa voi sisältää PHP-virheen, joka kaataa koko sivuston. WordPress 5.2:sta alkaen <a href="https://make.wordpress.org/core/2019/04/16/fatal-error-recovery-mode-in-5-2/">palautustila</a> lähettää tällöin ylläpitäjän sähköpostiin linkin, jolla pääsee hallintaan ja voi poistaa vikaantuneen lisäosan käytöstä. Se toimii vain, jos sivuston sähköposti toimii ja ylläpitäjän osoite on oikea.</p>
<p>Jos sähköpostia ei tule, lisäosa pitää poistaa käytöstä palvelimen puolelta:</p>
<ul>
<li>SFTP:llä tai hosting-palvelun tiedostonhallinnassa: nimeä lisäosan kansio uudelleen <code>wp-content/plugins</code>-kansiossa.</li>
<li>SSH:lla ja WP-CLI:llä: <code>wp plugin deactivate lainauslaatikko</code>.</li>
</ul>
<p><strong>Ennen kuin asennat mitään, tarkista, että sinulla on jokin näistä pääsyistä.</strong> Jos ainoa pääsy sivustoon on WordPressin hallintapaneeli, olet kaatumisen jälkeen hosting-palvelun tuen armoilla. Ota myös varmuuskopio ja kokeile lisäosaa ensin testiympäristössä, jos sellainen on.</p>
<h2 id="sudenkuoppa-2-lohkon-validointivirhe">Sudenkuoppa 2: lohkon validointivirhe</h2>
<p>JavaScript-lohkon <code>save</code>-funktio tallentaa HTML:n sivun sisältöön. Jos tekoäly myöhemmin muuttaa sitä, jo tehdyt lohkot näyttävät editorissa virheilmoituksen, jonka mukaan lohko sisältää odottamatonta sisältöä. Ratkaisuja on kaksi: lohkolle määritellään sen vanhat tallennusmuodot (deprecated), tai lohko tehdään dynaamiseksi, jolloin HTML tulostetaan PHP:llä joka kerta. ACF Blocks ovat aina dynaamisia, joten niissä tätä ongelmaa ei ole.</p>
<h2 id="sudenkuoppa-3-kuka-vastaa-tietoturvasta">Sudenkuoppa 3: kuka vastaa tietoturvasta?</h2>
<p>Zip-tiedostona asennettu lisäosa ajetaan samoilla oikeuksilla kuin WordPress itse. Se voi lukea tietokantaa, lähettää dataa ja muuttaa mitä tahansa. Tekoälyn koodi näyttää usein valmiilta, mutta siitä voi puuttua:</p>
<ul>
<li>tulosteiden suojaus, kuten <code>esc_html()</code>, <code>esc_attr()</code> ja <code>wp_kses_post()</code></li>
<li>käyttöoikeuksien tarkistus ja nonce-tunnisteet, jos lohko tallentaa tai hakee tietoja</li>
<li>syötteiden tarkistus.</li>
</ul>
<p>Vastuu on sillä, joka asentaa koodin. Valmiille lisäosalle tulee päivityksiä tekijältä, mutta itse tehtyä ei päivitä kukaan muu. Siksi jokaisella omalla lisäosalla pitää olla nimetty ylläpitäjä, koodi versionhallinnassa ja tieto siitä, mitä se tekee. Koodin pitää myös olla jonkun ihmisen lukema ennen asennusta.</p>
<h2 id="mika-tapa-kannattaa-valita">Mikä tapa kannattaa valita?</h2>
<ul>
<li><strong>Build-prosessi</strong>, kun lohko on osa ammattimaisesti ylläpidettyä teemaa tai lisäosaa.</li>
<li><strong>ACF Blocks</strong>, kun sisältö on rakenteista ja ACF PRO on jo käytössä. Teen itse suurimman osan lohkoista näin.</li>
<li><strong>Kevyt zip-lohko</strong>, kun tarvitaan yksi pieni lohko nopeasti ja ymmärrät, mitä koodi tekee.</li>
</ul>
<p>Jos haluat sivustollesi omia lohkoja, jotka on rakennettu ylläpidettäviksi ja turvallisiksi, se kuuluu <a href="/palvelut/wordpress-woocommerce">WordPress-työhöni</a>.</p>
<h2 id="usein-kysyttya">Usein kysyttyä</h2>
<h3 id="voiko-tekoalyn-tekeman-lisaosan-asentaa-suoraan-tuotantoon">Voiko tekoälyn tekemän lisäosan asentaa suoraan tuotantoon?</h3>
<p>Ei kannata. Kokeile ensin testiympäristössä, ota varmuuskopio ja varmista, että pääset tarvittaessa poistamaan lisäosan palvelimen puolelta.</p>
<h3 id="tarvitaanko-acf-blocksiin-acf-pro">Tarvitaanko ACF Blocksiin ACF PRO?</h3>
<p>Kyllä. ACF Blocks on ACF PRO -lisenssin ominaisuus. Ilmainen ACF riittää kenttiin, mutta ei lohkoihin.</p>
<h3 id="mita-teen-jos-sivusto-nayttaa-vain-virheilmoituksen">Mitä teen, jos sivusto näyttää vain virheilmoituksen?</h3>
<p>Tarkista ylläpitäjän sähköposti palautuslinkin varalta. Jos sitä ei tule, poista viimeksi asennettu lisäosa käytöstä SFTP:llä, hosting-palvelun tiedostonhallinnalla tai WP-CLI:llä, tai pyydä apua hosting-palvelun tuesta.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
