<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Rebounder Tech Blog</title><description>Field notes from the production systems operated by Rebounder Inc., written by the engineers who run them.</description><link>https://tech.rebounder.jp/</link><language>en</language><item><title>gcloud sql clone point-in-time: a Real Restore Drill</title><link>https://tech.rebounder.jp/en/posts/gcloud-sql-pitr-clone-restore-drill/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/gcloud-sql-pitr-clone-restore-drill/</guid><description>A record of restoring production Cloud SQL with gcloud sql instances clone --point-in-time: time to become usable, cost, and why it&apos;s private-IP only.</description><pubDate>Tue, 13 Oct 2026 00:00:00 GMT</pubDate></item><item><title>enabled: false Silently Disabled Claude Code Scheduled Tasks</title><link>https://tech.rebounder.jp/en/posts/claude-code-scheduled-tasks-three-ways-to-stop/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/claude-code-scheduled-tasks-three-ways-to-stop/</guid><description>Running Claude Code scheduled tasks on 6 daily slots for 7 weeks surfaced 3 ways they stop: never starting, dying mid-run, or enabled: false disabling the slot.</description><pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate></item><item><title>maxOutputTokens Was Missing, So Usage Had No Ceiling</title><link>https://tech.rebounder.jp/en/posts/cloud-run-instance-memory-rate-limit-not-shared/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/cloud-run-instance-memory-rate-limit-not-shared/</guid><description>A student chat reachable via anonymous magic link was rate-limited only per instance, with a regenerable cookie, leaving output and call count uncapped.</description><pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate></item><item><title>company_id Is Always Null on Public/Share Links</title><link>https://tech.rebounder.jp/en/posts/invite-company-id-null-on-public-link-skips-duplicate-check/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/invite-company-id-null-on-public-link-skips-duplicate-check/</guid><description>A duplicate check read company_id from the invite record, which public/share/QR applications never create, so the ID was always null and slots got re-booked.</description><pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate></item><item><title>Only Our Vercel API Functions Threw Cannot Find Module</title><link>https://tech.rebounder.jp/en/posts/vercel-node-functions-relative-import-missing-js-extension/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/vercel-node-functions-relative-import-missing-js-extension/</guid><description>tsc and vite dev pass locally, but Vercel Node Functions reject extensionless relative imports in production, crashing with Cannot find module.</description><pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate></item><item><title>is_pilot Backfill Misses Companies With Only One EXISTS</title><link>https://tech.rebounder.jp/en/posts/backfill-where-exists-misses-creatives-only-companies/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/backfill-where-exists-misses-creatives-only-companies/</guid><description>A backfill UPDATE that flags is_pilot with a single EXISTS(contracts) check misses creatives-only companies, which then get production-grade customer email.</description><pubDate>Wed, 07 Oct 2026 00:00:00 GMT</pubDate></item><item><title>A Poster&apos;s Title Shows Up as IMG_1234 on the Classroom TV</title><link>https://tech.rebounder.jp/en/posts/signage-title-from-filename-machine-name-detect/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/signage-title-from-filename-machine-name-detect/</guid><description>Raw filenames become titles, so IMG_1234 from a camera shows up on the classroom TV. We classify machine-generated names with regex and treat them as empty.</description><pubDate>Wed, 07 Oct 2026 00:00:00 GMT</pubDate></item><item><title>Bing Webmaster UrlCount Stuck at 1: the sitemap-index Trap</title><link>https://tech.rebounder.jp/en/posts/bing-webmaster-urlcount-stuck-sitemap-index/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/bing-webmaster-urlcount-stuck-sitemap-index/</guid><description>Submitting only sitemap-index.xml to Bing Webmaster makes it count UrlCount as 1 and stop, stalling impressions for days until child sitemaps go in directly.</description><pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate></item><item><title>listTotal Skips the units Multiplier, Preview Price Drifts</title><link>https://tech.rebounder.jp/en/posts/bundle-discount-preview-missing-units-multiplier/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/bundle-discount-preview-missing-units-multiplier/</guid><description>A bundle discount preview added termFee without multiplying by units, so a request for several slots always showed the price for just one slot.</description><pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate></item><item><title>max-width:900px Loses to a Later Same-Specificity Rule</title><link>https://tech.rebounder.jp/en/posts/css-media-query-overridden-by-later-same-specificity-base-rule/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/css-media-query-overridden-by-later-same-specificity-base-rule/</guid><description>A mobile @media override had no effect — text wrapped one char per line. Cause: a same-specificity base rule placed later in the file won the tie.</description><pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate></item><item><title>ScanFilter.setDeviceAddress Throws on the String &quot;null&quot;</title><link>https://tech.rebounder.jp/en/posts/scanfilter-setdeviceaddress-null-string-crash/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/scanfilter-setdeviceaddress-null-string-crash/</guid><description>ScanFilter.setDeviceAddress throws on invalid strings; optString turns a JSON null into &quot;null&quot;, which slips a blank guard and crashes the Service.</description><pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate></item><item><title>migrate_image_tag drifts from live after concurrent deploys</title><link>https://tech.rebounder.jp/en/posts/terraform-ledger-drift-concurrent-deploy-sessions/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/terraform-ledger-drift-concurrent-deploy-sessions/</guid><description>Two concurrent Cloud Run deploys left one session&apos;s change committed to Terraform&apos;s locals after another&apos;s unrelated commit, leaving the ledger behind live.</description><pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate></item><item><title>dpm set-device-owner Launches the App Before prefs Is Set</title><link>https://tech.rebounder.jp/en/posts/dpm-set-device-owner-launches-app-before-prefs-written/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/dpm-set-device-owner-launches-app-before-prefs-written/</guid><description>dpm set-device-owner launches the app instantly. Write prefs first, or the app mints its own device_id — one force-stop can no longer undo as device owner.</description><pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate></item><item><title>gcloud ADC Expires After ~44h: Reauthentication failed Fix</title><link>https://tech.rebounder.jp/en/posts/gcloud-adc-reauthentication-failed-non-interactive-service-account/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/gcloud-adc-reauthentication-failed-non-interactive-service-account/</guid><description>A scheduled AI agent calling the Search Console API died with Reauthentication failed. cannot prompt during non-interactive execution. Fix: a service account.</description><pubDate>Sun, 04 Oct 2026 00:00:00 GMT</pubDate></item><item><title>allUsers + objectViewer on GCS Grants list, Not Just get</title><link>https://tech.rebounder.jp/en/posts/gcs-allusers-objectviewer-includes-list-anonymous-enumeration/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/gcs-allusers-objectviewer-includes-list-anonymous-enumeration/</guid><description>A public GCS bucket granted allUsers objectViewer, which bundles get with list, letting anyone enumerate every object key instead of just fetching known ones.</description><pubDate>Sat, 03 Oct 2026 00:00:00 GMT</pubDate></item><item><title>Valid Token, Wrong Scope: an IDOR via design/date Parameters</title><link>https://tech.rebounder.jp/en/posts/signage-anonymous-token-trusts-design-date-query-params-idor/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/signage-anonymous-token-trusts-design-date-query-params-idor/</guid><description>A classToken-scoped signage API trusted its own design and date query parameters, letting a valid token pull names and dates it was never meant to show.</description><pubDate>Sat, 03 Oct 2026 00:00:00 GMT</pubDate></item><item><title>vercel inspect won&apos;t show which commit is live</title><link>https://tech.rebounder.jp/en/posts/vercel-cli-deploy-concurrent-collision-inspect-blind/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/vercel-cli-deploy-concurrent-collision-inspect-blind/</guid><description>vercel --prod via CLI (no GitHub integration) means concurrent deploys overwrite each other, and vercel inspect never shows which git commit is actually live.</description><pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate></item><item><title>term_months Display Drifts From Amount After Term Extension</title><link>https://tech.rebounder.jp/en/posts/invoice-document-period-drifts-from-term-extension/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/invoice-document-period-drifts-from-term-extension/</guid><description>Extending a contract term changes the billed period, but invoice/application pages still read term_months from the plan, so period and amount disagree.</description><pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate></item><item><title>@media(max-width:899px) Leaks Into a Scaled Signage Preview</title><link>https://tech.rebounder.jp/en/posts/scaled-signage-preview-inherits-mobile-media-query-layout/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/scaled-signage-preview-inherits-mobile-media-query-layout/</guid><description>A preview scaled with transform:scale() stays 1280x720, but @media(max-width:899px) for phones fires on real viewport width, leaking in mobile layout.</description><pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate></item><item><title>semgrep --config=auto Turns main Red, No Code Changed</title><link>https://tech.rebounder.jp/en/posts/semgrep-config-auto-registry-mutable-ci-breaks-without-code-change/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/semgrep-config-auto-registry-mutable-ci-breaks-without-code-change/</guid><description>semgrep ci --config=auto fetches the registry&apos;s rules every run, so main turns red the day upstream adds one, with zero code changed. Fix: pin rules and image.</description><pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate></item><item><title>amount_unset: Stripe&apos;s 7-Day Auto-Switch Never Fires</title><link>https://tech.rebounder.jp/en/posts/stripe-checkout-amount-unset-card-window-never-closes/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/stripe-checkout-amount-unset-card-window-never-closes/</guid><description>A Stripe contract with no amount set gets a notice promising an auto-switch to invoicing in 7 days — but the fallback needs amount != null, so it never closes.</description><pubDate>Thu, 24 Sep 2026 00:00:00 GMT</pubDate></item><item><title>sp.units Query Param Shows 5x Price for a 1-Unit Invite</title><link>https://tech.rebounder.jp/en/posts/invite-apply-page-trusts-query-units-while-server-confirms-one-unit/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/invite-apply-page-trusts-query-units-while-server-confirms-one-unit/</guid><description>Invite apply confirms 1 unit server-side, but the display used the raw query param, showing 5 units and 5x the price for a 1-unit contract.</description><pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate></item><item><title>gen-og.ts Cache Hid an Overwritten OG Image on 91 Posts</title><link>https://tech.rebounder.jp/en/posts/og-image-same-slug-lang-collision-incremental-cache-masks-it/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/og-image-same-slug-lang-collision-incremental-cache-masks-it/</guid><description>gen-og.ts wrote both languages to one og/${slug}.png; the later run won, and the cache called it fresh — 91 of 95 Japanese posts got an English share card.</description><pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Next.js 15.1.6 Got Blocked by Vercel as a Vulnerable Version</title><link>https://tech.rebounder.jp/en/posts/vercel-blocks-vulnerable-nextjs-version/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/vercel-blocks-vulnerable-nextjs-version/</guid><description>Pushing to Vercel with next pinned to 15.1.6 blocked the deploy pre-build — Vercel flagged it as vulnerable, and it stayed blocked until bumped to ^15.5.23.</description><pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate></item><item><title>pnpm-lock.yaml Made Vercel Misdetect an npm Project as pnpm</title><link>https://tech.rebounder.jp/en/posts/vercel-pnpm-lockfile-misdetect/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/vercel-pnpm-lockfile-misdetect/</guid><description>An untracked pnpm-lock.yaml made Vercel misdetect an npm repo as pnpm, since .vercelignore stops it reading .gitignore, and a version mismatch broke build.</description><pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Next.js Server Action Fail-Open: error Read as Success</title><link>https://tech.rebounder.jp/en/posts/nextjs-server-action-fail-open-error-swallow/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/nextjs-server-action-fail-open-error-swallow/</guid><description>A server action judged success by {data} alone, ignoring error. A transient DB failure then left the customer page and internal Slack contradicting each other.</description><pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate></item><item><title>01.dnsv.jp Full-Zone Replace Deletes Unrelated A Records</title><link>https://tech.rebounder.jp/en/posts/onamae-dns-full-zone-replace-record-vanishes/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/onamae-dns-full-zone-replace-record-vanishes/</guid><description>Onamae.com DNS submits the whole zone, not just the edit, so adding a subdomain can delete an unrelated A record missing from the stale copy on screen.</description><pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate></item><item><title>console_name.sql Collided Again 58 Minutes Later</title><link>https://tech.rebounder.jp/en/posts/duplicate-migration-number-from-parallel-prs-needs-rename/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/duplicate-migration-number-from-parallel-prs-needs-rename/</guid><description>I renamed a file to fix a duplicate migration number. 58 minutes later, two other branches had picked the same number, and trunk got three same-numbered files.</description><pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate></item><item><title>fail-closed Guard Was Missing From Two Other Write Paths</title><link>https://tech.rebounder.jp/en/posts/group-distribution-loop-invite-missing-start-month-guard/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/group-distribution-loop-invite-missing-start-month-guard/</guid><description>kimiteras-portal added a fail-closed guard to direct bookings, then found it missing from group distribution and invite issuance, which can&apos;t be recalled.</description><pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate></item><item><title>reminder_log_kind_check Regex Test Was a False Green</title><link>https://tech.rebounder.jp/en/posts/regex-check-constraint-name-mention-false-green-test/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/regex-check-constraint-name-mention-false-green-test/</guid><description>A static test extracted CHECK constraint values with a regex anchored on the constraint&apos;s name, matching a SQL comment or another table&apos;s check(kind in) clause.</description><pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate></item><item><title>RegExp.test False Positive: &quot;unsigned&quot; Matches &quot;signed&quot;</title><link>https://tech.rebounder.jp/en/posts/anyflow-unanchored-regex-unsigned-matches-signed/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/anyflow-unanchored-regex-unsigned-matches-signed/</guid><description>An unanchored regex for contract completion let &quot;unsigned&quot; match &quot;signed&quot;, auto-archiving unsigned documents as completed.</description><pubDate>Sun, 20 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Google Custom Search API 403: Switched to Brave Search API</title><link>https://tech.rebounder.jp/en/posts/google-cse-403-switched-to-brave-search-api/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/google-cse-403-switched-to-brave-search-api/</guid><description>Headless rank checks hit 403: This project does not have the access to Custom Search JSON API. Why Brave Search is the default now, with Serper as backup.</description><pubDate>Sun, 20 Sep 2026 00:00:00 GMT</pubDate></item><item><title>copyOneDay Overwrite Silently Drops Pinned Notices</title><link>https://tech.rebounder.jp/en/posts/editor-copy-day-overwrite-drops-pinned-notice/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/editor-copy-day-overwrite-drops-pinned-notice/</guid><description>The signage editor&apos;s copy-from-another-day feature overwrote a day&apos;s notices wholesale, silently dropping any pinned notice a teacher had entered.</description><pubDate>Sat, 19 Sep 2026 00:00:00 GMT</pubDate></item><item><title>supabase-js count Query Returns null on Failure</title><link>https://tech.rebounder.jp/en/posts/integration-health-monitor-swallows-its-own-query-error/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/integration-health-monitor-swallows-its-own-query-error/</guid><description>A daily health monitor fell back a failed supabase-js query to 0/[] without checking error, hiding its own failure as &apos;all clear.&apos;</description><pubDate>Sat, 19 Sep 2026 00:00:00 GMT</pubDate></item><item><title>start_month Missing Lets a Contract&apos;s Period Go NULL</title><link>https://tech.rebounder.jp/en/posts/loop-start-month-missing-publishes-null-period-contract/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/loop-start-month-missing-publishes-null-period-contract/</guid><description>A contract published with start_month missing gets period_start and period_end NULL, so the expiry sweep never fires and the slot stays live forever.</description><pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Next.js Middleware Missing an Exclusion Forces Login</title><link>https://tech.rebounder.jp/en/posts/middleware-excludes-public-share-link-from-login-redirect/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/middleware-excludes-public-share-link-from-login-redirect/</guid><description>Next.js middleware (Proxy) checks auth on every route by default. Forget to exclude a new no-login route (a public share link) and it still redirects to /login.</description><pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate></item><item><title>entity_id Was uuid, We Inserted a Token — 22P02</title><link>https://tech.rebounder.jp/en/posts/audit-log-entity-id-uuid-token-22p02-swallowed-by-catch/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/audit-log-entity-id-uuid-token-22p02-swallowed-by-catch/</guid><description>audit_logs.entity_id is a uuid column, but the code passed a 64-hex token straight in. The insert failed with 22P02, and a catch block swallowed it silently.</description><pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate></item><item><title>A 200 OK That Crashes a Server Component</title><link>https://tech.rebounder.jp/en/posts/fetch-200-contract-drift-missing-field-crashes-server-component/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/fetch-200-contract-drift-missing-field-crashes-server-component/</guid><description>An external API returned 200 but was missing a required field. Casting the JSON skips runtime validation, so the Server Component crashes without it.</description><pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate></item><item><title>PostgREST .or() Breaks Silently on a Comma</title><link>https://tech.rebounder.jp/en/posts/supabase-or-filter-comma-breaks-query-silently/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/supabase-or-filter-comma-breaks-query-silently/</guid><description>A search query interpolated raw text into .or(), so a comma broke the filter. supabase-js returns {data:null}, not a throw, so the category vanished silently.</description><pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Only system_admin Hits The Audit Log Foreign Key Constraint</title><link>https://tech.rebounder.jp/en/posts/audit-log-fk-violation-system-admin-not-in-users-table/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/audit-log-fk-violation-system-admin-not-in-users-table/</guid><description>The audit log&apos;s actor referenced users by foreign key, so only actions by system_admin — kept in a different table — failed on insert with 23503.</description><pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate></item><item><title>polynomial-redos: Missing ^ Made a Trim Regex O(n^2)</title><link>https://tech.rebounder.jp/en/posts/trailing-slash-regex-polynomial-redos-codeql/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/trailing-slash-regex-polynomial-redos-codeql/</guid><description>A trailing-slash regex without a leading ^ anchor tripped CodeQL&apos;s js/polynomial-redos in three spots, backtracking to O(n^2). Replaced with a linear scan.</description><pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate></item><item><title>pnpm --filter build &quot;Module not found&quot;: Use web...</title><link>https://tech.rebounder.jp/en/posts/pnpm-filter-build-turbopack-module-not-found-monorepo-docker/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/pnpm-filter-build-turbopack-module-not-found-monorepo-docker/</guid><description>In a pnpm workspace, `--filter web build` skips building dependencies, leaving dist missing and Turbopack throwing 93 Module not found. `...` fixes it.</description><pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Duplicate Key Value Violates Unique Constraint, Permanently</title><link>https://tech.rebounder.jp/en/posts/postgres-publish-demote-then-insert-non-atomic-duplicate-key-permanently-stuck/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/postgres-publish-demote-then-insert-non-atomic-duplicate-key-permanently-stuck/</guid><description>Publishing a version as a non-atomic demote-then-insert leaves one update stranded under concurrency, and every later publish fails on duplicate key forever.</description><pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Cloudflare Web Analytics Over GA4 for This Tech Blog</title><link>https://tech.rebounder.jp/en/posts/cloudflare-web-analytics-not-ga4/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/cloudflare-web-analytics-not-ga4/</guid><description>To avoid taxing Core Web Vitals twice and more cookie copy, this blog skips GA4 for Cloudflare Web Analytics — losing 2 days of data before the tag shipped.</description><pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate></item><item><title>drizzle-kit generate Duplicate ADD COLUMN: Stale Snapshot</title><link>https://tech.rebounder.jp/en/posts/drizzle-kit-snapshot-manual-edit-avoids-duplicate-alter-regen/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/drizzle-kit-snapshot-manual-edit-avoids-duplicate-alter-regen/</guid><description>A column added but not reflected in the drizzle snapshot makes the next generate re-emit an ADD COLUMN with no IF NOT EXISTS, failing where it already applied.</description><pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate></item><item><title>NoSuchBucket: Destroying Staging Broke Prod Ad Images</title><link>https://tech.rebounder.jp/en/posts/gcs-bucket-default-url-staging-destroy-prod-404/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/gcs-bucket-default-url-staging-destroy-prod-404/</guid><description>A staging GCS bucket URL was baked as a seed script&apos;s env-var fallback into production&apos;s media_url. Destroying staging then 404&apos;d prod images with NoSuchBucket.</description><pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate></item><item><title>findUnmaskedPii False-Positives After Unmask</title><link>https://tech.rebounder.jp/en/posts/unmask-pii-check-false-positive-drops-correct-draft/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/unmask-pii-check-false-positive-drops-correct-draft/</guid><description>A PII check after unmasking flags a teacher&apos;s restored phone or email as a raw leak, discarding the draft. Checking before unmask fixes it, no detection lost.</description><pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate></item><item><title>&quot;An invalid form control is not focusable&quot;: Hidden Steps</title><link>https://tech.rebounder.jp/en/posts/multistep-form-hidden-required-field-blocks-submit-not-focusable/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/multistep-form-hidden-required-field-blocks-submit-not-focusable/</guid><description>A form&apos;s steps toggled with hidden. An empty required field on a now-hidden step made the confirm step&apos;s submit button do nothing.</description><pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Next.js Build Breaks on a Module-Level Resend Client</title><link>https://tech.rebounder.jp/en/posts/resend-client-module-level-init-breaks-nextjs-build/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/resend-client-module-level-init-breaks-nextjs-build/</guid><description>A Resend client at module scope makes next build throw &quot;resend_api_key is required&quot; when page-data collection imports the route without the env var.</description><pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate></item><item><title>supabase-js .range() Without .order() Drops Rows</title><link>https://tech.rebounder.jp/en/posts/postgrest-range-without-order-duplicate-drop-live-asset-deleted/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/postgrest-range-without-order-duplicate-drop-live-asset-deleted/</guid><description>OFFSET/LIMIT paging with .range() can duplicate or drop rows at a page boundary without .order(). One missing reference marks a live asset for deletion.</description><pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Two PaymentIntents: a Losing webhook Reverts the Winner</title><link>https://tech.rebounder.jp/en/posts/stripe-duplicate-payment-intent-webhook-missing-pi-match-reverts-winner/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/stripe-duplicate-payment-intent-webhook-missing-pi-match-reverts-winner/</guid><description>Two tabs completing the same Checkout create two PaymentIntents. An UPDATE that never checked the PI id let the loser&apos;s webhook revert the winner&apos;s live hold.</description><pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate></item><item><title>supabase-js try/catch Doesn&apos;t Catch Errors: Check { error }</title><link>https://tech.rebounder.jp/en/posts/supabase-js-no-throw-contract-version-freeze-error-swallowed/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/supabase-js-no-throw-contract-version-freeze-error-swallowed/</guid><description>supabase-js never throws on network or PostgREST failure; it resolves to {data: null, error}. Checking only data can&apos;t tell a failed read from a missing row.</description><pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate></item><item><title>read-merge-write Drops a Key Without FOR UPDATE</title><link>https://tech.rebounder.jp/en/posts/display-settings-read-merge-write-lost-update-without-lock/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/display-settings-read-merge-write-lost-update-without-lock/</guid><description>A Server Action read a co-located key with a plain SELECT, not FOR UPDATE, so concurrent saves lost an update to last-writer-wins. Cause and the row-lock fix.</description><pubDate>Tue, 08 Sep 2026 00:00:00 GMT</pubDate></item><item><title>if/else-if as Kotlin&apos;s ?.let Return Value Requires else</title><link>https://tech.rebounder.jp/en/posts/kotlin-let-trailing-if-elseif-no-else-exhaustive-expression-error/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/kotlin-let-trailing-if-elseif-no-else-exhaustive-expression-error/</guid><description>An else-less if/else-if last in a Kotlin ?.let block hits &quot;if must have both main and else branches if used as an expression&quot;. Cause and the return@let fix.</description><pubDate>Tue, 08 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Telling not-allowed From no-speech in SpeechRecognition</title><link>https://tech.rebounder.jp/en/posts/speechrecognition-not-allowed-benign-vs-serious-error-hint/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/speechrecognition-not-allowed-benign-vs-serious-error-hint/</guid><description>The mic button did nothing on not-allowed or audio-capture. Every error was ignored — but warning on benign codes like no-speech makes the UI noisy instead.</description><pubDate>Tue, 08 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Promise.all Concurrent Writes Lose to last-writer-wins</title><link>https://tech.rebounder.jp/en/posts/editor-promise-all-last-writer-wins-duplicate-day/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/editor-promise-all-last-writer-wins-duplicate-day/</guid><description>An AI multi-day edit can duplicate today into the top-level write and the days array, so two replace-saves hit one row and Promise.all lets the later one win.</description><pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Missing frame-src in CSP Blocks YouTube, Kills Watch Logs</title><link>https://tech.rebounder.jp/en/posts/haiia-csp-missing-frame-src-blocks-youtube-breaks-watch-tracking/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/haiia-csp-missing-frame-src-blocks-youtube-breaks-watch-tracking/</guid><description>A learning-video CSP had no frame-src, so default-src &apos;self&apos; blocked every YouTube embed — and window.YT never loaded, so watch-time tracking died too.</description><pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Next.js Server Actions bodySizeLimit: Raising Isn&apos;t Enough</title><link>https://tech.rebounder.jp/en/posts/nextjs-server-actions-bodysizelimit-still-hits-error-boundary/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/nextjs-server-actions-bodysizelimit-still-hits-error-boundary/</guid><description>A Server Action throws before returning once its body exceeds bodySizeLimit, hitting the error boundary. Raising the limit alone won&apos;t fix it; add size guards.</description><pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate></item><item><title>An Empty contractId Gives invalid input syntax uuid</title><link>https://tech.rebounder.jp/en/posts/stripe-setup-mode-empty-contractid-invalid-uuid-postgres/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/stripe-setup-mode-empty-contractid-invalid-uuid-postgres/</guid><description>Stripe&apos;s company-level card registration (Setup Mode) has no contractId, but the caller&apos;s type still required a string, so an empty string hit a uuid column.</description><pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Drizzle onConflictDoUpdate Writes null: Use COALESCE</title><link>https://tech.rebounder.jp/en/posts/drizzle-onconflictdoupdate-coalesce-last-known-good-null/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/drizzle-onconflictdoupdate-coalesce-last-known-good-null/</guid><description>Drizzle onConflictDoUpdate writes set values over the row as-is. A source returning partial nulls can erase a known-good value unless wrapped in COALESCE.</description><pubDate>Sun, 06 Sep 2026 00:00:00 GMT</pubDate></item><item><title>cqw Fails Silently When the DOM Around It Changes</title><link>https://tech.rebounder.jp/en/posts/css-container-query-cqw-context-dependent-fails-silently/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/css-container-query-cqw-context-dependent-fails-silently/</guid><description>cqw stops working with no error once a DOM structure change leaves the referenced container width undetermined — the preview rendered at full size and clipped.</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Hand-Built Preview Payload Drifts From the Device</title><link>https://tech.rebounder.jp/en/posts/editor-preview-hand-built-payload-drifts-from-device-builder/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/editor-preview-hand-built-payload-drifts-from-device-builder/</guid><description>The class editor&apos;s board preview hand-built its base and pinned automatic blocks to null. The device builds every block from one source, so the two disagreed.</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>pdfjs-dist standard_fonts Missing in Next.js standalone</title><link>https://tech.rebounder.jp/en/posts/pdfjs-dist-standard-fonts-nextjs-standalone-not-bundled/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/pdfjs-dist-standard-fonts-nextjs-standalone-not-bundled/</guid><description>pdfjs-dist loads its standard fonts dynamically over file://, so Next.js file tracing cannot follow it and the standalone build ships without them.</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>A disabled Submit Button Dies Before Hydration</title><link>https://tech.rebounder.jp/en/posts/react-controlled-disabled-button-breaks-progressive-enhancement/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/react-controlled-disabled-button-breaks-progressive-enhancement/</guid><description>Driving the disabled attribute from server state left the button permanently disabled before hydration or when JS failed, making the signing form unsubmittable.</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Duplicate URLs in a Feed Break ON CONFLICT DO UPDATE</title><link>https://tech.rebounder.jp/en/posts/postgres-on-conflict-do-update-cannot-affect-row-twice-feed-dedup/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/postgres-on-conflict-do-update-cannot-affect-row-twice-feed-dedup/</guid><description>Duplicate URLs made one upsert hit &quot;ON CONFLICT DO UPDATE command cannot affect row a second time&quot; (21000), and a fail-soft catch skipped the feed silently.</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate></item><item><title>A Ledger INSERT Failure Swallowed as a Duplicate</title><link>https://tech.rebounder.jp/en/posts/stripe-webhook-ledger-insert-error-swallowed-as-duplicate/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/stripe-webhook-ledger-insert-error-swallowed-as-duplicate/</guid><description>The Stripe webhook read every ledger INSERT failure as Postgres 23505 idempotency and returned 200, so a transient fault lost the event — Stripe never retried.</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Supabase maybeSingle() PGRST116: Multiple Rows Returned</title><link>https://tech.rebounder.jp/en/posts/supabase-maybesingle-multiple-rows-pgrst116-permanent-404/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/supabase-maybesingle-multiple-rows-pgrst116-permanent-404/</guid><description>An evidence-PDF API filtered on 2 of 3 unique-key columns, then called maybeSingle(). Once a second row existed for that pair, real data started returning 404.</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Missing passThroughEnv Skips Tests While CI Stays Green</title><link>https://tech.rebounder.jp/en/posts/turbo-passthroughenv-missing-rls-tests-silently-skipped/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/turbo-passthroughenv-missing-rls-tests-silently-skipped/</guid><description>Without passThroughEnv, turbo won&apos;t forward CI&apos;s DATABASE_URL to vitest. A describe.skip guard hides the gap, so CI stayed green while 24 RLS tests never ran.</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Only the Poll Stringifies Date: getTime Is Not a Function</title><link>https://tech.rebounder.jp/en/posts/json-poll-response-date-string-gettime-not-a-function/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/json-poll-response-date-string-gettime-not-a-function/</guid><description>SSR restores Date as a Date, but the same screen&apos;s polling gets a string from res.json(). Calling .getTime() on it took the whole board down.</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate></item><item><title>insetsController Is null Before setContentView</title><link>https://tech.rebounder.jp/en/posts/android-insetscontroller-null-before-setcontentview/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/android-insetscontroller-null-before-setcontentview/</guid><description>window.insetsController returns null before setContentView() because the DecorView is not resolved yet. hide() never runs and immersive mode silently fails.</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate></item><item><title>One startActivity Is Not Enough to Blank a Kiosk Screen</title><link>https://tech.rebounder.jp/en/posts/android-kiosk-overlay-startactivity-can-silently-fail-leaving-screen-on/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/android-kiosk-overlay-startactivity-can-silently-fail-leaving-screen-on/</guid><description>An always-on Android kiosk that blanks its screen with one startActivity stays lit all night when BAL limits or a missing SYSTEM_ALERT_WINDOW block the call.</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Supabase SECURITY DEFINER RPC Callable by anon: Revoke It</title><link>https://tech.rebounder.jp/en/posts/supabase-security-definer-function-default-public-execute-exposes-rpc/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/supabase-security-definer-function-default-public-execute-exposes-rpc/</guid><description>A SECURITY DEFINER write RPC gets PUBLIC EXECUTE by PostgreSQL default. Without a revoke, anon can call it directly through Supabase&apos;s PostgREST layer.</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate></item><item><title>read-merge-write Without FOR UPDATE Loses Keys</title><link>https://tech.rebounder.jp/en/posts/colocated-config-key-lost-update-without-row-lock/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/colocated-config-key-lost-update-without-row-lock/</guid><description>Several settings keys share one JSONB row. A partial update that reads and writes back without SELECT ... FOR UPDATE loses the key a concurrent save just wrote.</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Only One Branch Had No Way to Add the First Item</title><link>https://tech.rebounder.jp/en/posts/conditional-branch-hides-first-item-creation-entry-point-stuck-ui/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/conditional-branch-hides-first-item-creation-entry-point-stuck-ui/</guid><description>The school structure screen branches three ways on two booleans, and the state with grades but no departments had no way to add a department at all.</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Re-consent to Revised Terms Does Not Reset auto_renew</title><link>https://tech.rebounder.jp/en/posts/contract-reconsent-does-not-reset-auto-renew/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/contract-reconsent-does-not-reset-auto-renew/</guid><description>A customer re-consents to terms without the auto-renewal clause, yet auto_renew stays true. The flag is only ever written false to true.</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Media Queries See the Real Viewport in a Scaled Stage</title><link>https://tech.rebounder.jp/en/posts/media-query-still-uses-real-viewport-inside-scaled-fixed-stage/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/media-query-still-uses-real-viewport-inside-scaled-fixed-stage/</guid><description>A fixed-size preview shrunk by transform:scale still evaluates its media query against the real viewport, so a big monitor takes the wide profile and overflows.</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>left:50% With width:fit-content Makes max-width Never Apply</title><link>https://tech.rebounder.jp/en/posts/absolute-left-50-fit-content-max-width-never-applies/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/absolute-left-50-fit-content-max-width-never-applies/</guid><description>An absolute plate centred with left:50% and width:fit-content wrapped long before its max-width. Shrink-to-fit subtracts the left offset from available width.</description><pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate></item><item><title>An inset box-shadow Ring Hides Behind a Child Background</title><link>https://tech.rebounder.jp/en/posts/inset-box-shadow-ring-hidden-by-static-child-background/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/inset-box-shadow-ring-hidden-by-static-child-background/</guid><description>A ring drawn with inset box-shadow vanished under a child with its own background. inset shadows paint at the background stage, below static children.</description><pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate></item><item><title>The Edit Form Pruned Selections It Could Not See</title><link>https://tech.rebounder.jp/en/posts/edit-form-prunes-selections-missing-from-stale-list-silent-data-loss/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/edit-form-prunes-selections-missing-from-stale-list-silent-data-loss/</guid><description>The edit form auto-prunes selections missing from the refetched list, losing them on an unrelated save — a price-only save could shrink the targeted monitors.</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Non-Numeric env Becomes NaN and Slips Past ??</title><link>https://tech.rebounder.jp/en/posts/env-nan-parseint-nullish-coalescing-immediate-abort/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/env-nan-parseint-nullish-coalescing-immediate-abort/</guid><description>A non-numeric env makes parseInt return NaN, slipping past the truthy check and ??. That NaN reached setTimeout, so the AbortController aborts immediately.</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Narrowing a Page&apos;s Roles Left the Action&apos;s Gate</title><link>https://tech.rebounder.jp/en/posts/parent-page-role-narrowed-child-component-gate-left-behind-forbidden-error/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/parent-page-role-narrowed-child-component-gate-left-behind-forbidden-error/</guid><description>Changed only the parent page&apos;s roles, forgot the child component&apos;s gate: requireRole narrowed to system admins while the panel kept its publisher gate.</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Post-Charge DB Failure Read as a Card Decline</title><link>https://tech.rebounder.jp/en/posts/stripe-post-charge-db-failure-misdiagnosed-as-card-decline/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/stripe-post-charge-db-failure-misdiagnosed-as-card-decline/</guid><description>Swallowing a post-payment failure in catch causes a double charge — a transient DB error after the charge succeeded was diagnosed as a card decline.</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>RLS Allowing actor_user_id NULL Erases Audit Trails</title><link>https://tech.rebounder.jp/en/posts/audit-log-rls-null-actor-allows-repudiation/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/audit-log-rls-null-actor-allows-repudiation/</guid><description>The audit log INSERT policy allowed actor_user_id IS NULL for any role. A compromised tenant account could log its actions as actor=NULL and escape the trail.</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Leftover sticky top:0 Makes a fixed Bar Fill the Screen</title><link>https://tech.rebounder.jp/en/posts/css-fixed-inherited-top-zero-bottom-zero-fullscreen-stretch/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/css-fixed-inherited-top-zero-bottom-zero-fullscreen-stretch/</guid><description>Switching to position:fixed without clearing the sticky top:0 leaves top and bottom both set, stretching the box to the full viewport height.</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate></item><item><title>The Leak Check Only Grepped Half the Package</title><link>https://tech.rebounder.jp/en/posts/dist-sanitizer-denylist-grep-misses-new-internal-string/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/dist-sanitizer-denylist-grep-misses-new-internal-string/</guid><description>A build script grepped the package against a word list for internal comment text. Internal wording leaked anyway: the grep path missed half the package.</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A New httpOnly Cookie 401s Only Already-Logged-In Users</title><link>https://tech.rebounder.jp/en/posts/new-httponly-cookie-not-issued-until-relogin-after-deploy/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/new-httponly-cookie-not-issued-until-relogin-after-deploy/</guid><description>A write-only httpOnly HMAC cookie shipped and only staff logged in before the deploy got 401s, while the UI still showed them signed in.</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Public Route Missing From the middleware matcher</title><link>https://tech.rebounder.jp/en/posts/nextjs-middleware-matcher-missing-public-route-login-redirect/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/nextjs-middleware-matcher-missing-public-route-login-redirect/</guid><description>The public signage page is anonymous — no __session. Left out of the middleware matcher&apos;s exclusion list, every device was redirected to /login instead.</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Duplicating a Placement Without Ending the Old One</title><link>https://tech.rebounder.jp/en/posts/renewal-successor-rows-without-retiring-predecessor-double-counts-capacity/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/renewal-successor-rows-without-retiring-predecessor-double-counts-capacity/</guid><description>Subscription auto-renewal duplicates placements for the successor. Without ending the original row, inventory capacity is double-counted in the remaining sum.</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate></item><item><title>LIMIT 1 Without ORDER BY Returns Another Tenant</title><link>https://tech.rebounder.jp/en/posts/dev-login-missing-orderby-returns-wrong-tenant-admin/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/dev-login-missing-orderby-returns-wrong-tenant-admin/</guid><description>dev-login resolved a school_admin with a SELECT LIMIT 1 and no ORDER BY, so as multi-tenant test data grows it can return a uid from an unintended school.</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate></item><item><title>proxy.ts Redirected API-Key Endpoints to the Login Page</title><link>https://tech.rebounder.jp/en/posts/nextjs-middleware-external-api-key-auth-redirected-to-login/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/nextjs-middleware-external-api-key-auth-redirected-to-login/</guid><description>Next.js proxy.ts listed only /api/health as exempt from session auth, so /api/v1/ and /api/mcp/ with their own API key auth were redirected to the login page.</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate></item><item><title>?? Defaults Overwrite Fields the Form Never Sent</title><link>https://tech.rebounder.jp/en/posts/supabase-update-partial-field-nullish-coalesce-overwrite/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/supabase-update-partial-field-nullish-coalesce-overwrite/</guid><description>A Supabase partial update can overwrite fields the form never sent: ?? default treats an unsent field as the default, rolling live slots back to vacant.</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Holding-Only Checks Reapply a Bundle Discount</title><link>https://tech.rebounder.jp/en/posts/bundle-discount-reapplied-on-every-purchase-without-granted-check/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/bundle-discount-reapplied-on-every-purchase-without-granted-check/</guid><description>A bundle discount decided only by what the buyer holds was applied repeatedly on further purchases — an idempotency bug. A granted-history check fixed it.</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>The Lock Held; the Count Counted Intent, Not Writes</title><link>https://tech.rebounder.jp/en/posts/for-update-count-intent-vs-actual-writes/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/for-update-count-intent-vs-actual-writes/</guid><description>A flaky test where newlyDown summed to 2 instead of 1 was not the DB rows but the summary. FOR UPDATE serialised the writes; the count used the classification.</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Temp-Password Guard Written Per Page Leaks by URL</title><link>https://tech.rebounder.jp/en/posts/forced-password-change-bypassed-by-direct-url/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/forced-password-change-bypassed-by-direct-url/</guid><description>A must_change_password advertiser could skip the forced change by going to any page but /dashboard by direct URL. The guard lived per page, not in one place.</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>RLS On Is Not Safe While TRUNCATE Is Granted</title><link>https://tech.rebounder.jp/en/posts/postgres-truncate-bypasses-rls-even-when-enabled/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/postgres-truncate-bypasses-rls-even-when-enabled/</guid><description>chat_knowledge had RLS enabled and zero policies, yet Supabase&apos;s default grants left TRUNCATE on anon/authenticated. TRUNCATE is not subject to RLS at all.</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Humanising an Error Message Cost the Dead-Letter Its Trace</title><link>https://tech.rebounder.jp/en/posts/dead-letter-error-humanized-loses-traceable-id/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/dead-letter-error-humanized-loses-traceable-id/</guid><description>Coverage validation returned only admin-form Japanese. Reusing it as the dead-letter last_error dropped the school ID, so logs could not name the cause.</description><pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Permissions-Policy: microphone=() Blocks Your Own Origin Too</title><link>https://tech.rebounder.jp/en/posts/permissions-policy-microphone-self-blocks-web-speech/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/permissions-policy-microphone-self-blocks-web-speech/</guid><description>Permissions-Policy: microphone=() allows no origin at all, blocking our own Web Speech API voice input with no permission prompt. Fixed with microphone=(self).</description><pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Stripe Checkout Session expires_at: 24h Default Holds Seats</title><link>https://tech.rebounder.jp/en/posts/stripe-checkout-session-default-24h-expiry-holds-reservation-seat/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/stripe-checkout-session-default-24h-expiry-holds-reservation-seat/</guid><description>A Stripe Checkout Session with no expires_at defaults to 24 hours, and a booking abandoned without paying keeps occupying capacity that whole time.</description><pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Aborting streamObject Leaves usage as an Unhandled Rejection</title><link>https://tech.rebounder.jp/en/posts/ai-sdk-streamobject-abort-unhandled-rejection/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/ai-sdk-streamobject-abort-unhandled-rejection/</guid><description>Wiring an AbortSignal into the Vercel AI SDK&apos;s streamObject makes result.usage reject on abort. If the caller returns without awaiting done, nothing catches it.</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Fixing a detect-non-literal-regexp False Positive</title><link>https://tech.rebounder.jp/en/posts/semgrep-non-literal-regexp-dead-branch-false-positive/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/semgrep-non-literal-regexp-dead-branch-false-positive/</guid><description>An E2E fallback, new RegExp(c.path.replace(...)), tripped Semgrep&apos;s detect-non-literal-regexp. The branch was unreachable, so we deleted it with a type.</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Stale Branch Deploy Silently Reverted Features</title><link>https://tech.rebounder.jp/en/posts/stale-branch-deploy-silently-reverts-merged-features/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/stale-branch-deploy-silently-reverts-merged-features/</guid><description>A deploy from a branch with an old merge base silently rolls back existing features: the Cloud Run image tag drops what merged to main since it diverged.</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>YT.Player Replacing a div Can Leave a Black Screen</title><link>https://tech.rebounder.jp/en/posts/youtube-iframe-player-div-replace-black-screen/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/youtube-iframe-player-div-replace-black-screen/</guid><description>Initialising the YouTube IFrame API by handing it a div shows nothing until that div becomes an iframe, and depending on timing playback never starts.</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Removing a Role-Change Seam With No Callers Left</title><link>https://tech.rebounder.jp/en/posts/dormant-privilege-escalation-seam-removed/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/dormant-privilege-escalation-seam-removed/</guid><description>Forgetting to delete an unused privilege-changing function leaves an attack surface: it wrote any role and any school ID into IdP claims, with no callers left.</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Phone Numbers Garble When Copied From a pdf-lib PDF</title><link>https://tech.rebounder.jp/en/posts/pdf-lib-fontkit-gsub-digit-garbling/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/pdf-lib-fontkit-gsub-digit-garbling/</guid><description>Embedding NotoSansJP through fontkit into pdf-lib garbles digits on copy and pdftotext. GSUB picks glyphs the ToUnicode CMap has no entry for.</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Remounting a Form by key Resets Uncontrolled Inputs</title><link>https://tech.rebounder.jp/en/posts/react-key-remount-resets-uncontrolled-input/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/react-key-remount-resets-uncontrolled-input/</guid><description>With &lt;form key={formGen}&gt; remounting on every submit, inputs given only defaultValue reset on the resubmit right after a validation error, saving the default.</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Carrying a creative_id Revived an Ended Placement</title><link>https://tech.rebounder.jp/en/posts/renewal-creative-id-revives-ended-placement/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/renewal-creative-id-revives-ended-placement/</guid><description>Status rolls back when several batches run on the same day: renewal keeps creative_id on both rows, so another batch flips the ended one back to booked.</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Two Migrations Claimed the Same Sequence Number</title><link>https://tech.rebounder.jp/en/posts/duplicate-migration-sequence-number/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/duplicate-migration-sequence-number/</guid><description>Two feature branches both created migration 0035. Both applied to production as idempotent SQL, but a fresh database run in order has no guaranteed sequence.</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A staging Default in env Deleted Production Images</title><link>https://tech.rebounder.jp/en/posts/env-default-bucket-leaks-across-environments/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/env-default-bucket-leaks-across-environments/</guid><description>Leave another environment&apos;s bucket as an env var&apos;s fallback and that value gets written into the production database, vanishing the day staging is destroyed.</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Half-Controlled Forms Silently Revert on Resubmit</title><link>https://tech.rebounder.jp/en/posts/react-partial-controlled-fields-silent-revert/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/react-partial-controlled-fields-silent-revert/</guid><description>React 19&apos;s &lt;form action&gt; resets uncontrolled inputs to defaultValue whether it succeeded or not. Control only some fields and the rest revert silently.</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Linking Everyone to a Tenant-Only Feature Gave 502</title><link>https://tech.rebounder.jp/en/posts/unconditional-link-to-tenant-only-pdf-feature/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/unconditional-link-to-tenant-only-pdf-feature/</guid><description>The application page always showed a PDF copy link to a route implemented for one tenant type only. The other side got a 502, though nothing had failed.</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A CHECK Rewrite Erased Another Branch&apos;s Value</title><link>https://tech.rebounder.jp/en/posts/check-constraint-rewrite-drops-branch-value/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/check-constraint-rewrite-drops-branch-value/</guid><description>Rewriting a PostgreSQL CHECK constraint with DROP then ADD silently removes values another branch added. share_links.kind lost receipt, with no migration error.</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A 23503 FK Violation Disguised as a Conflict</title><link>https://tech.rebounder.jp/en/posts/fk-violation-masked-as-conflict/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/fk-violation-masked-as-conflict/</guid><description>An operator ad submission failed in production and was reported as a different error — &quot;conflicted with another operation&quot;. The real cause: foreign key 23503.</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>auth/invalid-password: App Allowed Shorter Passwords</title><link>https://tech.rebounder.jp/en/posts/idp-password-min-length-mismatch/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/idp-password-min-length-mismatch/</guid><description>App minimum password length (4) was below Identity Platform&apos;s (6), so createUser returned auth/invalid-password uncaught: an error boundary, not a form error.</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Missing force-dynamic Froze a Flag Flip Behind Static HTML</title><link>https://tech.rebounder.jp/en/posts/nextjs-static-prerender-hides-flag-flip/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/nextjs-static-prerender-hides-flag-flip/</guid><description>Enabling teacher login changed nothing on screen. With no dynamic API call, Next.js prerendered the route at build time and the CDN cached it for a year.</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A UI Freeze Without a Server Check Is Not a Freeze</title><link>https://tech.rebounder.jp/en/posts/ui-freeze-not-enforced-server-side/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/ui-freeze-not-enforced-server-side/</guid><description>Editing disabled in the UI but the API does not validate: a direct POST could rewrite targeting while the update path checked only &quot;live&quot;, not &quot;bought out&quot;.</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>An Android Foreground Service Can Die Without Crashing</title><link>https://tech.rebounder.jp/en/posts/android-service-dies-without-crashing/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/android-service-dies-without-crashing/</guid><description>Guarding only pollOnce() is not enough. An exception in delay or the backoff calculation exits while(true) quietly, stopping the work while the app lives on.</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Enabling a Cloud Run Job Fails With SecretsAccessCheckFailed</title><link>https://tech.rebounder.jp/en/posts/cloud-run-job-secret-iam-race/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/cloud-run-job-secret-iam-race/</guid><description>A Cloud Run Job and its secret_accessor IAM in one Terraform apply is a race: creation-time validation runs before IAM propagates. Ordering it with depends_on.</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Routing Scanned PDFs to Gemini by Chars per Page</title><link>https://tech.rebounder.jp/en/posts/gemini-pdf-ocr-fallback-threshold/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/gemini-pdf-ocr-fallback-threshold/</guid><description>Scanned PDF text extraction fails: pdfjs-dist returns a near-empty text layer. Below a per-page char threshold, send bytes to Gemini as an OCR fallback part.</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Auth Middleware Redirects robots.txt to the Login Page</title><link>https://tech.rebounder.jp/en/posts/nextjs-middleware-robots-redirect/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/nextjs-middleware-robots-redirect/</guid><description>Middleware that sends unauthenticated users to /login tends to treat robots.txt the same way. Crawlers get a 307 and the Lighthouse SEO audit fails.</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Astro 7 Breaks Content Collections in Three Places</title><link>https://tech.rebounder.jp/en/posts/astro-legacy-content-config/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/astro-legacy-content-config/</guid><description>Upgrading Astro fails with LegacyContentConfigError. Three things changed at once: where the config file lives, the required loader, and the render API.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>drizzle-kit migrate Does Not Apply Hand-Written SQL</title><link>https://tech.rebounder.jp/en/posts/drizzle-migrate-skips-sql/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/drizzle-migrate-skips-sql/</guid><description>Migrations succeed but RLS policies and audit triggers are missing in production. drizzle-kit migrate runs only drizzle-generated DDL.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Your First Dev Board Depends on What You&apos;ll Build</title><link>https://tech.rebounder.jp/en/posts/first-dev-board/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/first-dev-board/</guid><description>ESP32, Raspberry Pi and FPGA cover completely different ground. A thing that communicates, a small computer, or learning circuits — that is the choice.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Three Errors You Actually Hit Connecting Actions to GCP</title><link>https://tech.rebounder.jp/en/posts/gcp-workload-identity-errors/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/gcp-workload-identity-errors/</guid><description>Workload Identity Federation splits configuration across three layers and impersonation fails if any is missing. The three real errors, in order.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Gemini Thinking Tokens Eat maxOutputTokens</title><link>https://tech.rebounder.jp/en/posts/gemini-thinking-budget-hang/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/gemini-thinking-budget-hang/</guid><description>A chat AI hung on &quot;thinking&quot; in production only. Gemini&apos;s thinking tokens eat the maxOutputTokens budget, so the response ends empty before output starts.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>The JMA Evening Update Nulls Today&apos;s Temperature</title><link>https://tech.rebounder.jp/en/posts/jma-evening-forecast-temp-null/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/jma-evening-forecast-temp-null/</guid><description>Japan&apos;s JMA forecast API drops today&apos;s temperature in the 17:00 update. Upsert it straight through and the morning&apos;s value is overwritten with null.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>FLAG_KEEP_SCREEN_ON Not Working on Android: The Screensaver</title><link>https://tech.rebounder.jp/en/posts/keep-screen-on-daydream/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/keep-screen-on-daydream/</guid><description>An always-on Android display still goes black with FLAG_KEEP_SCREEN_ON set. The most likely cause is the screensaver, and settings put resets on every reboot.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Next.js Bundling a wasm Package Breaks Only in Production</title><link>https://tech.rebounder.jp/en/posts/nextjs-wasm-bundling-broken/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/nextjs-wasm-bundling-broken/</guid><description>A WASM library for PDF generation got bundled by Next.js and broke in production with a path type error. Bundling changes how the wasm relative path resolves.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>SECURITY DEFINER Fails in Production: the Executing Role</title><link>https://tech.rebounder.jp/en/posts/security-definer-owner-role/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/security-definer-owner-role/</guid><description>CI passes but production gets nothing from a SECURITY DEFINER function. The owner is whoever ran the migration, and it cannot bypass RLS.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>The Still-Frame Threshold Depends on Bit Depth</title><link>https://tech.rebounder.jp/en/posts/static-frame-threshold-bitdepth/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/static-frame-threshold-bitdepth/</guid><description>Detecting still frames with tblend and signalstats: the YAVG threshold scales with luma range, so 4.8 from 12-bit material breaks entirely on 10-bit.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Conditional UPDATE Needs error, Not Just data</title><link>https://tech.rebounder.jp/en/posts/supabase-update-error-swallowed/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/supabase-update-error-swallowed/</guid><description>supabase-js returns data:null with error when a conditional UPDATE hits no row. Read only data and a swallowed write failure is indistinguishable from a no-op.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>terraform enabled = false Cannot Tear Down an Env</title><link>https://tech.rebounder.jp/en/posts/terraform-enabled-false-cannot-destroy/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/terraform-enabled-false-cannot-destroy/</guid><description>With an enabled flag on every module, flipping them all to false to fold an environment fails with Invalid template interpolation value. Only destroy works.</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>How I Settled on Splitting AI Coding Tools</title><link>https://tech.rebounder.jp/en/posts/ai-coding-tools/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/ai-coding-tools/</guid><description>Results from actually splitting work between Claude Code, Cursor, Codex and Gemini: complex development, quick builds, and a separate everyday companion.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>A Prompt Template for Mass-Producing Thumbnails</title><link>https://tech.rebounder.jp/en/posts/ai-eyecatch-template/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/ai-eyecatch-template/</guid><description>Rather than starting over each time: subject large, title band at the bottom, tone fixed. Swap only the subject and the title. Where Japanese text breaks down.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Cloud Run Jobs Freeze Their Image</title><link>https://tech.rebounder.jp/en/posts/cloud-run-job-image-frozen/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/cloud-run-job-image-frozen/</guid><description>You fixed the code, committed, and re-ran the job. Nothing changed. The image is pinned in the job definition until you bump the tag and apply.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Writing 3D Models as Code Instead of Mouse Work</title><link>https://tech.rebounder.jp/en/posts/code-cad-3dprint/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/code-cad-3dprint/</guid><description>Write dimensions as numbers in OpenSCAD and Python and let equations decide the shape. Change a parameter for a new size, and diff the design in git.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Why I Chose the DE10-Lite as a First FPGA Board</title><link>https://tech.rebounder.jp/en/posts/de10-lite-fpga-intro/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/de10-lite-fpga-intro/</guid><description>Switches, LEDs and a 7-segment display are on board, so a circuit runs with no external wiring, and the syntax is close to C. Those two are what helped.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>DeepL and Whisper Quietly Save Time</title><link>https://tech.rebounder.jp/en/posts/deepl-whisper/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/deepl-whisper/</guid><description>Neither is flashy, but both work. English is faster if you draft in Japanese first, and transcription run locally never leaves the machine.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Splitting Personal-Project Infrastructure by Use</title><link>https://tech.rebounder.jp/en/posts/dev-infra-choice/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/dev-infra-choice/</guid><description>How to choose between Vercel, Firebase, Supabase and GCP. Starting with the easy end and widening when you need to actually moves faster.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Heat and Battery Are a Choice on a Dev Laptop</title><link>https://tech.rebounder.jp/en/posts/dev-laptop-heat-battery/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/dev-laptop-heat-battery/</guid><description>Using a ThinkPad X1 Carbon for development, cool running and battery life do not coexist. The power mode makes you pick one.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>ESP32 Web Serial API: Live Sensor Data in Next.js</title><link>https://tech.rebounder.jp/en/posts/esp32-web-serial/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/esp32-web-serial/</guid><description>The Arduino IDE serial monitor is just numbers scrolling past. Here is the Next.js and Web Serial API setup that turns it into a browser dashboard.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Building the Same App on Firebase and Supabase</title><link>https://tech.rebounder.jp/en/posts/firebase-to-supabase/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/firebase-to-supabase/</guid><description>How to choose a backend for personal projects: Firebase for speed to launch, Supabase for freedom. What rebuilding the same app on both made plain.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Pick a First 3D Printer on Assembly and Levelling</title><link>https://tech.rebounder.jp/en/posts/first-3d-printer/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/first-3d-printer/</guid><description>What defeats beginners is not printing but assembly and bed levelling. Requiring 95% pre-assembled and automatic levelling shortens the road to a first print.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Running a Google TV Kiosk for Several Months</title><link>https://tech.rebounder.jp/en/posts/googletv-kiosk-ops/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/googletv-kiosk-ops/</guid><description>Making an Android device into signage that never falls over is a power and permissions problem, not a display one. Device Owner, silent failures, timers.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Figma Is Enough for a Logo and a Business Card</title><link>https://tech.rebounder.jp/en/posts/illustrator-to-figma/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/illustrator-to-figma/</guid><description>Figma is a UI tool by design, but being vector it holds up perfectly well at the level of a logo or a business card. Where the dedicated tool still wins.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Running a Local LLM with Ollama and Building RAG</title><link>https://tech.rebounder.jp/en/posts/local-llm-rag/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/local-llm-rag/</guid><description>Where you would rather not send data to an external API, a local LLM is realistic. Running Qwen on Ollama, and why retrieval matters more than the model.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Two Settings to Change When Supports Won&apos;t Come Off</title><link>https://tech.rebounder.jp/en/posts/orcaslicer-support/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/orcaslicer-support/</guid><description>OrcaSlicer prints well on defaults. What breaks beginners is supports: switch to tree type and lower the density, and they peel off without damage.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Face Recognition on a Raspberry Pi 5 Hits a Speed Wall</title><link>https://tech.rebounder.jp/en/posts/pi5-face-recognition/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/pi5-face-recognition/</guid><description>face_recognition plus a CSV file is enough to make face recognition work. But it takes about 15 seconds per person, and a queue forms as soon as numbers grow.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Building a Power Factor Meter With a Raspberry Pi Pico</title><link>https://tech.rebounder.jp/en/posts/pico-power-meter/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/pico-power-meter/</guid><description>Power factor comes from the phase difference between voltage and current. A clamp sensor gets the waveform and the Pico does the maths.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>What Stops You First in Quartus Is the Setup</title><link>https://tech.rebounder.jp/en/posts/quartus-first-traps/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/quartus-first-traps/</guid><description>The programmer is not recognised, correct code does nothing because a pin assignment is missing, and the 7-segment lights on 0. Three first traps.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Google TV or Raspberry Pi for a Signage Device</title><link>https://tech.rebounder.jp/en/posts/signage-android-vs-raspi/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/signage-android-vs-raspi/</guid><description>For an always-on display, Google TV and a Raspberry Pi take opposite design philosophies. Results from running both, and the storage that matters.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Reading a SwitchBot Motion Sensor Over BLE Directly</title><link>https://tech.rebounder.jp/en/posts/switchbot-ble-direct/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/switchbot-ble-direct/</guid><description>SwitchBot&apos;s motion sensor assumes a Hub and the cloud, but receiving its BLE advertisements directly keeps it all local. Three points and one silent trap.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Task Management Sticks When Entry Has No Friction</title><link>https://tech.rebounder.jp/en/posts/todoist-natural-language/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/todoist-natural-language/</guid><description>Once Todoist could be driven from an AI in natural language, tasks started accumulating without stopping work. Splitting the storing side from the doing side.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Separate the Machine You Touch Hardware With</title><link>https://tech.rebounder.jp/en/posts/two-laptops-hardware-dev/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/two-laptops-hardware-dev/</guid><description>Carrying two laptops was risk management, not luxury. Serial-chip drivers and ports, and separating work that can break things from data you cannot lose.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Three Vercel Traps I Hit After Going Live</title><link>https://tech.rebounder.jp/en/posts/vercel-deploy-traps/</link><guid isPermaLink="true">https://tech.rebounder.jp/en/posts/vercel-deploy-traps/</guid><description>Deploying to Vercel is the easy part. The alias not following the newest build, the public URL demanding a login, and not appearing in search are what you miss.</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item></channel></rss>