Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
Connect Xero, sync spend and bills, and review expense lines with your team—sign in with Xero, no separate passwords.
FinancePHP · BladeGitHub @alephcomOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Assist with mapping Xero expenses to clients.
Translation pending
Loading the full README.
Read the full README ↗A Laravel app that connects to Xero so your team can link organisations (tenants), sync bank spend and accounts-payable lines, and review expenses in the browser—with Sign in with Xero and organisation-scoped roles.
Stack: Laravel 13, PHP 8.3, Laravel Breeze (Livewire + Volt), Tailwind CSS, Vite.
SyncXeroOrganisationJob), with authorization re-checked when the job runs.composer install
npm install
cp .env.example .env
php artisan key:generate
# Create database/database.sqlite if using SQLite, then:
php artisan migrate
npm run build
For a scripted first-time setup (deps, .env, key, migrate, build): composer run setup.
Set DB_* in .env. SQLite is the default; create database/database.sqlite if it does not exist.
In the Xero developer portal, register one redirect URL used for both OpenID sign-in and accounting OAuth. It must match .env exactly (scheme, host, path):
${APP_URL}/xero/callback — same value as XERO_REDIRECT_URI (see .env.example).| Variable | Purpose |
|---|---|
XERO_CLIENT_ID / XERO_CLIENT_SECRET | Shared by SSO and Connect Xero |
XERO_REDIRECT_URI | Callback for both flows |
XERO_ALLOW_OPEN_SIGNUP | Default false: blocks self-serve sign-up unless the DB has no users yet or the user has a valid invitation. Set true only if you want a public, self-serve app. |
XERO_SSO_SCOPES | OpenID (default openid profile email) |
XERO_SCOPES | Accounting API scopes for sync (offline_access, transactions, contacts, settings, etc.) |
Invitations are sent from the dashboard. Configure MAIL_* in .env. For local dev, MAIL_MAILER=log writes messages to the log.
| Command | Use |
|---|---|
composer run dev | HTTP server, queue worker, log tail, and Vite (recommended) |
php artisan serve | App only |
npm run dev | Vite watch mode |
Use QUEUE_CONNECTION=database (default in .env.example) so sync jobs can run; composer run dev includes queue:listen.
/ or go to /login and Sign in with Xero./orgs/{public_id}/expenses). Route keys use an opaque public_id (ULID), not the internal numeric id.SyncXeroOrganisationJob always includes an initiating user id; handle() verifies that user is still a member of the organisation before calling Xero.php artisan xero:sync {public_id-or-slug} — pass --acting-user={id} with a user who belongs to that org. Optional: --from=YYYY-MM-DD, --to=YYYY-MM-DD, --queue to dispatch instead of running inline.APP_DEBUG=false, APP_URL to your real HTTPS origin, and SESSION_SECURE_COOKIE=true behind TLS.XERO_ALLOW_OPEN_SIGNUP=false unless you intentionally allow anyone to create an account via Xero.CACHE_STORE=database or Redis) for every web server and queue worker. Xero token refreshes and the one-Xero-job-per-organisation lock depend on it.retry_after above the sync job timeout (900s). The default is 960s; lowering it lets a long sync be picked up by a second worker.php artisan queue:restart after each deploy so workers load the new code.Set SEED_TEST_USER=true in .env, then php artisan db:seed. This creates [email protected] (password password) for local/testing only. Normal browser sign-in still uses Xero unless you authenticate in tests with actingAs.
composer run test
Laravel exposes GET /up for load balancers and uptime monitors.
This project is open source under the MIT license. Laravel is MIT licensed as well.