Parduotuvė, mokymai ir narystės

mdu.ltParduotuvė, mokymai ir narystės vienoje paskyroje

Žurnalą, parduotuvę, 35 seminarus ir narystės klubą trimis kalbomis perkėlėme iš WordPress su dešimtimis įskiepių į vieną sistemą: vienas krepšelis, viena paskyra trims domenams, nariai jungiasi senais slaptažodžiais.

Next.jsReactTypeScriptPostgreSQLmr.lt krepšelisBunny StreamBrevo
mdu.lt – pradžios puslapis
mdu.lt telefone
1krepšelis prekėms, mokymams, narystėms ir bilietams
990pamokų perkelta kartu su narių progresu
3kalbos ir domenai su viena paskyra
5narystės lygiai, atrakinantys turinį serveryje
Užduotis

Perkelti trijų kalbų žurnalą, parduotuvę, mokymus ir narystes iš WordPress į vieną sistemą, nieko neprarandant.

Projektas veikė ant WordPress su atskirais parduotuvės, mokymų, narysčių, prenumeratų ir vertimų įskiepiais. Kiekviena dalis turėjo savo pirkimo kelią, o dauguma vertimų nebuvo susieti. Reikėjo perkelti turinį, paskyras su slaptažodžiais, narystes ir pamokų progresą, išsaugoti senus adresus ir paieškos pozicijas. Kartu – sukurti vieną krepšelį visų tipų produktams ir vieną paskyrą trims kalbų domenams.

Ką padarėme
  • Perkėlėme 994 straipsnius, 35 seminarus su 990 pamokų ir 22 testais, istorinį progresą ir sertifikatus
  • Sukūrėme vieną prekių modelį ir krepšelį fizinėms prekėms, seminarams, narystėms ir bilietams per mr.lt su automatiniu prieigos suteikimu
  • Perkėlėme WordPress paskyras su slaptažodžiais: nariai jungiasi senu slaptažodžiu el. paštu arba vartotojo vardu
  • Įdiegėme penkių lygių narystę su turinio filtravimu serveryje ir nario savitarna paskyroje
  • Sujungėme tris kalbų domenus viena paskyra: prisijungimas perduodamas tarp domenų, seminaras atrakinamas visomis kalbomis
  • Sudarėme 264 puslapių ir 1 321 medijos failo 301 nukreipimų žemėlapį, visą mediją perkėlėme į savą saugyklą
  • Sukūrėme dinaminius modulius iš viešų duomenų ir skaičiavimų: mėnulio kalendorius, geomagnetinis aktyvumas, ši diena istorijoje, skaičiuoklės, garso generatoriai
  • Įdiegėme administravimo zoną su audito žurnalu, savą naujienlaiškį ir bendrą paiešką per straipsnius, mokymus ir parduotuvę
Išbandykite gyvai

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ų.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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

SritisBuvoDabar
PirkimasTrys atskiri keliai, narystės skiriamos rankiniu būduVienas krepšelis prekėms, seminarams, narystėms ir bilietams, prieiga atsiveria automatiškai
PaskyraAtskiros tapatybės skirtingose dalyseViena paskyra trims domenams su bendra seminarų prieiga
KalbosDauguma vertimų nesusietiKalbos perjungiklis veda į tikrą vertimą, hreflang visur
TurinysStatiniai straipsniaiStraipsniai ir duomenimis grįsti puslapiai, atsinaujinantys kasdien
ValdymasDešimtys įskiepių ir jų atnaujinimaiVienas 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.
DUK

Apie tokį projektą

Ar perkeliant iš WordPress prarasime Google pozicijas?

Rizika atsiranda, kai pasikeičia adresai be nukreipimų. Mes pirmiausia sudarome visų senų adresų sąrašą iš sitemap'ų, kur įmanoma išlaikome tą pačią URL struktūrą, o kitiems sukuriame 301 nukreipimus. Prieš perjungimą patikriname pavyzdžius iš kiekvieno puslapių tipo.

Ar klientams teks keisti slaptažodžius po migracijos?

Ne. Perkeliame slaptažodžių maišos reikšmes ir įgyvendiname tą patį tikrinimo algoritmą, kurį naudoja WordPress, todėl klientai jungiasi tuo pačiu slaptažodžiu ir net tuo pačiu vartotojo vardu.

Ar galima viename krepšelyje parduoti prekes, kursus ir prenumeratas?

Taip. Visi produktai yra vieno modelio įrašai su tipu, todėl krepšelis ir užsakymai bendri, o po apmokėjimo sistema automatiškai suteikia prieigą prie kurso ar narystės arba perduoda prekę siuntimui.

Kiek laiko trunka tokio masto perkėlimas?

Šiame projekte nuo pirmo commit'o iki DNS perjungimo praėjo septynios dienos, bet tai priklauso nuo turinio kiekio ir įskiepių skaičiaus. Svarbiausia, kad nauja sistema iki perjungimo veiktų su tikrais duomenimis atskirame adrese.

Kaip veikia kelios kalbos ant skirtingų domenų?

Vienas kodas aptarnauja visus domenus, kalba nustatoma pagal domeną, vertimai susiejami tarpusavyje, o paskyros sesija saugiai perduodama tarp domenų, kad lankytojui nereikėtų jungtis kelis kartus.

Kiti projektai

Reikia panašaus sprendimo? Migracija iš WordPress – su kaina ir terminais raštu.

Žiūrėti paslaugą
Savaitės suvestinė

DI kainos, Google atnaujinimai ir prekybos sezonai

Kartą per savaitę: kas pasikeitė DI, paieškoje ir el. prekyboje. Be triukšmo.