Release Notes
The story of Zam!, one commit at a time.
Changelog Lite
Zam! is in live beta. Current focus: - Reliability - Data safety - Billing - Cloud Sync What changed: - Cloud Sync is the signed-in encrypted protection path. - Free accounts include two active Cloud Sync slots. - Premium adds unlimited sync slots and expanded encrypted version history. - Version History can recover encrypted non-empty budget snapshots when available. - Sign-out, reset, device, conflict, and recovery flows were hardened after beta testing. - CSV import/export, calendar workflow, and richer budget sections are live beta. - Gift-card payment method and balance tracking are live in the app Add flow. - Gift-card merchant hints now use a full local metadata cache so merchant searches stay on-device. - Gift cards can be removed from the Add More tracker while Expense and Deposit stay as core controls. - App Settings was redesigned into a clearer dashboard with grouped cards, segmented controls, and local-data danger-zone wording. - Public marketing rebrand started: Zam! name, temporary Z! mark, Cloud Sync wording, and zambudget.com contact addresses are now visible on the Zam website. - Cloud Sync naming was restored to the plain original label instead of a product-branded sync name. - The app login page now uses Zam! branding for the title, logo, account messages, beta signup copy, and footer. - App footers and support pages now use Help Center, Guides, and Contact Us routing, with social channels hidden until public handles are ready. - The Cloudflare Wrangler target was renamed to zambudget-website and now serves the Zam marketing domain. - GitLab-facing names now use zambudget-app and zambudget-website to reduce confusion during the rebrand. - The website Worker now attaches zambudget.com and www.zambudget.com only; legacy marketing custom domains were removed. - Header, footer, signup, demo, billing, and guide links now send visitors to app.zambudget.com instead of the old app domain. - The main app rebrand now carries Zam! through the signed-in shell, static app pages, safety dialogs, Cloud Sync recovery copy, Premium billing copy, exports, diagnostics, privacy, terms, support, and account-deletion language while preserving legacy technical identifiers. - The homepage comparison was reframed around why someone would switch to Zam! instead of direct app-versus-app claims. - The homepage comparison now frames Zam! as planning-focused budgeting, adds forecasting to the premium-platform comparison, and keeps shared-budgeting claims out until the feature is real. - Homepage comparison tables now label the product as Zam! Budget App for clearer first-visit context. - Homepage comparison now uses a Big guys / Other guys switch so visitors see one comparison table at a time. - Homepage FAQ was tightened into eight short accordion answers with a two-column desktop layout and single-column mobile layout. - Accessibility Statement now reads like a living review practice with WCAG target wording, testing scope, known limitations, reporting guidance, and a last-reviewed date. - Public GitLab readiness cleanup added README, security, MIT license, and public-readiness docs, removed internal notes/artifacts, and clarified source posture while the public GitLab route remains a coming-soon link. - Premium copy now states plainly that core budgeting is free while Premium helps fund sync, shared budgeting, reports, planning tools, support, and continued development. - Public website search indexing is enabled for zambudget.com with Zam canonicals, metadata, structured data, robots, sitemap, and a positive SEO audit gate. - The website Worker now runs before static assets so www.zambudget.com can redirect to zambudget.com before serving pages. - Privacy, Cookie Policy, and Trust Stack copy now disclose Cloudflare aggregate delivery, security, performance, and web-analytics telemetry without changing the no-ad-tracking or no-data-brokerage stance. - Public-safe GitLab runbooks now give future chats and rebuild work a clear starting point, including architecture, deployment, DNS, Cloudflare, Supabase, backups, disaster recovery, cutover, and rebuild-from-GitLab notes. - Public contact routing now lists support, billing, legal, accessibility, and Zam! mail-only office address, plus public-channel links. - Public website footer and legal pages were cleaned up with a real Partnerships page, a fuller Cookie Policy, and Billing/Legal contact routing moved into a dedicated Support section. - Trust & Privacy Stack now names Proton Mail as the public email provider and explains email metadata limits before users attach diagnostics. - The public social mailbox route is paused; public collaboration now routes through support or Andrew's public LinkedIn profile. - The no-reply auth email was removed from public contact routing; sign-in and magic-link help now goes through Support. - Public contact and legal pages now label the Zam! office address as mail-only and use the two-line ZIP+4 mailing format. - Public channel routing now removes TikTok and social email, keeps LinkedIn pointed to Andrew Struck, and makes the GitLab coming-soon link active against the closed app repository page. - The homepage footer now keeps the Zam! copyright and MIT License line under Contact in one line below the GitLab coming-soon link. - The homepage Contact footer now uses compact SVG icon links for support email, LinkedIn, and GitLab below Contact Us. - Website feedback Worker email routing is configured for support@zambudget.com, with mailto fallback retained until Cloudflare Email Service accepts the Zam sender route. - Help Center and Guides now separate support routing from detailed instructions. - Public source-code posture was narrowed: the marketing/docs surface can be public, while app, backend, sync, and infrastructure code remain private during beta. - The homepage footer was simplified into Product, Support & Legal, and Contact columns, with the bottom area reduced to the Zam! logo and copyright. - The homepage live beta signup banner was reduced into a compact strip so it supports the hero call-to-action without repeating the full hero weight. - Support documentation now includes magic link sign-in, recovery keys, billing, account deletion, diagnostics, and what support can and cannot recover. - Support content was split into Help Center, Guides, Trust & Privacy Stack, and Contact Us pages so users can find help without reading one oversized support article. Important: - Keep your Cloud Sync recovery key. - Zam! cannot decrypt or recover synced budget data without that key. - Browser-only budgets have no recovery support if local browser storage is lost. - Premium helps pay for infrastructure and continued development.
Zam! is in live beta. The goal now is honest validation: is the product useful enough to keep entering budgets, stable enough to trust with real data, and valuable enough that Premium support can at least cover infrastructure and continued development time?
Live Beta Honesty Report
Settings modal redesigned as a dashboard
App Settings now groups defaults, budget rules, appearance, data/privacy tools, and local erase actions into clearer cards with segmented controls, a local-only danger zone, and a sticky Save/Cancel footer that only shows an unsaved-changes notice after edits.
Public search indexing enabled
The marketing site now publishes indexable Zam metadata, extensionless canonical URLs, Open Graph and Twitter previews, structured data, a populated sitemap, robots.txt sitemap discovery, and a positive SEO audit while the app domain remains noindex.
Marketing rebrand preview started
The public website now uses the Zam! name, a temporary Z! mark, Cloud Sync terminology, and zambudget.com public contact addresses while preserving app behavior during the rebrand.
Cloud Sync naming restored
The sync feature now uses the plain Cloud Sync label across public website copy instead of the temporary product-branded sync name.
App login page rebranded
The app login page now shows Zam! in the page title, logo text, sign-in and signup messages, account-deleted confirmation, and footer while auth behavior stays unchanged.
App footer and support routing synced
The app shell and standalone app pages now use Help Center, Guides, and Contact Us links, hide unready social channels, and remove repository-posture copy from compact footer areas.
Cloudflare Worker target renamed
The marketing Wrangler config and GitLab deploy guardrails now target zambudget-website so the website Worker name matches the Zam deployment.
GitLab naming aligned
GitLab-facing app and website metadata now use zambudget-app and zambudget-website naming so the rebrand is clearer before the project paths are renamed in GitLab.
Website domain cutover started
The website Worker now attaches zambudget.com and www.zambudget.com directly. Legacy marketing custom domains were removed so the website no longer serves from the old brand domain.
App links moved to app.zambudget.com
Header buttons, footer launch links, signup CTAs, demo links, Premium entry points, and support guides now point to the Zam app domain.
Main app rebrand completed
The signed-in app shell, static app pages, safety dialogs, Cloud Sync recovery copy, Premium billing copy, export filenames, diagnostic reports, privacy, terms, support, and account-deletion language now use Zam! branding while legacy storage keys, Supabase table names, and compatibility identifiers remain unchanged.
Homepage comparison reframed
The homepage now answers why someone would choose Zam! with planning-focused switching guidance for users coming from premium finance platforms or simpler budgeting apps, without direct app-versus-app superiority claims.
Comparison table labels clarified
The homepage comparison tables now use Zam! Budget App as the product column label so first-time visitors and search engines get clearer product context.
Homepage comparison switch added
The switching comparison now uses two buttons, Big guys and Other guys, so visitors can view either the premium-platform table or the simple-app table without seeing both at once.
Homepage FAQ tightened
The FAQ now keeps the eight core who/what/when/where/why/free/privacy/update questions, uses one-sentence answers, and presents as a two-column accordion on desktop that stacks on mobile.
Accessibility Statement expanded
The Accessibility page now explains Zam!'s WCAG baseline, practical WCAG 2.2 review direction, supported accessibility practices, review checks, beta limitations, issue-reporting details, and last-reviewed date without claiming a formal audit.
Public GitLab readiness tightened
The marketing/docs repo now has a README, security contact guidance, MIT license notice, and public-readiness checklist. Internal support notes and the old theme-reference artifact were removed or converted to public-safe documentation, and public GitLab routing stays labeled as coming soon until source posture changes.
Premium value copy clarified
The Premium section now says core budgeting is free and explains that Premium helps fund sync, shared budgeting, reports, planning tools, support, and continued development without relying on ads, trackers, or selling budget data.
Planning-focused comparison refined
The homepage comparison now uses Premium Platforms and Simple Apps labels, adds forecasting to the premium-platform table, and avoids shared-budgeting claims until that capability is actually shipped.
Public contact and channel routing refined
The website now publishes dedicated support, billing, legal, and accessibility mailboxes plus the Zam! mail-only office address. Dev-test remains internal, social email and TikTok are not public routes, LinkedIn points to Andrew Struck, and the GitLab coming-soon link opens the closed app repository page. Sign-in and magic-link questions route through Support because the auth email is a no-reply/system address.
Source-code posture narrowed
The public website and docs can remain visible for trust and transparency, while the Zam! app, backend, Cloud Sync architecture, and infrastructure configuration stay private during beta.
Homepage footer simplified
The homepage footer now keeps Product, Support & Legal, and Contact as the main link columns, alphabetizes Product and Support & Legal links, uses SVG icon links for support email, LinkedIn, and GitLab under Contact Us, and keeps the one-line Zam! copyright and MIT License notice under the icons.
Support information architecture split
The oversized Support article is now divided into Help Center, Guides, Trust & Privacy Stack, and Contact Us. The public contact page stays focused on visitor-facing mailboxes and keeps dev-test/internal routing off the site.
Partnerships and cookie-policy pages filled in
The marketing footer now links to a real Partnerships page, the Cookie Policy explains browser storage and provider-session behavior, and Billing/Legal contacts live in a dedicated Support section instead of cluttering the legal footer.
Proton Mail email-provider disclosure added
The Trust & Privacy Stack now names Proton Mail as the public mailbox provider, links back to Proton's official pages for brand transparency, and reminds users to review diagnostics and keep recovery keys, magic links, passwords, card numbers, gift card numbers, PINs, and raw budget exports out of email.
Social mailbox route paused
The Contact Us page no longer publishes the social mailbox or TikTok placeholder. Public collaboration now routes through support or Andrew's public LinkedIn profile until dedicated launch channels are ready.
Beta testing is open and intentionally honest
Zam! is being tested with real budgets, real sign-ins, real Cloud Sync recovery, and real billing paths. Feedback matters now because the next decision is practical: keep developing if users find it useful enough and it can at least pay for its infrastructure, or scrap it if the time-to-value and support load do not make sense.
Gift-card payment method and balance tracker added
The app Add flow now includes Gift Card as a payment method. Users can save a gift-card number, total amount, current balance, and expiration date, then Zam! subtracts tracked gift-card expenses and previews the remaining balance before save.
Local-only gift-card merchant metadata cache added
Gift-card merchant hints now download as one full static bundle, cache locally, and search on-device so merchant search terms and suggestion selections are not sent to a server.
Gift-card removal added
Saved gift cards can now be removed from the Add More gift-card tracker without changing the core Expense and Deposit controls.
Live data-loss scare turned into Cloud Sync recovery hardening
Beta testing exposed a serious edge case where secure sign-out could clear local data and a fresh sign-in could land on a blank budget while the usable copy lived in Version History. Cloud Sync now treats blank local sign-ins as cloud-priority recovery, preserves a secure-sign-out recovery marker, and can recover the newest non-empty encrypted saved version when needed.
Trusted Cloud Sync browser key added
After a successful setup or recovery-key import, Zam! can store a non-extractable WebCrypto key in IndexedDB so the same browser can keep syncing after refresh without storing the raw recovery key in localStorage. The trusted key stays local to the browser, is not part of Account > Devices records, and cannot be displayed as the recovery-key text.
Data safety moved ahead of feature expansion
Auth, billing, Cloud Sync, secure sign-out, rough logout, conflict review, and recovery-key handling are now treated as production-critical work. New feature work is intentionally secondary until these paths keep passing real beta use.
Provider metadata legal copy clarified
The legal pages now plainly distinguish Zam-controlled privacy-minimal records from infrastructure, authentication, email, payment, and security-provider metadata. The disclosure now covers IP-related logs, approximate country or region metadata, user agent/browser hints, request metadata, OAuth provider metadata, delivery logs, billing records, retention limits, lawful requests, and the fact that encrypted Cloud Sync contents remain unreadable without the recovery key.
GitLab and Cloudflare deployment path stabilized
The project moved into GitLab with Cloudflare pulling from the main branch for deploys. This gives beta fixes a repeatable path from local patch, to commit, to push, to live Cloudflare deployment.
Calendar, category, savings, debt, and recent-flow polish continued
The calendar now supports the budget workflow without interrupting it. Categories gained ordering controls, savings and debt surfaces were tightened, and transaction slide actions were adjusted so destructive actions require clearer intent.
Premium support is framed as project sustainability
Premium is not being positioned as hype. The beta question is whether Zam! is good enough that users want to help fund reliability, billing, Cloud Sync, and infrastructure. If it cannot pay for itself, development may stop instead of growing into an unsupported product.
Premium moved to direct subscription pricing
Premium pricing is now presented as a direct $3.99/month subscription. Core budgeting and two active Cloud Sync slots remain free, while Premium is for users who want unlimited active sync slots, expanded encrypted version history, and to support continued development.
v1.0 Production Report
Cloud Sync moved into v1 production prep
Cloud Sync is now the core free backup and sync path for Zam! It supports encrypted cloud vault upload/download, conflict handling, recovery-key import, and a reset path for users who lose the recovery key and need to start their cloud vault over.
Multi-Device Sync Plus added to Cloud Sync
Free Tier now supports two active synced browsers/devices at a time. Premium unlocks unlimited Cloud Sync slots. The app uses privacy-minimal sync slot hashes and timestamps for the Free limit, without storing device names, user agents, IP-derived locations, or readable budget data.
Cloud Version History added to Cloud Sync
Cloud Sync now keeps encrypted vault snapshots so users can restore an earlier saved budget version, such as a previous day. Free accounts keep the newest encrypted safety snapshot, while Premium keeps the newest 10 encrypted snapshots. Snapshots are encrypted client-side with the same recovery-key model before storage, and restoring a snapshot happens locally before uploading the restored encrypted vault as current.
Zero-readable-budget cloud architecture
Budget contents are encrypted in the browser before sync using AES-GCM. Transactions, balances, budgets, categories, descriptions, notes, and amounts are inside the encrypted vault payload. The server keeps only operational metadata needed for sync, such as timestamps, schema/encryption version, and checksum.
Recovery key safety model
First-time Cloud Sync setup now starts a 72-hour recovery-key grace period instead of blocking onboarding. Recovery-key reveal now requires a short login-verification guardrail when Supabase supports it, falls back to local unlock when needed, auto-locks after 5 minutes or tab hide, and still enforces key safety before risky actions such as clearing the browser, signing out all devices, or resetting Cloud Sync. PIN/passkey-protected local key storage is marked as a top v1.1 priority.
Priority Recovery Tools
Added guided Cloud Sync Recovery Help with human-readable sync status, recovery-key checks, version-conflict guidance, device-limit guidance, diagnostic export routing, and safe reset direction. Zam! still cannot recover or decrypt a lost recovery key, but the app now gives users clearer next steps before they panic or reset unnecessarily.
Reset Cloud Sync replaces destructive account deletion
The lost-key recovery path now deletes the encrypted Cloud Sync vault and encrypted version-history snapshots for the signed-in account, keeps the Supabase login intact, clears this browser, and lets the user create a fresh vault with a new recovery key. Full auth-user deletion was removed from the normal reset flow after Supabase returned database-level delete errors, and normal Cloud Sync reset no longer depends on billing-profile reads.
Live beta billing guard added
Premium billing now has an explicit config switch. For beta, billingEnabled is false, so Upgrade and billing-portal actions stay visible but cannot redirect to Stripe until checkout, webhooks, portal management, and cancellation paths are intentionally verified for live billing.
Account Management redesign
The account menu now has a left-aligned identity header, local avatar fallback, welcome message, Free Tier/Premium badge, time-of-day greeting, two-row action grid, Devices, Settings, Support, and OAuth-aware password reset visibility.
Time-of-day account greeting
Added a small right-side account badge with Coffee budgeter, Midday money, or Night budgeter based on local browser time. The night state includes a moon icon, glow, and subtle looping starfield animation. The morning Coffee budgeter state now has matching motion with a warm glow, drifting light dots, and a subtle animated coffee icon.
Opt-in local diagnostics
Diagnostics moved into Account Settings and now require explicit confirmation before generating a local JSON report. The report is not uploaded automatically, does not opt users into tracking or future diagnostics, and excludes budget contents, transactions, balances, budgets, categories, descriptions, notes, amounts, recovery keys, access tokens, email, and transaction counts.
Device and session controls simplified
Devices is now focused on session risk and sign-out behavior. Known Zam! browsers are listed using privacy-minimal browser hashes, existing sync slot hash links, and timestamps, with browser-icon rows, right-aligned individual sign-out controls, and a separate full-width Sign Out All Devices action. Logout, revoked-browser cleanup, Cloud Sync reset, and Sign Out All Devices now show a Clearing Session screen while local storage, session storage, accessible cookies, and stale page state are cleared before refresh. Manual upload/download controls only appear when Cloud Sync detects competing changes on another device.
Account management modal flow polished
Cloud Sync account-management dialogs now transition smoothly between Devices, Privacy Details, sign-out confirmations, and Back actions. Device sign-out rows give immediate visual feedback, confirmation screens return users to the Devices list instead of dead-ending the flow, and reduced-motion preferences are respected.
Cloud Sync slot cleanup
Free Tier capacity now shows as sync slots instead of devices, and Account > Devices can map known browser access records to the existing opaque Cloud Sync slot hashes that already enforce the Free limit. Free sync slots now behave like active browser leases: if a browser does not check in for 60 minutes, the slot can be released automatically. The cleanup does not add device names, user agents, IP-derived locations, recovery keys, or readable budget data.
Privacy and legal review notes added
Privacy copy and production notes now distinguish encrypted budget contents from operational metadata. The checklist flags legal review for account/auth records, sync timestamps, schema/encryption version, checksums, billing records, and lawful-provider request language.
OAuth password reset gating
OAuth-only users no longer see the Password tile in Account Management. The reset handler is also guarded directly, so password reset cannot be triggered for accounts that do not have a Supabase email/password identity.
Support page and footer-page headers finalized
Added a dedicated Support page, wired Account Management Support to it, removed broken or disabled public footer actions, and tightened footer-linked page headers so they expose only theme controls, live signed-in status, and a styled Back to App button. Static page headers now inherit the saved theme and accent color from the main app, and footer-linked pages no longer carry the Settings control. The support path points users toward Recovery Help, Devices, Version History, Diagnostics, and the beta support email without asking for recovery keys.
New Features
Deep Drill-Down Views
Click any category to see budget vs. actual spending, inline budget editing (just click the "Budgeted" row), quick emoji shortcuts for fast entry, and a full transaction history - all without leaving the screen.
3-Way Theme Engine
Light, Dark, or follow your OS. The toggle lives in the header and your preference persists across sessions. System preference changes are detected in real-time.
Income Breakdown Panel
A dedicated section that shows where your money comes from - each income source, its total, and its percentage of overall income. Updates instantly as you add transactions.
10 Quick-Add Categories
Housing, Food & Dining, Transportation, Entertainment, Subscriptions, Shopping, Health, Education, Savings, and Debt - all one tap away with preset icons.
Security & Auth
Supabase Authentication
Full email/password auth powered by Supabase. Sessions persist across tabs and browser restarts. Unauthorized users are redirected to the login page - no ghost sessions.
Password Recovery Flow
"Forgot Password?" link on the login page triggers a Supabase email with a secure reset link. Users land on a dedicated reset page to choose a new password. Minimum 6 characters enforced.
Clean Logout & Redirect
Logging out destroys the Supabase session server-side and redirects to login. No stale tokens, no "ghost" logged-in state if someone hits the back button.
UI/UX Polish
Avatar Dropdown Menu
Replaced the clunky "Log In / Sign Up" text links with a single, color-coded avatar circle. Click it to reveal your display name, email, profile editor, and logout - all in a smooth, animated dropdown.
Editable Display Name
Click "Profile" in the avatar dropdown to set a custom display name. Stored in Supabase user_metadata so it syncs across devices. Your avatar initial updates instantly.
Mobile-First Responsive Layout
The dashboard grid collapses cleanly on phones. Quick-add categories reflow to 3 columns. Transaction list is scrollable. Drill-down modal goes full-width. No horizontal scrolling - ever.
Rainbow Accent Bar
That thin gradient strip at the top of the page? It's a 4px tall status symbol. Purple -> Green -> Blue. Subtle, but it ties the whole design together.
Performance
Zero-Dependency Rendering
No React, no Vue, no virtual DOM. Pure vanilla JS with direct DOM manipulation. The result? Sub-50ms renders for hundreds of transactions. The app weighs in at a single HTML file.
Instant Local Persistence
In the original browser-only build, every transaction and category was saved to localStorage immediately. The current signed-in beta uses Cloud Sync as the encrypted recovery path.
Precision Fixes
Fixed: Layout Shift on Browser Back Gesture
When navigating back from the login page using a trackpad swipe or Alt+Left, the browser would restore the page from bfcache with stale layout calculations - causing the entire UI to shift off-center. Fixed by adding a pageshow event listener that detects bfcache restoration and forces a full layout recalculation via display: none -> reflow -> display: ''. Also set scrollRestoration = 'manual' to prevent scroll position conflicts.
Fixed: Custom Categories Missing from Dropdown
The transaction form's category <select> only showed the 12 built-in options. Custom categories were being added to the array but never re-rendered into the dropdown. Fixed by calling updateCategoryDropdown() after every category creation and deletion, and preserving the previously selected value across re-renders.
Fixed: Duplicate Category Creation
Clicking a quick-add button twice would create two identical categories. Fixed by adding a case-insensitive duplicate check (name.toLowerCase()) before pushing to the array. Now shows a toast: "Category already exists!"
Fixed: Delete Category Left Orphan Transactions
Deleting a category removed it from the list but left its transactions floating in the ledger with no matching category. Fixed by filtering out transactions that belong to the deleted category before removing it. The confirmation dialog now tells you exactly how many transactions will be removed.
Fixed: Auth State Ignored on Dashboard Load
The login page set the Supabase session correctly, but the main dashboard had zero Supabase code - it never checked if you were actually logged in. The header always showed "Log In / Sign Up" regardless. Fixed by adding initSupabase() to the DOMContentLoaded handler, which calls sb.auth.getSession() and conditionally renders the avatar or sign-in link.
Fixed: Password Field Cleared on Failed Login
If you typoed your password, the login form cleared both the email and password fields - annoying if you have a long email. Fixed by only clearing the password field on error, keeping the email intact for a retry.
The final beta. Tested by real humans who actually budget. Their feedback shaped every feature in v1.0.
Features
Income Overview Section
Added a visual breakdown of income sources below the main dashboard. Shows each source, its total, and percentage of overall income.
Skip Delete Confirmation
Added a "Don't remind me again" option on delete confirmations for power users who don't want the extra click every time.
Precision Fixes
Fixed: Date Formatting Inconsistency
Some dates showed as "5/31/2026" while others displayed "May 31". Standardized all dates to the friendlier "May 31" format using toLocaleDateString('en-US', {month:'short', day:'numeric'}).
Fixed: Negative Balance Display
When expenses exceeded income, the balance showed as "$-123.45" instead of "-$123.45". The dollar sign was on the wrong side of the minus. Rewrote formatMoney() to handle negative values correctly.