Preskoči na sadržaj

Naš redesign proces (Custom WordPress)

Za potrebe našeg tima trebao nam je novi website kao landing page za naše web development usluge, blog funkcionalnost i LMS (learning menagment system) za naše kurseve. Naravno, najbolji alat za ovaj projekat je bio WordPress.

Kada se kaže “WordPress sa online kursem”, mnogi odmah pomisle na neku generičnu temu i gotov LMS plugin. Naš je pristup drugačiji: klasični WordPress sajt (stranice, meni, custom tema) proširen je custom pluginom koji dodaje kompletan “academy” sloj: kurs, lekcije, progres, zaključavanje lekcija i prikaz dashboarda, dok je login riješen preko provjerenog social login plugin-a.

Ovaj pristup daje dvije velike prednosti:

  • Sajt ostaje “standardan WordPress” (teme, stranice, editor, SEO), a kurs logika je izolovana u pluginu.
  • Academy dio se može razvijati i mijenjati bez mijenjanja teme, i bez vezivanja za teške LMS ekosisteme.

U nastavku je objašnjeno kako su povezani tema, stranice i plugin, i kako teče korisnički flow.


Arhitektura: tema radi “marketing”, plugin radi “academy”

1) Custom tema (ili prilagođena tema)

Tema služi za:

  • javne stranice: Home, About, Services, Blog…
  • UI/branding: header, footer, tipografija, globalni stil
  • “landing” stranicu kursa (/kurs/) koja je obična WP page i uređuje se kroz Block Editor

Tema uređuje design i layout cijele web stranice da i sve bilo konzistentno. Tema ne mora znati ništa o “lekcijama”, progresu ili zaključavanju kursa. To sve radi plugin.

2) Custom plugin: “SynergyAcademy”

Plugin implementira:

  • Custom Post Types (Course i Lesson)
  • relaciju lekcija → kurs (preko meta polja)
  • rute za “academy” sekciju (npr. /academy/<kurs>/ i /academy/<kurs>/lesson/<lekcija>/)
  • server-side render dashboarda i lekcija (koristi theme header/footer, ali “content” generiše plugin)
  • progres (mark complete, % napretka)
  • sekvencijalno otključavanje lekcija

Ovo je klasičan pattern: tema je prezentacija sajta i uređivanje bloga, plugin je aplikaciona logika kursa.


Tema je “javni sloj” sajta: sve što korisnik vidi prije logina (home, navigacija, sadržajne stranice, landing za kurs), i okvir (header/footer) koji se koristi i kada plugin renderuje Academy dashboard/lekcije. WordPress to radi kroz template hijerarhiju: zavisno od tipa zahtjeva (page, post, archive…), WordPress bira najkonkretniji template fajl i fallbackuje do index.php.​

Struktura teme (šta gdje živi)

U klasičnoj (PHP) temi, najbitniji fajlovi su:

  • style.css (deklaracija teme + osnovni CSS)
  • functions.php (setup + registracija menija + enqueue CSS/JS)
  • header.php i footer.php (globalni layout; bitno je da imaju wp_head() i wp_footer() da bi pluginovi i tema mogli ubacivati skripte/stilove).​
  • Template fajlovi (front-page.php, page.php, single.php, archive.php, 404.php…) koje WordPress bira preko template hijerarhije.​

