Skip to content
← Work01 ·Client project

Connect

Platform and release pipeline for a law firm

A bilingual site for a Lviv law firm that its team runs itself, and everything under it: Payload inside the Next.js app, Docker on the firm's own Lightsail, Terraform, and a one-command release that audits the exact image it ships and rolls back in seconds.

Role
Full-stack engineer: design, implementation, CMS, infrastructure, deployment
Years
2025 – 2026
Built by
Alone, design included
commits
140
tests
~54
prerendered routes
45
Lighthouse mobile, home
97
SEO, 9 of 10 pages
100
hosting / month
~$7

Source: the Connect repository, measured during the phase 2 audit (§2).

§ 01Editable by the firm, never rendered late

The firm edits its own pages in Payload, which runs inside the same Next.js app. Pages are prerendered from the database at build time, so a visitor never waits on the CMS.

§ 02What runs where

The firmedits in Payload
Next.js + PayloadDocker on Lightsail · Caddy
SQLite / Tursomigrated before build
S3 + CloudFrontmedia · invalidated by tag
Terraform · two workspaces
Fig. 1 · Connect: one long-lived process on the firm's own AWS, provisioned by Terraform in two workspaces.

§ 03Five decisions, written down

  1. 01
    One long-lived process, on purpose

    In-process cache invalidation breaks on serverless or across instances.

  2. 02
    Migrations before the build

    The build prerenders from the database, so migrations stay additive and a destructive change ships in two releases.

  3. 03
    Audit the image that ships

    The checks run against the exact Docker image that goes to the server.

  4. 04
    Images over SSH, not a registry

    Lightsail has no instance role, so no IAM keys live on the server.

  5. 05
    Fingerprint content around a deploy

    If content changed during the release, the cache is purged.

§ 04One command to release

migrate
build image
audit image
ship over SSH
rollback ready
Fig. 2 · The release script. Lighthouse runs locally against the build; it is not a pipeline step.

§ 05Invalidating by tag

Payload hooks invalidate the cache by tag when content changes, so an edit shows on the next request. A daily rebuild is the backstop.

§ 06Built to be found

Every page is in the sitemap and has a Markdown twin. llms.txt and llms-full.txt give language models the whole site in one read. OG images are generated per page, and Ukrainian and English each have their own URLs. SEO scores 100 on 9 of 10 pages on mobile.

Connect on a desktop screen
Connect on a phone
The site refuses framing, so the preview is a poster.Open site ↗
“We needed a site that looks as serious as our practice. Ivan handled the design, the build and the launch, and the team updates the content without calling anyone. Communication was clear the whole way through.”
Managing Partner · Connect