Automating Full-Page Screenshots with Playwright in CI
9 min readHow I replaced manual landing-page screenshots with a weekly Playwright job that captures desktop and mobile views, then bundles them into a static archive site
How I replaced manual landing-page screenshots with a weekly Playwright job that captures desktop and mobile views, then bundles them into a static archive site
How I sped up CI and release pipelines for a large Next.js app: disabling inline ESLint and type checking in next build, running them as parallel jobs, linting only changed files, and fixing broken caches.
A Cloud Run service kept hitting its memory limit at startup. The cause: uv run re-syncs the environment by default, reinstalling the dev dependency group at runtime even though the image was built with --no-dev. The fix is --no-sync (and --no-install-project for better layer caching).
Moving the app off its default *.run.app URL onto a company subdomain with Cloud Run domain mappings: the domain-verification step the runbooks skip, why a zone apex takes A/AAAA records instead of a CNAME, why the cutover order matters when an OIDC audience is involved, and a 502 that looked like a broken deploy but was a TLS cert still propagating.
Making a Slack bot invite meeting participants to a Google Calendar event. Service accounts cannot add attendees without domain-wide delegation, so the bot authenticates as a real user via an OAuth refresh token and patches the event on that user's calendar copy, with a fallback that never blocks the submission.
Replacing an in-memory mock with local Postgres: Docker, a Drizzle schema and first migration, seeding, swapping the data layer, and designing for private-network cloud access.
A form sends a URL. The bot decides whether the page lives in a repo it can change, and if so it triggers a CI workflow where an AI coding agent makes a fixed, repetitive edit and opens a pull request, then reports back into the Slack thread. Covers classifying a page via the GitHub contents API, the reusable-workflow pattern, an AI agent in CI, and a secured callback.
A report form sends a URL. The bot normalizes the URL, looks it up in a master spreadsheet to find who owns that page, and @mentions them in-thread, with sensible fallbacks. Covers URL normalization, an efficient bottom-up sheet lookup, and Slack mention resolution including subteam groups.
How to stop a site full of short-lived pages from accumulating near-identical "this page has ended" entrypoints, using a data registry, one shared page, and a middleware rewrite.
Concrete gotchas from building the UI of a status-driven workflow tool on Next.js 16 and React 19: intercepting + parallel routes for modals, the React Hook Form + Zod typing trap with default values, gating a stepper by status and role, and pinning a gantt with the one legitimate inline-style exception.
My hobby recipe app got paused after 90 days of inactivity and could no longer be restored from the dashboard. Here is how I rescued the data from a backup and rebuilt the stack on platforms that do not freeze - swapping Supabase for Neon + Drizzle, Auth.js, and Vercel Blob.
Upgrading Swiper from v8 to v11 seems harmless until your carousels start thrashing the page. A deep dive into why loop mode broke, what loopAddBlankSlides actually does (nothing useful), and how to fix it with a wrapper component.
Adding deadline reminders to a workflow tool: a Cloud Scheduler → Cloud Tasks → worker pipeline, why IAM run.invoker was the wrong lock for a public SSO-gated Cloud Run app, verifying OIDC tokens in-app instead, making retries idempotent, computing Japanese business days without hardcoding holidays, and a Next.js standalone build trap with Google client libraries.
When Slack SSO works for staff but not guest accounts: adding Google sign-in as a gated fallback, re-keying users on email, preserving Slack mentions for users who never sign in with Slack, and enforcing who may use which door.
A new design draft and a fresh requirements list arrived mid-build. How I triaged them against priority, deferred the integration-heavy features without stalling, kept the plan doc as the source of truth, and decided the schema was finally stable enough to stand up the database.
Why I built the entire UI of an internal workflow tool before standing up Postgres, and how the mock layer worked: an in-memory store, MSW interception, Zod as the single source of truth, and a cookie-based mock session to exercise every role.
Migrating a custom-server Next.js app from Sentry v8 to v10: a server config that was never loaded, source map options that had been silently ignored since v8, a shared library shipping a second SDK copy, and the sendDefaultPii change.
A deep dive into how JVM handles memory management through garbage collection, its types, and best practices.
Designing monitors that detect only your service’s own failures, filtering out upstream noise.
Refined Datadog queries for ALB metrics, latency, unit handling, and rate computations: mistakes learned and correct patterns.