Ako je tema block-theme (Full Site Editing), onda umjesto header.php/footer.php često ima theme.json + templates/*.html + parts/*.html, gdje theme.json definiše globalne stilove, tipografiju, spacing, palete, i “template parts”.​

Kako tema služi landing stranici /kurs/

Naša/kurs/ stranica je običan WordPress Page, pa je tema tu zadužena za:

  • layout i grid (širine, spacing)
  • tipografiju, boje, dugmad
  • render glavnog sadržaja (poziv the_content() u page.php)
  • prikaz Nextend shortcode-a (Google login dugme), koji se renderuje unutar sadržaja stranice.​

Praktično: mi u editoru slažemo sekcije (hero, benefiti, FAQ…), a tema osigurava dosljedan dizajn kroz globalne stilove i CSS klase.

Kako tema “oblači” Academy plugin

Iako Academy dashboard i lekcije generiše plugin, naš plugin ih ubacuje između get_header() i get_footer() (što znači: tema i dalje daje okvir, meni, fontove, globalne skripte). To je dobar pattern jer Academy dio izgleda kao dio istog sajta, a ne kao “druga aplikacija”. template_redirect se koristi da se zahtjev presretne prije nego WordPress pokuša standardni template, a onda plugin sam renderuje sadržaj ali koristi teme header/footer.​

Stilovi: podjela odgovornosti (theme CSS vs plugin CSS)

Tipično imamo dva sloja CSS-a:

  • Theme CSS: globalni (body font, colors, header, footer, button sistem, spacing utiliti klase) i sve za marketing stranice.
  • Plugin CSS: namespace-ovan (npr. .sa ...) i pokriva isključivo Academy UI (kartice, progress bar, lista lekcija, QA sekcija).

Ovaj pristup minimizira konflikte: tema može mijenjati dizajn sajta, a Academy ostaje stabilan jer koristi svoje prefiksirane klase.

Primjer (ilustracija, ne produkcija):

css/* theme */
.btn { border-radius: 12px; }

/* plugin */
.sa .sa-btn { border-radius: 10px; }

U temi je meni “Kurs” normalno linkovan na /kurs/ (WP Page). Logika “ako je user ulogovan, ne ostaj na /kurs/ nego idi na academy dashboard” nije u temi nego u pluginu, jer je to aplikaciono pravilo. Ovaj redirect se najstabilnije radi u template_redirect (server-side), prije outputa.​

To daje čist UX:

  • guest klikne “Kurs” → vidi landing + Google login
  • logged-in klikne “Kurs” → odmah je na dashboardu kursa (outline + lekcije)

URL struktura i routing: “virtual pages” unutar WordPressa

Academy dio izgleda kao posebna aplikacija unutar WP-a, ali tehnički se i dalje izvršava kroz WordPress request lifecycle.

Tipični URL-ovi:

  • /kurs/ – landing page (WP Page)
  • /academy/<course-slug>/ – dashboard kursa (outline + lista lekcija)
  • /academy/<course-slug>/lesson/<lesson-slug>/ – prikaz lekcije

Da bi WordPress razumio ove URL-ove, plugin registruje rewrite pravila i query varove i presreće zahtjev prije nego što tema pokuša render standardni page template.

U blog postu je dovoljno znati:

  • WordPress dobije URL
  • plugin “prepozna” da je to academy ruta
  • plugin umjesto standardne WP stranice renderuje svoj view (ali i dalje koristi header/footer iz teme)

Content model: Course i Lesson kao custom post types

Kurs (Course)

Kurs je jedan “glavni” entitet. On ima:

  • naslov (ime kursa)
  • thumbnail/cover (slika kursa)
  • excerpt ili content (kratki opis i/ili outline)

Lekcija (Lesson)

Lekcije su zasebni postovi koji imaju:

  • naslov i sadržaj
  • meta polje koje kaže kojem kursu pripada (_sa_course_id)
  • meta polje za redoslijed (_sa_order)
  • opcionalno meta polja poput “procijenjeno vrijeme” ili “YouTube link”

Ovaj model je fleksibilan:

  • lekcije se uređuju kao WP postovi
  • može se dodavati više kurseva ili mijenjati redoslijed bez promjene koda

Progres: kako se pamti “mark as complete”

Progres se čuva per-user, najčešće u usermeta tabeli:

  • ključ tipa sa_progress_<course_id>
  • vrijednost je lista ID-eva lekcija koje su završene (npr. JSON array)

Kada korisnik klikne “Završi lekciju”:

  1. browser pošalje POST na custom action endpoint (npr. /academy/action/complete/)
  2. plugin validira nonce (sigurnost)
  3. upiše lesson_id u user meta
  4. odluči gdje da redirecta:
    • ako postoji sljedeća unlocked lekcija → ide tamo
    • ako je zadnja lekcija → vraća na dashboard/outline

