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.