Înapoi la portofoliu
WebappStudiu / personal

CMS Sections

Mini-CMS construit cu Laravel, Inertia și Vue pentru crearea paginilor din blocuri configurabile, ordonare drag-and-drop, upload de imagini și randare publică optimizată prin cache și încărcare lazy a secțiunilor.

CMS Sections

Stack principal

PHP 8.2
Laravel 12
Eloquent ORM
Laravel Breeze
Inertia.js 2Vue 3TypeScriptTailwind CSS 3Vite 6vuedraggableSQLiteLaravel CacheLaravel FilesystemZiggyPHPUnit 11

Provocarea

Provocarea a fost proiectarea unui editor suficient de generic încât paginile să poată combina secțiuni foarte diferite fără câte un model și formular separat pentru fiecare tip, păstrând în același timp ordinea, editarea nested, uploadurile de imagini și randarea publică predictibilă.

Soluția

Soluția folosește un registry TypeScript ca sursă pentru schema editorului, PageSection cu content JSON pentru persistarea payload-ului specific fiecărui bloc și o mapare section_type → componentă Vue pentru randare. Editorul normalizează valorile implicite, gestionează repeatere și imagini, reordonează secțiunile cu vuedraggable, iar backendul salvează pagina și structura secțiunilor într-o tranzacție. PublicPageController pregătește și cache-uiește pagina, iar frontendul încarcă async secțiunile non-hero.

Complexitate notabilă

CMS Sections este un proiect personal de studiu construit ca un page builder compact peste Laravel 12, Inertia.js 2 și Vue 3. În locul unui model rigid de pagină, conținutul este compus din secțiuni ordonate, fiecare având un tip și un payload JSON. Un registry TypeScript definește schema de editare pentru fiecare tip, iar aceeași cheie de tip este folosită de frontendul public pentru alegerea componentei Vue corespunzătoare.

Editorul permite crearea paginilor cu titlu și slug unic, marcarea unei singure pagini ca home, adăugarea secțiunilor dintr-un catalog, editarea conținutului într-un modal și reordonarea prin drag-and-drop. Registry-ul confirmă 11 tipuri de secțiuni: hero, carousel, features, testimonials, team, pricing, FAQ, CTA, statistics, gallery și contact. Câmpurile pot fi text, textarea, imagine sau repeatere recursive, ceea ce permite structuri precum slide-uri, planuri de preț, membri de echipă, întrebări FAQ și galerii fără câte un formular hardcodat separat pentru fiecare secțiune.

Persistența folosește două entități principale: Page și PageSection. Page păstrează metadata de bază, iar PageSection leagă pagina de tipul secțiunii, ordinea ei și conținutul JSON. La salvare, actualizarea paginii și înlocuirea setului de secțiuni sunt executate într-o tranzacție, astfel încât structura paginii să nu rămână parțial actualizată dacă apare o excepție. Este o abordare simplă și potrivită pentru un proiect de studiu, cu compromisul că secțiunile sunt recreate la fiecare salvare și nu există istoric de versiuni sau optimistic locking.

Media este gestionată printr-un endpoint autentificat de upload. Imaginile sunt validate ca fișiere image de maximum 2 MB, primesc nume randomizate și sunt salvate pe disk-ul public Laravel; URL-ul rezultat este injectat în conținutul secțiunii. Acest flux este folosit inclusiv în câmpurile nested din repeatere.

Frontendul public rezolvă pagina home sau pagina după slug și cache-uiește payload-ul pregătit timp de 10 minute. Cache-ul este invalidat explicit după editare și poate fi curățat manual din zona de administrare. Hero-ul este încărcat eager, iar celelalte componente de secțiune folosesc defineAsyncComponent și IntersectionObserver pentru a fi montate când se apropie de viewport. Galeria include lightbox și navigare din tastatură, carousel-ul și testimonials au autoplay, iar componentele publice folosesc layout responsive și stiluri Tailwind.

Autentificarea provine în mare parte din Laravel Breeze: register, login, resetare parolă, verificare email și profil. Funcționalitatea CMS personalizată se află în modelele Page/PageSection, controllerele de pagini și upload, registry-ul de secțiuni, editorul Vue, componentele publice și logica de cache/randare.

Scope-ul repository-ului rămâne de prototip/studiu. Nu există versionare de conținut, status draft/published pe pagini, preview separat de pagina live, management SEO, policies/roluri editoriale sau pipeline CI/CD. Formularul din secțiunea Contact simulează submit-ul doar în browser, iar harta este un placeholder pentru o integrare Maps neconfigurată. Din acest motiv proiectul este prezentat ca un page builder funcțional și extensibil, nu ca un CMS production-ready.

Rezultate cheie

  • Catalog configurabil cu 11 tipuri de secțiuni reutilizabile pentru pagini publice
  • Editor de pagini cu adăugare, editare, eliminare și reordonare drag-and-drop a secțiunilor
  • Persistență generică a conținutului pe PageSection prin JSON și ordine explicită
  • Suport pentru câmpuri nested/repeater folosite de carousels, pricing, FAQ, echipă, testimoniale și galerii
  • Upload autentificat de imagini cu validare Laravel și stocare pe disk-ul public
  • Rutare publică pentru home page și pagini accesibile prin slug unic
  • Cache de pagină cu TTL de 10 minute, invalidare după editare și acțiune manuală de clear cache
  • Încărcare lazy a componentelor publice non-hero cu defineAsyncComponent și IntersectionObserver
  • Componente interactive pentru carousel, testimonials, FAQ și galerie cu lightbox
  • Build frontend cu TypeScript typecheck, Vite și bundle SSR Inertia configurat

Proiecte asemănătoare

Vrei ceva similar?

Începe cu wizard-ul de estimare — răspunzi la câteva întrebări și primești un range de preț + timeline realist.