Real financial data is sensitive, hard to share, and usually messy in ways that obscure the features you’re trying to demonstrate. This project uses synthetic data instead — generated once by a deterministic script and committed to the development workflow. Because the random number generator is seeded with a fixed value, every developer who runs the seed script gets identical rows. The data isn’t just random noise either: it was authored with specific financial stories so that every chart type — trends, anomalies, budget comparisons, category breakdowns — has something genuinely interesting to show rather than a flat line or uniform noise.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/astrxnomo/financial-analytics-agent/llms.txt
Use this file to discover all available pages before exploring further.
Running the Seed
Apply the schema first, then run the seed script. Both commands are defined aspnpm scripts in the project root:
db:migrate runs db/migrate.ts, which reads db/schema.sql and applies it via sql.unsafe(). It uses CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS, so running it against an already-initialized database is safe — it won’t drop or recreate anything.
db:seed runs db/seed.ts. It opens a transaction, TRUNCATEs all four tables with RESTART IDENTITY CASCADE, then bulk-inserts departments, categories, transactions (in batches of 500), and budgets. The seed covers 36 months ending at June 2026, producing a few thousand transaction rows and one budget row per department per month (180 budget rows total).
Determinism
The seed usesmulberry32 from agent/lib/rng.ts — a small, fast pseudo-random number generator initialized with the fixed seed 2026. Calling mulberry32(2026) always produces the same sequence of floats regardless of Node version or platform, so rerunning the seed always reproduces the exact same transaction amounts, dates, and descriptions.
rand() in a fixed order for every jitter and random day offset, so inserting rows in a different order or adding conditional branches would shift the sequence. If you modify the seed script, re-verify the integration tests (see Re-seeding below).
Authored Financial Stories
The seeded data contains deliberate patterns that make each analytic meaningful. These aren’t accidental byproducts of the RNG — they were explicitly coded into the generation logic:-
Yearly seasonality + slow multi-year growth trend on revenue. Revenue follows a
sin-wave seasonal curve with a 15% amplitude and compounds at ~1% per month. Trend charts show a clear upward arc with repeating peaks and troughs across all three years. - Subscription revenue compounding faster than the rest of the business, with a recurring ~yearly churn dip. Subscription Revenue grows at 4.5% per month (much faster than the base 1%) and takes a 28% hit every 14 months, simulating a real SaaS churn cycle. A category breakdown over the full 36-month window shows Subscription Revenue expanding its share of total income noticeably relative to the other revenue lines.
- Marketing Advertising spend spiking on a recurring campaign cadence. Every 8 months, the Marketing department’s Advertising spend multiplies by 3.2×. Three campaign cycles fit in the 36-month window, giving anomaly detection a real, repeating pattern to describe rather than a one-time outlier.
- Cloud Infrastructure step-change (platform migration) + two autoscaling/data-transfer incident months. Engineering’s Cloud Infrastructure cost jumps 60% at month 9 (the platform migration), then spikes 2.4× at month 15 (autoscaling incident) and 2.0× at month 27 (data transfer overage). The descriptions on those rows are labeled explicitly, so the agent can surface them by name.
-
Two Contractors project ramps (bell-curve spend) at different points in the 3-year window. Contractor spend follows Gaussian bell curves peaking around months 7 and 24, modeled as
exp(-((m - 7)² / 8)) + exp(-((m - 24)² / 10)). This creates a ramp-up-and-wind-down shape across both Engineering and Operations rather than a flat average — a more realistic project spend pattern. - Two Recruiting hiring pushes a year apart. Sales and Engineering both have elevated recruiting spend during months 12–14 and again during months 24–26, with sparse low-level activity in between. Budget-vs-actual charts show two visible hiring push periods.
- One-off Office (relocation) and Travel (conference) spikes — anomalies aren’t always in the same departments. Operations gets a one-time office relocation spike at month 20; Sales gets a one-time conference travel spike at month 9. These two events spread outlier variety across a third and fourth category, so anomaly detection doesn’t always point at Marketing and Engineering.
The seed data is intentionally rich — it’s not just noise. Specific stories ensure anomaly detection has real outliers to find, budget charts show over/under patterns, and trend charts show growth curves worth discussing.
Re-seeding
The seed is deterministic, so you almost never need to regenerate it. The only reasons to reseed are:- You’ve changed the schema and need to repopulate with the new structure.
- You’ve modified
db/seed.tsto add a new financial story or adjust parameters. - Your database was accidentally corrupted or wiped.
DATABASE_URL to be set in .env.local pointing at the database you just seeded. The tests exercise all exported functions and assert on specific numeric results, so any unintended change to the generation logic will surface as a test failure rather than silently changing chart output.