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
21 posts tagged Python
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
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.
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).
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.
Parsing a multi-field Slack Workflow form into structured data, appending it to a Google Sheet, posting a review message with an Approve button, and on approval booking a Google Calendar event. Covers form parsing, the Sheets API, Slack interactive buttons, and the Calendar API.
Slack Workflow Builder dropped the outbound webhook action, so a form can no longer call your service directly. Here is how I worked around it by routing form submissions through a private channel that a bot reads, then DMing the requester a computed deadline, all without paying for a third-party connector.
How I added Confluence as a knowledge source for the bot without duplicating content - a sync script that fetches pages, converts HTML to markdown, and a weekly GitHub Actions pipeline to keep GCS up to date.
How I added a case archive search feature to an existing Slack support bot - from arguing against a separate service, to skipping FAISS for 600 records, to automating a CMS-to-GCS data pipeline.
Why I switched from Gemini 2.5 Flash to Claude Sonnet on Vertex AI, and how the migration went. Covers the Anthropic Vertex SDK, code changes, type safety, and first impressions.
How I built a Slack Workflow integration that lets users submit raw notes, uses Gemini AI to structure them into proper documentation, and automatically creates GitHub PRs for review.
How I added interactive feedback buttons to collect user satisfaction data, log it to BigQuery, and prevent double-clicking with visual confirmation.
How I fixed the bot serving outdated knowledge after GCS file updates by adding a reload endpoint, OIDC authentication, and wiring up GCS change notifications through Pub/Sub.
Adding structured logging Python Slack bot, stream logs to BigQuery, and visualize usage with Looker Studio dashboards.
Fixing Slack retry duplicates with event deduplication, eliminating Cloud Run cold starts with min-instances, and dealing with cross-region Gemini API latency.
How I integrated Google Cloud Storage as a knowledge base for Gemini, allowing the bot to answer questions from markdown documentation without redeploying.
How I added Google Vertex AI Gemini to my Flask Slack bot, with chat sessions, error handling, and troubleshooting permission issues. From zero to working AI in production.
How I deployed a Python Flask app to GCP Cloud Run with GitHub Actions CI/CD, coming from an AWS background. Spoiler: easier than you think.
What building a Flask REST API looks like when you‘re coming from Next.js. Spoiler: Flask routes are way simpler than I expected.
How I set up a Python development environment using uv, coming from a TypeScript/Next.js background. Spoiler: it‘s a lot like modern JavaScript tooling.
How I automated weekly PR creation from Google Sheets data using Python, GitHub Actions, and Slack notifications