← Posts

Notes from the cooldown

Six days since Day 24. Pull the Plug has been quiet on purpose. The other projects took the floor.

Pull the Plug went into cooldown

Two PRs landed on June 1. The player keeps RUN_SPEED across a jump now; only stopping resets you to Walk. That fixed the "felt floaty" note from the couch playtest. And there is a cumulative timer on the mission-end card, so a playthrough finally feels like one thing instead of six.

Then the laptop closed on the game for a week. Playtest cooldown is a real cost I had not budgeted for.

Eortes met a real device

The app went on a phone. Then the device started telling me things.

The first tap on Search was slow because a 990-name Greek-locale sort was running the first time anyone opened the screen. Bell toggles on the People list took two seconds, because every mutation awaited rescheduleAll(): cancel ~120 alarms, reschedule ~120 alarms, in series, before the UI updated. The Android calendar-add was crashing through a multi-year SDK bug that needed a patch-package monkeypatch on expo-intent-launcher. All three fixed.

A Settings screen also showed up that I had not planned. The reminder time was hard-coded to 09:00. The wish message fired instantly with no preview, which on Viber is irreversible. Editable preview before sending. Saved template with a {name} placeholder. A per-contact "remind me to send the wish" toggle. Things you only put in when someone you know is about to use this.

Three version bumps in one Friday. Most of it is invisible. That is the gig.

PodReddit grew a verification harness

The Reddit-ads pipeline for the podcast had a bad week before this one. A 401 silently killed every webhook for a day because verify_jwt drifted on a deploy. The daily digest stopped fanning out for days because a jitter setting was bigger than its cron's runtime, so every dispatcher timed out before sending. An ad that Reddit was just slow to approve got auto-deleted by a cleanup job that assumed pending-for-five-days meant dead.

The pattern was the same in every case. The failure was silent. The silence was the worst part.

So this week was the verification harness. A script that asserts the invariants whose silent breakage caused the churn. Every public function reachable unauthenticated. Every critical cron has a recent successful run. The jitter is smaller than the runtime. No campaign stuck mid-launch. It exits non-zero on any failure and gates the deploy. Then the same checks run as an edge function on a 4-hour watchdog cron, Telegrams me on any fail, stays silent when healthy.

Plus a behavioral check that actually invokes the digest end to end for one tenant and asserts the message landed on Telegram, email, and Discord. The thing the existing crons could not catch.

Run this before declaring any pipeline change done. That note is in PROJECT_NOTES now, in caps.

No Rush is going to the Play Store

The PWA install banner kept nagging people who already had the app installed, because display-mode: standalone is false the moment they open the same link from a regular browser tab. Now the install detection uses navigator.getInstalledRelatedApps() against the manifest's related_applications. The banner goes away when the app is actually there.

The more honest reason for the Play Store: the install-to-home-screen dance has too many steps. The Play Store has one button. The TWA scaffold is in. Bubblewrap config, assetlinks.json served from app.norush.chat, the runbook for the first upload. The TWA loads the live site, so web deploys keep updating the app instantly. The Play Console is just the shell.

Outside got a map and 728 playgrounds

A new project on the pile. A mobile app for parents in Berlin: pick a park or a playground, broadcast "we're going" to a small circle of friend families, watch them join. Family-scoped, not public. It is called Outside.

It already existed on Firebase. A week or two ago it got rewritten under itself onto Supabase: Postgres with RLS gated by family membership, Edge Functions for the push fanout. This week was the catch-up. Bring the Berlin curated data, the Android EAS workflow, and the handoff doc forward from the Firebase branches that will not be making the trip.

The map also got real. The old MapPreview rendered a Static Maps image and bounced you out to Google Maps on tap, where Google read the landmark name as a search query and surfaced flea markets and bus stops sharing the name. Replaced with an interactive react-native-maps MapView, a coral marker locked to the actual coordinates, and a small "↑↗ Directions" button if you actually want turn-by-turn.

728 landmarks for Berlin seeded from OpenStreetMap: 355 playgrounds, 373 parks. Names ending in "platz" got filtered (memorial squares, not real parks), so did the FKK areas, so did the bare-generic "Spielplatz" and "Park". The curated 111 still take priority on collisions. Data © OpenStreetMap contributors.

A bot that buzzes my phone when the code does

Today's tiny one. A Node process on my laptop takes a POST /notify and DMs me on Discord. Useful because Discord push is good on a phone and works on desktop too, so I get one buzz instead of plumbing three different notification systems into every project. Five hours old.

Slash commands too. /log <project> <message> writes a quick note to data/log.json on the laptop, /recent <project> reads the last ten back. The next step is wiring it into every project's deploy and build hook, so my phone tells me when staging is up before I have to ask.

Comments

Anyone can post. Captcha keeps the bots out. No links allowed.

0 / 800