## Summary
- Add `SyncUserToResendListener` to automatically sync users to Resend
contacts on registration
- Add `ResendService` for Resend API interactions
- Add `resend:sync` command to bulk sync existing users
## Changes
- **New**: `app/Listeners/SyncUserToResendListener.php` -
Auto-discovered queued listener
- **New**: `app/Services/ResendService.php` - Service for Resend
contacts API
- **New**: `app/Console/Commands/ResendSyncCommand.php` - Bulk sync
command
- **New**: Tests for listener and command
## Usage
New users are automatically synced on registration. For existing users:
```bash
php artisan resend:sync
```
## Test plan
- [x] New user registration triggers contact sync
- [x] `resend:sync` command syncs all existing users
- [x] Graceful handling when API key is not configured
- [x] Duplicate contacts are handled by Resend (no errors)
## Summary
- Enable the budgets Pennant feature flag for all users by changing the
default from `false` to `true`
## Test plan
- [x] Existing `BudgetFeatureFlagTest` passes (9 tests, 39 assertions)
## Summary
- Fixed hover background color in dark mode to improve visibility and
contrast with chart bars
- Changed from `fill-muted` (oklch(0.269 0 0)) to `fill-white/5` in dark
mode for a lighter, more transparent background
- Resolves issue where hover background was too similar to bar colors in
dark mode
## Changes
- Updated `ChartContainer` component to use `dark:fill-white/5` for the
recharts tooltip cursor in dark mode
- Maintains existing `fill-muted` behavior for light mode
Closes#66
## Summary
- Removed explicit `gap-6` from the mobile bottom navigation bar so
`justify-evenly` distributes items naturally
- Reduced horizontal padding from `px-8` to `px-4` to give items more
room when 5 are present (e.g., when Cashflow and Budgets features are
enabled)
Closes#77
## Test plan
- [x] Verify the bottom nav looks correct with 4 items (Cashflow or
Budgets feature disabled)
- [x] Verify the bottom nav looks correct with 5 items (all features
enabled)
- [x] Confirm items are evenly spaced and none are clipped on small
screens
## Summary
- Fixes automation rules not applying labels when creating transactions
manually or via CSV import
- Eager-loads the `labels` relationship on automation rules in both
`TransactionController` and `HandleInertiaRequests`
- Syncs `label_ids` on the transaction `store` endpoint (was accepted
but never persisted)
- Passes `automationRules` prop through the full component chain:
`index.tsx` → `TransactionActionsMenu` → `ImportTransactionsDrawer`, and
`index.tsx` → `EditTransactionDialog`
- Passes `automationRules` as the missing 5th argument to
`reEvaluateAll()`
Closes#61
## Test plan
- [x] Existing feature tests pass (`php artisan test
--filter=Transaction`, `--filter=AutomationRule`)
- [x] Pint, ESLint, and Prettier all pass
- [x] Manually verify: create a transaction matching an automation rule
with labels → labels are applied
- [x] Manually verify: import CSV with transactions matching rules with
labels → labels are applied
- [x] Manually verify: "Re-evaluate All" applies labels from matched
rules
## Summary
- Adds a structured bug report issue template using GitHub's YAML form
format
- Includes fields for environment, steps to reproduce, expected/actual
behavior, and additional context
## Test plan
- [x] Verify the template appears when creating a new issue on GitHub
- [x] Confirm all form fields render correctly
## Summary
- Added label update support to the single transaction `update()`
endpoint
- Previously, labels could only be updated via the bulk update endpoint
- Now both endpoints support label updates with consistent behavior
## Changes
- **UpdateTransactionRequest**: Added `label_ids` validation (array of
UUIDs that must belong to user)
- **TransactionController@update**: Now handles label updates alongside
other attributes
- Syncs labels when `label_ids` is provided
- Reloads labels relationship for fresh data in events
- Fires single `updated` event after all changes
- **AssignTransactionToBudget listener**: Ensures labels are loaded
fresh after queue serialization
- **Tests**: Added 6 comprehensive tests covering all label update
scenarios
## Behavior
- **Don't send `label_ids`** → labels unchanged (partial update)
- **Send `label_ids: []`** → removes all labels
- **Send `label_ids: [uuid1, uuid2]`** → replaces labels with these
## Testing
When labels are updated, the `TransactionUpdated` event fires and the
transaction is automatically assigned to matching budgets (via queued
listener).
All tests pass (29 tests, 134 assertions).
Fixes the issue where transactions wouldn't appear in budget after
adding a matching label via the single transaction update endpoint.
## Overview
We're excited to introduce budgeting capabilities to Whisper Money! This
feature helps you take control of your finances by setting spending
limits and tracking your progress over time.
## Screenshots
<img width="1316" height="793" alt="image"
src="https://github.com/user-attachments/assets/ac394d36-cded-4ea4-9883-120785e260f1"
/>
<img width="1315" height="907" alt="image"
src="https://github.com/user-attachments/assets/7c682474-5aa7-4388-b626-29b56f5ebbef"
/>
<img width="1315" height="992" alt="image"
src="https://github.com/user-attachments/assets/21eace45-23c6-472d-9aa0-0feb6db3fba4"
/>
## What's New
### Create Flexible Budgets
- Set budgets for specific categories or labels
- Choose from monthly, weekly, bi-weekly, or custom periods
- Set your own budget start date for better alignment with your pay
schedule
### Track Your Spending
- Visual spending charts show how much you've spent vs. your budget
- See at a glance which budgets are on track and which need attention
- View all transactions that count toward each budget
### Smart Budget Management
- **Carry Over**: Unused budget amounts automatically roll into the next
period
- **Reset**: Unused amounts return to your available money pool
- Edit or delete budgets anytime as your needs change
### Easy Access
- New Budgets section in the main navigation
- Quick overview cards showing budget status
- Detailed budget pages with spending history and transaction lists
## How It Works
1. Create a budget by selecting a category or label and setting your
spending limit
2. Your transactions are automatically matched to relevant budgets
3. Track your progress with visual charts and spending summaries
4. Adjust your budgets as needed to stay on track with your financial
goals
This feature is now available behind a feature flag and can be enabled
for users who want to start budgeting their expenses.
https://github.com/user-attachments/assets/a80966de-b282-4ba0-9431-2cfbcfddc023
Every detail is important. Now, when you are about to update the balance
of an account, the current balance is pre-filled, and you can even do
simple math operations.
If you just receive 1,000 dollars, you can just type `+ 1000` and press
enter.
No need to do the maths by your self.
This PR simplifies the IndexedDB synchronization mechanism by removing
individual sync controllers and services, and instead using Inertia.js
shared props to provide data globally across the application.
## Benefits
1. **Simplified Architecture**: Removed complex sync logic for
static/semi-static data (accounts, categories, banks, labels, automation
rules)
2. **Better Performance**: Data is now shared via Inertia props,
eliminating unnecessary API calls and IndexedDB operations
3. **Reduced Complexity**: Significantly reduced codebase size (~2000
lines removed)
4. **Better UX**: Data is immediately available on page load without
waiting for sync operations
5. **Maintainability**: Fewer moving parts means easier to maintain and
debug
## Migration Notes
- Transaction syncing still uses IndexedDB for offline support
- All other data (accounts, categories, banks, labels, automation rules)
is now fetched via Inertia shared props
- Components automatically receive updated data on navigation without
manual sync operations
## Changes
- Moved `setup.sh` to `public/setup.sh` so it's accessible via
`https://whisper.money/setup.sh` for remote users
- Added `wispermoney` wrapper command in root directory for easy local
execution
- Updated README to document the new `wispermoney` command
- Removed duplicate `setup.sh` from root directory
## Benefits
- Remote users can still use: `bash <(curl -fsSL
https://whisper.money/setup.sh)`
- Local developers can now use: `./wispermoney install` (or
start/stop/upgrade)
- Single source of truth - no duplicate setup scripts
- Cleaner project structure
This PR adds a comprehensive setup script that automates the entire
local development setup process.
<img width="1470" height="932" alt="image"
src="https://github.com/user-attachments/assets/b173333a-6605-4fd9-b2e4-4c62d164d048"
/>
### Key Features
- **Automated Setup Script** (`setup.sh`): One-command installation that
handles everything
- **Caddy Integration**: Replaced Traefik with Caddy for simpler SSL
certificate management
- **Automatic Repository Cloning**: Script can be run remotely and will
clone the repo automatically
- **SSL Certificate Management**: Uses mkcert for trusted local
certificates
- **Automatic Hosts Configuration**: Configures /etc/hosts automatically
- **Version Checking**: Warns users when their local copy is outdated
- **Service Management**: Easy commands to start/stop/upgrade services
### Improvements
- Simplified local development setup
- Better SSL certificate handling (no browser warnings with mkcert)
- Updated README with quick start instructions
- Updated environment configuration for Docker
- Added production Dockerfile for CI/CD builds
### Usage
```bash
bash <(curl -fsSL https://whisper.money/setup.sh)
```
After installation, visit https://whisper.money.local