Work project
Landing Page Deployment Platform
A push to a landing page, and the page live without restarting anything
The infrastructure that publishes, watches and maintains 100+ landing pages for several clients on one VPS, without restarting anything on each deployment.


What it is about
The agency publishes its clients' landing pages under each client's domain, one path per program or campaign. This platform is everything between a push to a landing page and the live page, from the build and the publication to the server and the monitoring.
The landing pages are edited with a visual builder or by hand, and both paths end in the same workflow.
What it does
- Each landing page calls a reusable GitHub Actions workflow that installs, builds, checks the base path, gzips the files, generates WebP images and uploads the result with rsync in two phases.
- The deployment logs in as a user without a shell, confined with rrsync and with a pinned host key, and each client's Nginx mounts its landing pages read-only.
- A single Nginx block serves any registered landing page, with assets immutable for a year, uncached HTML, WebP by negotiation and the Google Tag Manager tags injected on the server.
- Scripts that apply one change to all 106 repositories (deploy workflow, Dependabot policy, environment files) and generate each client's Nginx configuration.
- A daily monitor checks HTTP status, the HTML, a single Google Tag Manager tag, compression, caching, pending deployments and certificates, and opens an issue when something fails; Lighthouse measures the main landing pages every week.
- Commit markers to push without deploying, and documented rollback paths for a landing page, for a client's Nginx and for the repositories' history.
How it works
From push to live page
Every change goes from the repository to GitHub Actions and from there to the VPS; the bottom row watches all of it.
Repositories
- 106 landing pages in React and Vite
- Changes from a visual builder or by hand
- A minimal workflow in each landing page
GitHub Actions
- Install, build and base path
- gzip and WebP
- Two-phase rsync with a restricted user
VPS
- One Nginx per client in Docker
- Landing pages mounted read-only
- Google Tag Manager injected on the server
Monitoring
- Daily monitor that opens issues
- Weekly Lighthouse
- Documented rollback paths
Decisions and their costs
Publish files instead of images
If each landing page traveled inside an image, publishing it would mean rebuilding the image and restarting the container.
A confined deploy user
The credential CI deploys with could leak.
The HTML is never precompressed
Google Tag Manager is injected on the server with sub_filter, which does not work on files that are already compressed.
Stack
Pick a technology to see the projects that use it.



