Changelog

What we've shipped.

New work, changes, and fixes to the Loopdash site — newest first.

Edge proposal gate for Cloudflare Pages hosting

Added a Cloudflare Pages Function (functions/proposals/_middleware.js) that enforces the proposal password at the edge, replacing the Eleventy dev-server middleware that today forces the site to run as a paid Node web service on DigitalOcean. With the gate at the edge, the site can deploy as pure static output (_site) on Cloudflare Pages — no origin server, no health-check fragility, ~$0 hosting.

The Function is a faithful port of the .eleventy.js gate: same proposal_access_granted cookie, same 401 password form, same ?pw= prefill, password from the PROPOSAL_PASSWORD env var (default ShapeTomorrow). Cookie is now also Secure; SameSite=Lax. Covered by test/proposals-gate.test.mjs.

This is additive — the DigitalOcean deploy and its Eleventy middleware are untouched, so nothing changes until the Cloudflare Pages cutover. See the "Cloudflare Pages hosting" section in readme.md for the cutover steps.

On-page images now served from assets.loopdash.com

On-page images are now served from the assets.loopdash.com CDN (Cloudflare R2) instead of the site origin, enabled by setting CDN_ASSETS_URL in the deploy environment. The full pipeline is live: the build restores existing derivatives from the bucket so eleventy only re-encodes images whose source bytes changed (fast deploys), uploads are incremental (only new/changed files, scoped to the img/ prefix, never deleting), and the build rewrites /img/... references to the CDN. Origin image copies remain as a fallback, and OG/social images (Cloudinary) are unaffected.

Design It For Us CEO Letter Campaign proposal

Adds the password-protected proposal page at /proposals/design-it-for-us-ceo-letter/ for the CEO letter-writing flow on designitforus.org, with the live Documenso signing embed at /proposals/design-it-for-us-ceo-letter/sign/.

Faster deploys: rebuild only changed images

Deploys no longer re-encode every image from scratch. scripts/restore-images.mjs runs before eleventy and restores the previously-built derivatives from the assets bucket into _site/img, so eleventy-img skips re-encoding anything that hasn't changed (a full build with derivatives present takes ~2s vs minutes). Only images whose source bytes changed are re-encoded — tracked by a small source-hash manifest (image-source-hashes.json) on the bucket, published by the upload step after a successful upload. Restore is best-effort: with no creds or an empty bucket it does nothing and eleventy generates images as before.

Incremental asset uploads to assets.loopdash.com

npm run upload now runs scripts/upload-assets.mjs, which walks the built _site/img tree recursively and uploads each file to the assets.loopdash.com bucket only when it is new or its bytes changed (local MD5 vs remote ETag). Unchanged files are skipped, so a deploy no longer re-pushes whole directories that didn't change. The script reads only ASSETS_* env vars, is scoped to the img/ prefix, and never deletes — it cannot touch the cdn.loopdash.com bucket or any client assets.

Kyntronics support block moves to 50 hours

The Kyntronics proposal now offers a 50-hour support block at $5,500 prepaid instead of 100 hours at $11,000, and its signing embed points at the new Documenso document. Hourly rates, hosting, and scheduling terms are unchanged.

Serve images from assets.loopdash.com

Production builds can now serve all on-page images from the assets.loopdash.com CDN. A post-build step (scripts/rewrite-cdn-urls.mjs, chained into npm run build) rewrites /img/... references in the built HTML, CSS, and JS — including relative favicon paths and CSS url() backgrounds — to the CDN base, and a preconnect is emitted to warm the connection for LCP.

It's off by default and inert until CDN_ASSETS_URL is set in the deploy environment (e.g. https://assets.loopdash.com); local dev and CI are unaffected. Origin image copies remain in the build, so any reference the rewrite misses still resolves — no 404s. Social/OG images are unchanged (Cloudinary).

Fix deploy health-check timeout on startup

Production npm start no longer rebuilds the full site before listening — it serves the prebuilt _site output immediately (Eleventy --ignore-initial) so DigitalOcean health checks pass. Local development moves to npm run dev.

