Release Notes
The story of BudgetBuddy, one commit at a time.
Changelog Lite
BudgetBuddy is in live beta. Current focus: - Reliability - Data safety - Billing - Buddy Cloud What changed: - Buddy Cloud is the signed-in encrypted protection path. - Free accounts include two active Buddy 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. - Public website SEO, legal-page metadata, canonical links, sitemap, robots.txt, and social previews were cleaned up. Important: - Keep your Buddy Cloud recovery key. - BudgetBuddy 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.
BudgetBuddy 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?
At a glance by tag
Features
Buddy Cloud, version history, Premium support, CSV import/export, calendar workflow, and richer budget sections moved into live beta.
Security
Zero-readable-budget sync, recovery-key guardrails, device/session controls, reset safety, and privacy-minimal metadata were hardened.
UI/UX
Account management, calendar placement, category ordering, savings/debt surfaces, recent actions, footer pages, legal pages, and SEO metadata were cleaned up.
Performance
GitLab-to-Cloudflare deployment, sync timing visibility, viewport repair, and load-state behavior were stabilized for beta use.
Fixes
Blank sign-in recovery, graceful sign-out, OAuth signup copy, avatar fallback, income/savings math, and destructive transaction flows were corrected.
Live Beta Honesty Report
Beta testing is open and intentionally honest
BudgetBuddy is being tested with real budgets, real sign-ins, real Buddy Cloud 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.
Live data-loss scare turned into Buddy Cloud 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. Buddy Cloud 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.
Data safety moved ahead of feature expansion
Auth, billing, Buddy Cloud, 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.
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 BudgetBuddy is good enough that users want to help fund reliability, billing, Buddy Cloud, and infrastructure. If it cannot pay for itself, development may stop instead of growing into an unsupported product.
v1.0 Production Report
Buddy Cloud Sync moved into v1 production prep
Buddy Cloud is now the core free backup and sync path for BudgetBuddy. 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 Buddy Cloud
Free Tier now supports two active synced browsers/devices at a time. Premium unlocks unlimited Buddy Cloud device syncs. 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 Buddy Cloud
Buddy Cloud 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 Buddy Cloud 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 Buddy Cloud. PIN/passkey-protected local key storage is marked as a top v1.1 priority.
Priority Recovery Tools
Added guided Buddy Cloud Recovery Help with human-readable sync status, recovery-key checks, version-conflict guidance, device-limit guidance, diagnostic export routing, and safe reset direction. BudgetBuddy 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 Buddy Cloud replaces destructive account deletion
The lost-key recovery path now deletes the encrypted Buddy Cloud 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 Buddy Cloud 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 BudgetBuddy 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, Buddy Cloud 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 Buddy Cloud detects competing changes on another device.
Account management modal flow polished
Buddy Cloud 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.
Buddy 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 Buddy Cloud sync slot hashes that already enforce the Free limit. If a slot has no active browser match, the Devices modal shows it as an unmatched sync slot with a release action, and old unmatched slots are automatically released after 2 hours. 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 Buddy Cloud 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.