• Projektipäevik #3: Vundament – pluginad, CPT-d, meta-väljad

    Kolmas postitus projektipäeviku sarjas. Eelmistes lugesime, mis on theme.json ja meie disainisüsteem ning mis on meie plaan ja arhitektuuri-otsused. Nüüd on viimaks tehtud vundamenditöö – kõik see, ilma milleta esilehe ehitama ei saa hakata.

    Mida vundament katab

    “Etapp 0” meie plaanis koosneb kuuest sammust:

    1. CPT UI + ACF pluginate installimine
    2. Service ja Team Custom Post Type’ide seadistamine
    3. Meta-väljade lisamine ACF kaudu
    4. Õhuke teema functions.php loomine
    5. (järgmine: patterns/ kausta loomine + Hero pattern)
    6. Testandmete loomine

    Selles postituses katab esimesed neli. Vaatame samme ükshaaval ja peatume olulistel õppetundidel.

    1. Pluginate paigaldamine

    Otsus, et CPT-d (Custom Post Type’d) lähevad plugin’isse, mitte teema functions.php-isse, oli teadlik (vaata #2 postitust). Põhjus: kui sa vahetad teemat, kas sait jääks tööle? CPT-d on sisu-loogika – peavad jääma alles isegi kui teema muutub.

    Praktikas valisime kaks levinumat tasuta plugin’it:

    • Custom Post Type UI (CPT UI) – GUI CPT-de registreerimiseks
    • Advanced Custom Fields (ACF) – meta-väljade haldamiseks

    Kompromissi-otsus oli, et õpetuslikus kontekstis pole praegu eesmärk PHP CPT-koodi õpetada. CPT UI annab kiire stardi GUI kaudu. Hiljem saab näidata, kuidas CPT UI-st kood eksportida ja oma plugin’i kolida – see on omaette õppetund “GUI vs koodipõhine konfiguratsioon”.

    2. CPT-d: Service ja Team

    CPT UI vorm võib esmapilgul tunduda hirmutav – kümneid välju, igaüks oma seadega. Aga enamus on intuitiivne, kui mõistad mõnda võtmemõistet:

    • Post type slug (service) – sisemine koodi-nimi, ei muutu hiljem
    • Custom Rewrite Slug (services) – URL-is nähtav
    • Has Archive – kas tekib koondleht (/services/)
    • Supports – millised toimetamise-väljad on saadaval (title, editor, thumbnail, excerpt)
    • Show in REST API – kriitiline, ilma selleta Block Editor ei tööta

    Service vs Team – vahed

    SeadeServiceTeam
    URL slugservicesteam
    Has ArchiveTrue (/services/ koondleht)False (kuvame Meist-lehel)
    ExcerptJah (lühikirjeldus kaardile)Ei
    Menu ikoondashicons-portfoliodashicons-groups

    Üks asi, mille üle veel mõtleme: /team/ URL renderdub praegu tühjalt (ainult footer), sest has_archive: false. WP ei loo Team arhiivilehte, ja sait langeb fallback’iks index.html-le. Pole hetkel probleem – Team kuvatakse Meist-lehel Query Loop’i kaudu.

    3. ACF meta-väljad – ja “Show in REST API” lõks

    Iga CPT vajab lisaks vaikimisi väljadele ka kohandatud välju:

    • Service Fields: price_from (Number), icon (Text), featured (True/False)
    • Team Member Fields: job_title (Text), email (Email), linkedin (URL)

    ACF Field Group on jaotatud kolme tabi vahel: Location Rules, Presentation, Group Settings. Iga üksiku Field on omakorda neljas tabis: General, Validation, Presentation, Conditional Logic. UI loogika selgus pärast paari katse-eksitust.

    Kõige olulisem lüliti: Show in REST API

    ACF Field Group Group Settings tab → lüliti Show in REST API. Vaikimisi VÄLJAS. Kui jätad nii, siis Block Editor ei näe ACF välju – ehk meie tulevased patternid ei saa neid kuvada. Lülita alati sisse.

    Sama oluline on Location Rules: iga grupp peab teadma, millise CPT juures ilmuda (Post Type = Service VÕI Team Member). Vastasel juhul grupp kas ei ilmu kuskil või kõikjal.

    4. Õhuke teema functions.php

    Klassikalises WP teemas oli functions.php “kõik-ühes-failis”. FSE teemas on see palju õhem. Lihtne otsustamise reegel: “kui sa eemaldad teemat, kas sisu jääks alles?” Kui jah → on plugin. Kui ainult visuaal muutub → on teemas.

    Meie teema functions.php teeb kolm asja:

    • add_theme_support() – deklareerib, mida teema toetab (post-thumbnails, HTML5)
    • register_block_style() – lisab Button blokile uue stiili “Secondary”
    • register_block_pattern_category() – loob 3 kategooriat patternide grupeerimiseks

    Kõik kasutab WordPressi hookide süsteemi – funktsioonid “liidetakse” sündmustele (after_setup_theme, init). See on WP-i tuum: mitte impereratiivne kood, vaid sündmuse-põhine “kui see juhtub, käivita too”.

    Terve functions.php pärast seda etappi

    Selle etapi lõpus näeb functions.php välja nii (PHP-võhikutele: salvesta see fail teema kausta nimega functions.php):

    <?php
    /**
     * fse-theme functions.php
     *
     * Theme support + block styles + pattern categories.
     * NB! CPT-d ja meta-väljad on plugin'ites (CPT UI + ACF), mitte siin.
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }
    
    /**
     * Theme support deklaratsioonid.
     */
    function fse_theme_setup() {
        add_theme_support( 'post-thumbnails' );
    
        add_theme_support( 'html5', [
            'search-form',
            'comment-form',
            'comment-list',
            'gallery',
            'caption',
            'style',
            'script',
        ] );
    
        add_theme_support( 'wp-block-styles' );
    }
    add_action( 'after_setup_theme', 'fse_theme_setup' );
    
    /**
     * Block style: Secondary Button.
     */
    function fse_theme_register_block_styles() {
        register_block_style( 'core/button', [
            'name'  => 'secondary',
            'label' => __( 'Secondary', 'fse-theme' ),
        ] );
    }
    add_action( 'init', 'fse_theme_register_block_styles' );
    
    /**
     * Pattern kategooriad.
     */
    function fse_theme_register_pattern_categories() {
        register_block_pattern_category( 'fse-theme-hero', [
            'label' => __( 'FSE Theme – Hero', 'fse-theme' ),
        ] );
    
        register_block_pattern_category( 'fse-theme-card', [
            'label' => __( 'FSE Theme – Cards', 'fse-theme' ),
        ] );
    
        register_block_pattern_category( 'fse-theme-section', [
            'label' => __( 'FSE Theme – Sections', 'fse-theme' ),
        ] );
    }
    add_action( 'init', 'fse_theme_register_pattern_categories' );
    

    See on versioon 1. Iga järgmise blogipostituse (kus muudame functions.php) näitame nii lisatava juppi kui kogu sel hetkel tervet faili.

    Vahepealse õppetund: slug ei tohi alata numbriga

    Ehitamise käigus jooksime kokku samasse lõksu, mida juba kirjeldasime esimeses postituses – aga seekord font-size slug’idega. Kõik h1, h2, h3 olid frontend’is sama suurusega (14px). Põhjus: WP normaliseeris CSS muutuja nimi (5xl5-xl), aga styles.elements.h2 viide jäi 5xl-iks – muutuja ei eksisteerinud, brauser kasutas fallback’i.

    Lahendus: ümbernimetatud kõik 2xl, 3xl, … 7xl kujule xxl, xxxl, … xxxxxxxl. Sama muster mis spacing’utel. Reegel: theme.json slug ei alga kunagi numbriga.

    Mis nüüd näeme

    Loodud on testandmed: üks Service (“SEO Optimization”) koos kõigi ACF väljadega ja üks Team Member (“Maria Saar”). Frontend’is näevad mõlemad korralikud välja:

    • H1 pealkiri suur ja silmatorkav (Inter font, 56px-ni)
    • H2/H3 alapealkirjad selgelt väiksemad
    • Body text lugemissõbralik (14px, 1.6 line-height)
    • Listid bullet-stiilis

    Üks väike asi veel: post-title on praegu sinine, sest index.html template’is on isLink: true ja link’i värv on accent-default. Tehniline detail, mille parandame, kui ehitame proper single.html template’i.

    Mis tuleb järgmisena

    Etapp 0 viimane samm: patterns/ kausta loomine ja esimene pattern (Hero-Home). Siis hakkame ehitama esilehte – kuus sektsiooni, igaüks oma pattern:

    1. Hero (juba olemas project/-s, vaja kolida teema kausta)
    2. Values – “Miks meie”
    3. Featured Services – kasutab äsja loodud CPT-d
    4. BlogPreview – 3 viimast postitust
    5. Testimonials
    6. Final CTA

    Iga sektsioon = eraldi õppetund. Iga pattern = uus kontseptsioon (Query Loop, Post Template, nested patterns, jne). Järgmises postituses tutvustame Hero patternit ja räägime, mis vahe on theme pattern’il ja template part’il.

  • Projektipäevik #2: Plaan ja arhitektuuri-otsused

    See on esimene postitus uues postituste sarjas “Projektipäevik”, kus dokumenteerime samm-sammult selle WordPress FSE teema ehitamist. Sari on mõeldud nii õpilastele kui ka tulevikus uutele meeskonnaliikmetele – et nad mõistaksid, miks projekt sellisena välja näeb, mitte ainult kuidas ta töötab.

    Mida me ehitame

    WordPress Full Site Editing (FSE) teema nimega fse-theme, mille disain pärineb Figma wireframidest. Lehte saab ehitada otse Site Editor’is, ilma et peaks teadma PHP-d või muutma malle koodi tasandil. Kogu kujundus tuleb theme.json-ist ja patternidest.

    Sait sisaldab 8 erinevat lehte (esileht, teenused, üksiku teenuse leht, meist, kontakt, blogi, blogipostitus, privaatsuspoliitika) ning kahte custom post type’i (Service ja Team). Disainisüsteem koosneb 38 muutujast: värvid, vahed, fondi-suurused, raadiused.

    Pedagoogiline lähenemine

    See projekt on ennekõike õppematerjal. Iga samm – alates theme.json seadistamisest kuni pattern-i loomiseni – on dokumenteeritud nii, et õpilane saab aru:

    • Miks me seda teeme (FSE-loogika, parimad tavad)
    • Kuidas see samm-sammult käib
    • Mida kontrollida, et veenduda õnnestumises

    Töövoog: AI-assistent (Claude/Cowork) selgitab ja dokumenteerib → kasutaja teeb. Ei lähe automaatselt edasi. Iga lõpetatud samm dokumenteeritakse projekti repos failis project/casestudy.md.

    Põhilised arhitektuuri-otsused

    1. Fluid spacing – üks väärtus, kohaneb ekraaniga

    FSE-l pole praegu native UI’d, mille kaudu määrata blokile erinevat padding’ut mobiilis ja desktopis. Lahenduseks valisime CSS clamp() funktsiooni spacingSizes preset’ides:

    { "slug": "xxxxxxl", "size": "clamp(40px, 3vw + 16px, 96px)" }

    Mobiilis ~40px, desktopis 96px, vahepeal sujuv üleminek. Põhimõte: mida väiksem spacing, seda väiksem muutus. UI-tihendid (4–16px) jäävad fikseerituks, sektsiooni-padding’ud (32px+) kahanevad mobiilis. Üks padding-väärtus footer’is töötab kõigil ekraanidel – pole vaja media query’sid.

    2. Custom Post Type’d plugin’is, mitte teemas

    WordPressi ametlik soovitus: “If you switch themes, you shouldn’t lose your content.” Kui registreeriksid Service CPT teema functions.php-s, siis teema vahetusel kaoks menüüpunkt “Teenused” admin’ist (postitused küll jääksid DB-sse, aga “orvuks”).

    Õige eraldus:

    • Teema – kujundus (CSS, templates, layout, theme.json)
    • Plugin – funktsionaalsus (CPT-d, meta-väljad, integratsioonid)

    Valisime CPT UI plugin’i CPT-de registreerimiseks (kõige levinum, 5M+ installi) ja ACF meta-väljade jaoks. Põhjus: õpetuslikus kontekstis pole praegu eesmärk PHP CPT-koodi õpetada – keskendume FSE-le. CPT UI annab kiire stardi GUI kaudu.

    3. Page-by-page lähenemine

    Kahe peamise lähenemise vahel – “ehita kõik komponendid valmis, siis lehed” vs “leht-haaval otsast lõpuni” – valisime teise. Põhjus: kasutaja näeb kohe töötavat tulemust, iga sektsioon on selge sammuga seotud, ja õpilane saab visuaalselt jälgida progressi.

    Esimene leht: esileht, mis koosneb 6 sektsioonist: Hero (juba olemas), Values, Featured Services, Blog Preview, Testimonials, Final CTA. Igale sektsioonile vastab üks (või kaks) pattern’it.

    4. Dokumenteerimine kahes kohas

    • project/casestudy.md – tehnilised case study’d (probleem → lahendus formaadis), versioonihalduses Git’i kaudu
    • WordPress’i blogi (see postituste sari) – “miks” ja “kuidas” narratiivina, avalik, läbi WP admin’i loetav

    Mis on praegu valmis

    • theme.json – disainisüsteem (38 muutujat) + fluid spacing’ud
    • parts/header.html ja parts/footer.html – template parts
    • CPT UI ja ACF pluginad installitud ja aktiveeritud
    • Inter fondid integreeritud

    Mis tuleb järgmisena

    1. CPT-de seadistamine CPT UI kaudu – Service ja Team
    2. Meta-väljade lisamine ACF kaudu – hind, ametinimetus, jne
    3. Õhuke teema functions.php – ainult block styles + pattern categories
    4. Esimesed patternid: card-value, values-grid (“Miks meie” sektsioon)
    5. Edasi punkti haaval iga sektsiooni kaudu kuni esileht on koos

    Järgmises postituses – CPT-de seadistamine ja miks me valisime just need konkreetsed sätted (slug, supports, has_archive jne).

  • Projektipäevik #1: theme.json – disainisüsteemi süda

    Projektipäeviku esimene postitus tutvustab theme.json faili – WordPress Full Site Editing teema tähtsaimat üksikfaili. See on koht, kus elab kogu disainisüsteem: värvid, vahed, fondi-suurused, raadiused, varjud. Kogu kujundus voolab siit edasi nii Site Editor’i UI-sse kui ka frontendi.

    Mis on theme.json?

    Kuni WordPress 5.9 oli FSE veel eksperimentaalne, ja teemastiilide haldamine käis CSS-failide ja PHP-koodi kaudu. Alates 5.9-st on theme.json ametlik viis defineerida:

    • Settings – mis disaini-väärtused on saadaval (värvi-palett, spacingu skaala, fondi-perekonnad)
    • Styles – kuidas vaikimisi asjad välja näevad (body taust, h1-h6, button’id, lingid)
    • Block-spetsiifilised stiilid – eraldi seaded igale bloki-tüübile
    • Template parts – header, footer, jne registreerimine

    Üks theme.json-i seade võib mõjutada nii Block Editor’i UI-d kui ka avaldatud lehte. WordPress genereerib selle põhjal CSS muutujad ja Block Editor’i konfiguratsiooni automaatselt.

    Meie projekti disainisüsteem

    Figma’st tõime üle 38 muutujat nelja kategooriasse:

    Värvid (11 tk) – settings.color.palette

    Mitte kasutame “Background”, “Text”, “Accent” – vaid täpsemad nimed: bg-default, bg-gray, bg-dark, text-default, text-muted, text-light, text-inverse, accent-default, border-default, border-strong, placeholder. Iga slug muutub CSS muutujaks: var(--wp--preset--color--bg-default).

    Vahed (10 tk) – settings.spacing.spacingSizes

    Spacingute skaala mahajääb xs-ist (4px) kuni xxxxxxl-ini (96px). Suuremad väärtused (xl ja edasi) on tehtud fluid’iks CSS clamp() funktsiooniga:

    { "slug": "xxxxxxl", "size": "clamp(40px, 3vw + 16px, 96px)" }

    Tulemus: mobile-vaates 40px, desktop’is 96px, vahepeal sujuv üleminek. Mida väiksem spacing, seda väiksem muutus – UI-tihendid (4-16px) jäävad fikseerituks, sektsiooni-padding’ud (32px+) kahanevad mobiilis. Üks padding-väärtus, töötab kõigil ekraanidel.

    Fondi-suurused (12 tk) – settings.typography.fontSizes

    Sarnaselt spacingule: xs (12px) → xxxxxxxl (56px). Samuti fluid clamp() väärtustega. Vaikimisi seadame Inter-perekonna ja line-height’i relaxed (1.6).

    Raadiused (4 tk) – settings.custom.radius

    sm (4px), md (6px), lg (8px), pill (999px). Custom muutujad on tarbitavad var(--wp--custom--radius--md) kaudu.

    Õppetund: slug ei tohi alata numbriga

    Ehitamise käigus jooksime kokku ühe peidetud lõksuga. Algselt olid font-size slug’id numbri-prefiksiga: 2xl, 3xl, 5xl, 7xl – Tailwind’i stiilis. Aga frontend’is jäid kõik h1, h2, h3 ja paragraafid täpselt ühe suurusega (14px).

    Põhjus

    WordPress normaliseerib slug’i CSS muutuja nimes: kui slug algab numbriga ja siis tuleb täht, lisatakse sidekriips:

    theme.json slug:  "5xl"
    WP CSS muutuja:   --wp--preset--font-size--5-xl    (sidekriipsuga!)

    AGA: kui sa kasutad seda muutujat styles.elements.h2-s nii:

    "fontSize": "var(--wp--preset--font-size--5xl)"

    …siis WordPress ei normaliseeri seda viidet. Tulemus: muutuja, millele h2 viitab, ei eksisteeri. Brauser kasutab fallback’i (body font-size = 14px). Kõik pealkirjad jäävad 14px.

    Lahendus

    Vältida numbri-prefiksiga slug’e. Asendasime kõik vormid mitme x-iga:

    Vana slugUus slugSuurus
    2xlxxl24px
    3xlxxxl28px
    4xlxxxxl32px
    5xlxxxxxl40px
    6xlxxxxxxl48px
    7xlxxxxxxxl56px

    Sama lõksu märkasime varem ka spacing’utes – sealgi 2xl-vormid ei töötanud, ja xxl-vorm lahendas selle. Niisiis: kogu projektis ühtne reegel – slug ei algagi numbriga.

    theme.json kihiline süsteem

    Üks oluline mõiste mõista: theme.json-il on kolm “kihti”, mille väärtused omakorda kombineeruvad:

    1. WordPress core – vaikimisi värvid, fondid, vahed (sa võid need vaikimisi välja lülitada defaultPalette: false jne kaudu)
    2. Teema theme.json – see, mida meie defineerime
    3. Kasutaja kohandused – kui kasutaja muudab Site Editor’is Styles’i

    Hilisem kiht võidab varasema. Meie näiteks lülitame välja WordPress’i vaikimisi värvi-paleti, sest see segab Figma disainisüsteemi. Selleks: "defaultPalette": false.

    Mida theme.json EI tee

    • Ei sisalda templates’eid (need on templates/*.html failid)
    • Ei sisalda patterneid (need on patterns/*.php failid)
    • Ei sisalda CPT-d (need lähevad plugin’isse)
    • Ei sisalda dünaamilist loogikat (PHP – see on functions.php)

    theme.json on ainult deklaratiivne konfiguratsioon: “millised väärtused on, kuidas vaikimisi näevad”. Kogu ülejäänud loogika elab teistes failides.

    Edasi: arhitektuuri-otsused

    Järgmises postituses (Projektipäevik #2) räägime laiematest arhitektuuri-otsustest: kus CPT-d elavad (plugin vs teema), miks valisime page-by-page lähenemise, ja kuidas dokumenteerime kogu protsessi.