Courier case-study hero, homepage tools rotator, inspiration additions

Courier's case-study hero now uses the transparent "Cover-Up" cutout on the brand yellow field at Navigator's ~1.43:1 ratio, capped at 800px and centered; the homepage Courier image is likewise capped at 700px. The homepage statement's single "Slack" mention is now an auto-cycling vertical carousel of the tools we work inside (Slack, Linear, Figma, GitHub). Added five images to the inspiration gallery, ordered newest-first, and scaled the inspiration page heading down from the display size.

Cleaner Courier "Cover-Up" image on mobile

Swapped the mobile crop of Courier's homepage featured-work image for the full-yellow "The Cover-Up" wordmark composition, so it fills the row cleanly at the same height as the other cards without a device frame, letterboxing, or a clipped wordmark.

Courier and GAIN featured images sit on their brand field

Courier and Global AI Youth Network now use a single "subject on a solid brand field" image on the homepage — Courier's "Cover-Up" cutout on brand yellow, GAIN's dithered globe on terminal blue. Each sits on a matching CSS background and is contained and centered (GAIN scaled down with room around it), so the artwork frames identically at every size instead of a zoomed-in crop, and one asset serves desktop and mobile to keep load down. These rows are static (no parallax drift).

Lighthouse scores reported on every CI run

The Lighthouse CI job now writes the evaluated Performance, Accessibility, Best Practices, and SEO scores for each audited page into the GitHub Actions run summary as a color-coded table. Lighthouse already ran on every PR and push to main; this surfaces the numbers so they can be reviewed at a glance. The job stays advisory (non-blocking).

Homepage featured work restyled as full-bleed overlays; Searchlight proposal added

Reworked the homepage featured-work section from two-column image/text rows into full-width image rows with the project name, industry, and tagline overlaid on a soft bottom scrim. Titles sit at 80% white and go fully white on hover, which also reveals a "View case study" cue; removed the blur-on-hover, softened the parallax drift, and dropped the divider borders. Courier's "The Cover-Up" now uses an art-directed square crop on mobile so the wordmark isn't clipped. Also adds the Searchlight Institute website-redesign proposal page and small v3 proposal polish (smaller headline, pill CTA, share icon color).

Homepage CTA standardized, hero divider removed, proposal-gate hardening

