Digi4 — Agency Website & CMS
Website, CMS and security: Digi4 agency's complete digital ecosystem.
- 0
- SQL injection found
- 1
- Stored XSS fixed
- 71
- Repository commits
The challenge
Digi4, a Moroccan digital agency, needed a marketing site capable of presenting its services, case studies and team in both French and English, without relying on a generic theme or an external CMS that was hard to extend. The brief called for language-prefixed URLs, careful SEO (structured data, metadata, sitemap), and an admin area letting non-technical staff publish content, blog posts and quote requests, all while enforcing strict role- and module-level access control.
The solution
Saad designed and built a complete ecosystem: an Angular 19 SSR frontend (port 4400) consuming a unified Node.js/Express API (port 3400) that exposes read-only public routes and authenticated private routes, plus a separate Angular 19 admin SPA (port 4401, Tailwind v3) for content management by non-technical teams.
- Bilingual FR/EN content via dedicated i18n tables and ngx-translate, with SSR-safe state transfer
- Granular RBAC (project, module, action) resolved through roles with per-user overrides
- JWT authentication (bcryptjs, passport-jwt), image upload and processing (multer, sharp)
The results
The project underwent a dated internal security audit covering SQL injection, the file-upload pipeline, XSS, CSRF and SSR rendering. The audit confirmed no query was vulnerable to SQL injection despite multipleStatements being enabled at the MySQL connection level, a risk pattern identified and neutralized. One High-severity issue was found: a mislabeled upload (GIF/SVG) could trigger stored XSS; it was fixed, along with several Medium and Low findings. The bilingual SSR architecture and the custom-built analytics system were also delivered and verified.
Methodology and project management
Development was concentrated into roughly one month of focused work in July 2026 (67 of the repository's 71 commits), following earlier scaffolding and technical groundwork laid in spring. The architecture itself evolved: an initial attempt with the Directus headless CMS was abandoned in favor of a custom Express/MySQL/Angular stack, judged better suited to the level of control needed over RBAC and SEO. In the interest of right-sizing complexity, a multi-tenant scheme (federation_id) and a separate file microservice with HMAC authentication, both present in a reference architecture under study, were deliberately replaced with simpler single-tenant, in-process equivalents matching the project's real scale.
Technical architecture and performance
The architecture runs on a unified Node.js/Express API backed by MySQL 8 (a callback-mode mysql2 pool), with JWTs signed using a per-user secret (a server key combined with the password hash), which automatically invalidates a user's active sessions on password change. Cookies are HttpOnly, Secure and SameSite=Strict, a revocable token set is kept server-side, and an X-Requested-With header is required on every mutating request as CSRF defense. The custom analytics system writes raw events then pre-aggregates them hourly via a scheduled job, a design intended to sustain tens of millions of events per month.