Ovo je važan UX detalj: na zadnjoj lekciji “complete” treba vratiti na outline, ne na istu lekciju.

Primjer pseudo-koda (ilustracija):

phpif (has_next_lesson()) {
  redirect(next_lesson_url);
} else {
  redirect(course_dashboard_url);
}

Zaključavanje lekcija: sekvencijalni unlock

Sistem je “sequential”:

  • prva lekcija je uvijek dostupna
  • svaka naredna se otključava tek kada je prethodna završena

Logika se zasniva na _sa_order i listi completed lekcija:

  • pronađe se “prethodna” lekcija
  • ako je prethodna u completed listi → current je unlocked

Ovaj pristup je jednostavan i robustan, i može se kasnije proširiti (drip, datumi, kvizovi, uslovi itd.).


Login: zašto je Google login prebačen na Nextend

Prvobitno se razmatralo da plugin ima vlastiti Google OAuth flow, ali se u praksi pokazalo da:

  • custom OAuth endpointi u WordPressu često upadnu u konflikte sa rewrite pravilima, redoslijedom ruta, i cachingom
  • na shared hostingu i uz caching (LiteSpeed) OAuth callback i redirecti znaju praviti “čudna ponašanja”

Zato je praktičnije i stabilnije koristiti provjeren plugin:

  • Nextend Social Login odradi OAuth proces sa Google-om
  • plugin automatski kreira WP user nalog pri prvom login-u (ako se uključi membership u Nextend-u)
  • login proces radi i za guest korisnike bez custom ruta

Ključni detalj:

  • Nextend shortcode se prikazuje samo korisnicima koji nisu ulogovani (zato se u adminu ili kad si ulogovan dugme ne vidi).

Flow korisnika: “Guest ide na /kurs/, logged-in ide na /academy/”

Ovo je najvažniji dio UX-a:

1) Guest korisnik

  • klikne “Kurs” u meniju → ide na /kurs/
  • vidi Google login dugme
  • nakon logina treba da završi na dashboardu kursa

2) Ulogovan korisnik

  • klikne “Kurs” u meniju → ne smije ostati na /kurs/
  • automatski se preusmjerava na /academy/<course>/

Ovaj redirect je najstabilnije raditi u template_redirect (server-side, prije outputa), a ne u shortcode-u.

Primjer pseudo logike:

phpif (is_page('kurs') && is_user_logged_in()) {
  redirect(academy_dashboard_url);
}

Cache i “nsl_bypass_cache” parametar

Kod social login-a često postoji problem: cache može servirati “guest” verziju stranice i nakon što se user uloguje.

Zato Nextend ponekad dodaje parametar poput nsl_bypass_cache=... kako bi URL bio “unikatan” i zaobišao keširani HTML.

To je normalno i uglavnom nije greška, samo mehanizam da se login stanje pravilno reflektuje na frontendu.


Admin bar i wp-admin: “student” korisnici ne trebaju WordPress backend

Za kurs korisnike je obično cilj:

  • da nikad ne vide WordPress admin bar
  • da nemaju pristup wp-admin

To se rješava na nivou plugina ili malog snippet-a:

  • sakrije se admin bar za sve osim admina
  • blokira se wp-admin za non-admin

Primjer (ilustracija):

phpif (!is_admin_user()) {
  hide_admin_bar();
  block_wp_admin();
}

Zašto je ova kombinacija dobra

Ova implementacija je “lakša” od LMS-a, a mnogo prilagodljivija od klasičnih membership rješenja:

  • WordPress stranice i tema = marketing dio sajta
  • custom plugin = academy aplikacija (kurs, lekcije, progres)
  • Nextend = pouzdan Google login bez custom OAuth komplikacija

Ako se kasnije poželi:

  • više kurseva, više “academy” sekcija
  • napredniji Q&A, drip content, testovi
  • integracija plaćanja ili membership

… plugin se može proširivati postepeno, bez rušenja ostatka sajta.