Pradinė situacija
mdu.lt – žurnalas, parduotuvė, mokymų platforma ir narystės klubas viename. Viskas veikė ant WordPress: straipsniai, WooCommerce parduotuvė, mokymų įskiepis su pamokomis ir testais, narysčių įskiepis, prenumeratų įskiepis ir vertimų įskiepis trims kalboms. Kiekviena kalba turi savo domeną: lietuviška versija – mdu.lt, angliška – mind.university, rusiška – ru.mind.university.
Tokia sąranka laikui bėgant tapo trapi. Kiekviena dalis turėjo savo duomenų modelį ir savo pirkimo kelią: mokymai pirkti vienu paspaudimu be krepšelio, narystės skirtos rankiniu būdu, o fizinės prekės gyveno atskirai. Vienas lankytojas galėjo turėti kelias atskiras tapatybes. Dauguma vertimų nebuvo susieti tarpusavyje, todėl kalbos perjungiklis dažnai vedė į titulinį puslapį, o ne į to paties turinio vertimą.
Trumpai. WordPress su dešimtimis įskiepių pakeitėme viena Next.js ir PostgreSQL sistema: straipsniai, mokymai, parduotuvė, narystės ir paskyros dabar turi vieną duomenų modelį, vieną krepšelį ir vieną prisijungimą trimis kalbomis. Seni adresai išsaugoti arba nukreipti 301.
Architektūra ir technologijos
Rinkomės Next.js (App Router) su React ir TypeScript bei PostgreSQL duomenų bazę. Priežastys praktiškos:
- Serverio pusės atvaizdavimas. Turinys, kurį mato tik nariai, filtruojamas duomenų bazės užklausos lygmenyje. Užrakinto straipsnio ar pamokos tekstas į naršyklę iš viso nepatenka – tai ne CSS paslėptas blokas.
- Viena duomenų bazė visam projektui. Prekės, mokymai, narystės lygiai, užsakymai, pamokų progresas, sertifikatai ir naujienlaiškis yra lentelės toje pačioje bazėje, todėl paieška, paskyra ir administravimas mato viską kartu.
- Trys domenai, vienas kodas. Kalba nustatoma pagal domeną, kiekvienas puslapis turi savo adresą kiekviena kalba, o hreflang žymos ir kalbos perjungiklis veda į tikrą vertimą.
- Krepšelis ir mokėjimai – per mr.lt. Tai mūsų pačių komercijos platforma, kuri jau aptarnauja mūsų projektų krepšelius ir rezervacijas. Svetainė pati kortelių duomenų nemato.
- Vaizdo pamokos transliuojamos per vaizdo platformą su pasirašytomis, laike galiojančiomis nuorodomis, kad pamokos nuoroda neveiktų be prieigos.
Ką sukūrėme
Žurnalas ir paieška
Perkėlėme 994 straipsnius (LT 834, EN 93, RU 67) su kategorijomis, autoriais ir paveikslėliais. Sukūrėme kategorijų, autorių ir paieškos puslapius. Paieška vienu metu ieško straipsniuose, mokymuose ir parduotuvėje, o rezultatus rodo skirtukais su kiekiais. Straipsnio apačioje sistema pati parenka susijusius mokymus ir prekes pagal teksto temą – tai paprastas tf-idf palyginimas su redaguojamu raktažodžių žodynu, be jokio išorinio modelio.
Mokymų platforma
Mokymų įskiepį pakeitėme sava platforma: 35 seminarai, 990 pamokų, 22 testai su 73 klausimais. Yra pamokų eiliškumas, progreso juosta, testų vertinimas serveryje ir sertifikatai. Kiekvienam seminarui galima nustatyti nemokamų peržiūros pamokų skaičių, o anoniminio lankytojo progresas išsaugomas slapuke ir neprarandamas užsiregistravus. Perkeltas ir istorinis pamokų progresas, o seminarą anksčiau baigę dalyviai sertifikatus gavo atgaline data.
Parduotuvė ir krepšelis
Vietoj trijų atskirų pirkimo kelių sukūrėme vieną prekių modelį: fizinė prekė, seminaras, narystė ir renginio bilietas yra tos pačios lentelės įrašai su savo tipu. Katalogas sinchronizuojamas su mr.lt pagal SKU, o mokėjimo patvirtinimas grįžta pasirašytu webhook'u ir automatiškai atveria prieigą: seminarą, narystę ar bilietą. Pirkti galima ir be paskyros – užtenka el. pašto. Pirkinys prie paskyros prijungiamas tik patvirtinus tą el. pašto adresą. PVM skaičiuojamas pagal pirkėjo šalį, o prekė be kainos automatiškai tampa neparduodama: nėra pirkimo mygtuko, struktūrizuotuose duomenyse nėra pasiūlymo.
Narystės
Penki narystės lygiai turi rangą, o kiekvienas straipsnis ar seminaras – minimalų reikalaujamą rangą. Narys savo paskyroje mato galiojančią narystę, gali išjungti automatinį pratęsimą, pakeisti kortelę ar planą. Esamų narių pasikartojantys mokėjimai perkelti į naują sistemą taip, kad kitas nurašymas įvyktų ta pačia data ir ta pačia suma kaip anksčiau.
Viena paskyra trims domenams
Narys turi vieną paskyrą visose trijose kalbose. Prisijungus viename domene, vienkartinis dviejų minučių bilietas perduoda sesiją į kitą domeną, todėl jungtis tris kartus nereikia. Nupirktas lietuviškas seminaras atrakina ir jo anglišką bei rusišką versijas, o paskyroje rodomas vienas įrašas. Atsijungus sesija nutraukiama iškart visuose domenuose, nes sesijos saugomos duomenų bazėje, o ne savarankiškuose žetonuose.
Dinaminiai įrankiai ir testai
Atskira projekto dalis – įrankiai, kurie generuoja puslapius iš duomenų ir skaičiavimų, o ne iš rankomis rašyto teksto. Mėnulio fazės ir kalendoriai skaičiuojami astronominiu algoritmu vietoje, geomagnetinio aktyvumo puslapiai remiasi viešais NOAA kosmoso orų duomenimis, istorijos įvykiai dienai – viešu Wikimedia API, saulėtekis ir saulėlydis – pagal Lietuvos miestus. Šalia jų veikia datos skaičiuoklės, kvėpavimo laikmatis su garso signalais, tonų ir triukšmo generatoriai naršyklėje, emocijų ratas, gyvenimo rato ir ikigai testai, sapnų žodynas ir vardų žinynas. Visi turi bendrą įrankių centrą su piešiniu ir trumpu aprašu kiekvienam įrankiui, o kai kurie turi mokamą išsamesnę versiją, perkamą per tą patį krepšelį.
Administravimas
Administravimo zona prieinama tik administratoriaus rolei: apžvalga, nariai ir jų narystės, užsakymai, klientai, prekių likučiai, CSV eksportas. Kiekvienas administratoriaus veiksmas įrašomas į audito žurnalą. Toje pačioje zonoje veikia naujienlaiškis su dvigubu patvirtinimu, kampanijų siuntimo eile ir atidarymų bei paspaudimų sekimu, taip pat renginių registracija su bilietais.
Migracija ir duomenys
Svarbiausias reikalavimas – nieko neprarasti: nei turinio, nei paskyrų, nei paieškos pozicijų.
- Turinys eksportuotas tikromis WordPress funkcijomis, o ne rankiniu SQL, ir importuotas idempotentiškais skriptais, kuriuos galima paleisti pakartotinai. Prieš perjungimą perkėlėme ir paskutinių dienų naujus įrašus.
- Vertimų ryšiai šaltinyje buvo nepatikimi, todėl seminarų vertimų grupes sutikrinome pagal turinį ir susiejome iš naujo – dabar kalbos perjungiklis veda į tą patį seminarą kita kalba.
- Paskyros perkeltos kartu su slaptažodžių maišos reikšmėmis. Naujausios WordPress versijos slaptažodį prieš bcrypt dar apdoroja HMAC-SHA384, todėl paprastas bcrypt palyginimas neveikia. Įgyvendinome tą patį algoritmą, todėl nariai jungiasi senu slaptažodžiu be priverstinio keitimo, el. paštu arba senuoju vartotojo vardu.
- Medija. Visi paveikslėliai parsiųsti iš seno serverio, sumažinti iki 1600 px, išvalyti nuo EXIF ir perrašyti duomenų bazėje bei straipsnių HTML. Nė vienas paveikslėlis nebeprikabintas prie seno saito.
- Adresai. Kur buvo įmanoma, palikome tą pačią URL struktūrą, net pamokų kelius. Kitiems sudarėme nukreipimų žemėlapį: 264 puslapių ir 1 321 medijos failo 301 nukreipimą (prekės, testai, kategorijos, puslapiai, senos nuotraukos).
Perjungimas be prastovos
Nauja sistema iki DNS perjungimo veikė atskirame adrese su tikrais duomenimis, todėl perjungimo dieną liko tik pakeisti DNS įrašus, perregistruoti mokėjimų webhook'ą, persinchronizuoti katalogą ir perkelti paskutinių dienų skirtumą.
Greitis, SEO ir struktūra
Kiekvienas puslapis turi kanoninį adresą, hreflang žymas trims domenams, Open Graph ir struktūrizuotus duomenis (straipsniams, prekėms, DUK). Dalinimosi paveikslėliai skaičiuoklėms ir įrankiams piešiami serveryje kiekvienam puslapiui atskirai. Kiekvienas domenas turi savo sitemap'ą, naujienų sitemap'ą ir RSS srautą. Sitemap'uose 2026-10-06 buvo 5 645 adresai: mdu.lt – 2 819, mind.university – 1 432, ru.mind.university – 1 394.
Dėl greičio: statiniai failai ilgai kešuojami, paveikslėlių kešas – 30 dienų, šriftai neužkraunami iš anksto be reikalo, o analitikos skriptai įkeliami tik po puslapio įkėlimo. Puslapių HTML sąmoningai nekešuojame. Kiekvienas puslapis atvaizduojamas atsižvelgiant į lankytojo narystę, todėl bendras kešas galėtų vienam lankytojui parodyti kitam skirtą užrakintą turinį. Pasirinkome saugumą, o greitį kompensuojame serverio pusėje.
Rezultatas
| Sritis | Buvo | Dabar |
|---|---|---|
| Pirkimas | Trys atskiri keliai, narystės skiriamos rankiniu būdu | Vienas krepšelis prekėms, seminarams, narystėms ir bilietams, prieiga atsiveria automatiškai |
| Paskyra | Atskiros tapatybės skirtingose dalyse | Viena paskyra trims domenams su bendra seminarų prieiga |
| Kalbos | Dauguma vertimų nesusieti | Kalbos perjungiklis veda į tikrą vertimą, hreflang visur |
| Turinys | Statiniai straipsniai | Straipsniai ir duomenimis grįsti puslapiai, atsinaujinantys kasdien |
| Valdymas | Dešimtys įskiepių ir jų atnaujinimai | Vienas kodas, audito žurnalas, savas naujienlaiškis |
Pirmas commit'as padarytas 2026-09-16, DNS perjungtas 2026-09-23. Iki 2026-10-06 repozitorijoje – 550 commit'ų: sistema vystoma toliau kasdien, o ne „atiduodama ir pamirštama“.
Ką iš to galite pritaikyti savo verslui
- Migracija be pozicijų praradimo – senų adresų auditas, nukreipimų žemėlapis ir nauja sistema, išbandyta su tikrais duomenimis dar prieš perjungimą.
- Vienas krepšelis viskam – jei parduodate ir fizines prekes, ir kursus, ir prenumeratas, jiems nereikia trijų atskirų sistemų.
- Narių turinys, kuris tikrai užrakintas – filtravimas serveryje, o ne paslėptas blokas puslapyje.
- Paskyrų perkėlimas be slaptažodžių keitimo – klientams nereikia nieko daryti po perkėlimo.
- Dinaminiai puslapiai iš viešų duomenų – šimtai naudingų, kasdien atsinaujinančių puslapių, kurie atveda paieškos srautą ir patys susieja jį su jūsų produktais.
- Kelios kalbos ant atskirų domenų su viena paskyra ir teisingais hreflang ryšiais.