Standardized the primary call-to-action to "Start a project" across the nav (desktop + mobile), hero, and footer, and removed the divider line above the hero CTA row. Also updated the /proposals gate fallback so the dev/preview server always boots (using the real proposal password when PROPOSAL_PASSWORD isn't set) and cleaned up package.json (dropped bogus fs/path deps, fixed the upload script, pinned Node via engines) and .gitignore (stopped tracking .DS_Store, .cache/, and a stale dist/).

Strengthen nonprofit web design links

Three relevant guides now point readers to Loopdash's nonprofit web design service.

Action Network data cleanup guide

Adds a practical guide to building a human-reviewed workflow for cleaning supporter data in Action Network.

Terms of Use refresh + legal page layout

Replaced the old AR-reminder Terms of Service with general website Terms of Use in Loopdash's voice (Ohio governing law). Both Terms and Privacy now share a compact legal layout — smaller hero, two-column section rows — instead of the oversized page-hero treatment.

Strengthen commercial internal links

Relevant blog and glossary pages now point readers to nonprofit web design, SEO, and managed hosting services.

Careers page: two new contract roles + public changelog

Changed

  • Replaced the three prior openings (Digital Designer, Product Designer, Technical Project Lead) with two contract roles — Contract Designer/PM and Contract Developer — each with its own role page and application form.
  • Dropped the mission-driven / advocacy / nonprofit framing from the careers copy.
  • Added 301 redirects (all host variants) from the six removed career URLs to /careers/.

Added

  • A public /changelog/ page that lists these entries newest-first, so shipped changes are visible on the site.

Homepage accessibility fixes + fast repeat-visit LCP

Fixed

  • Text contrast: darkened the muted-ink token so eyebrows, feature-row numbers/taglines, cap-meta, and review citations meet WCAG AA (3.78:1 → ~5:1 on cream); dimmed review-org buttons now clear the 3:1 large-text bar too.
  • Heading order: homepage feature-row project names are now h2 (the hero h1 previously jumped straight to h3).
  • Mobile zoom: removed maximum-scale=1 from the viewport meta so visitors can pinch-zoom.

Changed

  • The homepage count-up preloader now only plays on a visitor's first visit (30-day cookie). Return visits skip the overlay before it paints and show the hero immediately, so the LCP element no longer waits ~5.5s behind the intro — a large repeat-visit performance win. First-visit intro, reduced-motion, and safety-timeout behavior are unchanged.

Strengthen commercial service links

Relevant guides now point readers to Loopdash web development, copywriting, and branding services.

About page "Applied Intelligence Studio" reel, rename, and polish

The About page gains a scroll-pinned "Intelligent ___" word reel over a filtered, heavily-compressed nature backdrop, plus a rewritten Purpose statement that reveals word-by-word on scroll. The studio identity is renamed to Applied Intelligence Studio across home, about, careers, and selected-work (service pages keep "embedded web team"). Also: the homepage proof stat becomes "17 organizations" (was "12 case studies"), the service-page projects grid balances orphan last rows so they fill the width, the Cloudinary OG image drops the logo for a heading on a solid color field, the projects page loses redundant hero/index labels, and form inputs get a faint translucent-white fill.

Fix missing About reel backdrop image

The About scroll reel's backdrop (about-reel-bg.jpg) was referenced from CSS but sat at the src/img/ top level, which Eleventy does not pass through (only specific src/img/* subfolders are copied), so it 404'd in real builds. Moved it into the passthrough'd src/img/raw/ and updated the CSS path. Added a test/css-assets.test.mjs test that fails on any unresolved url() reference in the built CSS, closing the gap the HTML-only link test left open.

Homepage/hero animations, mobile nav, blog logos, SEO schema

Added

  • Per-word staggered entrance on the homepage and projects heroes (gated behind the preloader, with a <noscript> fallback and safety timeout so text can never stay hidden).
  • Word-by-word reveal on the studio statement, with a highlighted your Slack term (help-circle marker + hover/focus tooltip explaining the embed/augment model).
  • Auto-cycling homepage testimonials (pauses on hover/focus).
  • About page hero image; rebuilt editorial testimonials index page.
  • Richer JSON-LD: Organization (founding date, slogan, knowsAbout, contactPoint) and Article dateModified — on top of existing Organization/WebSite/Article/FAQPage/Service/Breadcrumb coverage.

Changed

  • Accent color to #035fd0; lighter #3986e6 on dark sections; white text on accent-filled button hovers.
  • Mobile nav: gaussian-blur overlay, larger/airier items, Support link replaced with a "Work with us" CTA.
  • Related-services blocks as editorial top-rule rows; apply forms left-aligned with paired name/email and the intro removed; role-stat pills softened.
  • Blog card brand marks render white (Action Network keeps its colors); single post covers use a subtle neutral background.
  • About page compressed; footer uses a Stripe "Billing" link.

Fixed

  • Mobile nav: header backdrop-filter was trapping the navbar z-index, hiding the logo + close button under the open overlay.
  • Statement/hero reveals use a scroll-position trigger instead of a fragile IntersectionObserver threshold (can't get stuck hidden or fire early).
  • FAQ answer body aligned flush with the question (was indented on open).

Removed

  • The /about-2 comparison page; Forge Health from the testimonial rotation.

Redesign dynamic OG images as text-on-color cards

Social/preview images are now clean text cards in the site palette — the page heading as large type (steps down for longer headings) with the logo as a small brand mark, no stock computer.png. Conversion pages (home, services, contact, work-with-us) render as blue background / cream text; content pages render as cream background / charcoal text. The image is computed once in head.njk and shared by the OpenGraph tags and the Article schema.