Help us measure site usage?

With your permission, we use self-hosted analytics to understand page usage. It is optional and does not affect the Service. Learn more.

TypeScriptbeginnerwebAI generated

CSV Expense Viewer

Build a React website where you upload a CSV file of your expenses (for example exported from your bank or a spreadsheet) and instantly see where your money went: totals per category, totals per month, and a table of every expense. Real CSV files are messy, so every row is checked with Zod: rows with a missing date, a price written as text or an unknown format are listed separately with the reason, instead of silently breaking the totals. Everything happens in the browser, so the file never leaves your computer. You'll learn React with TypeScript, reading files in the browser, parsing CSV with Papa Parse, validating data with Zod, and grouping and summing data.

Estimate
~8.5h
Steps
6
Completed by
0
Proposed by
codeseed.app

React · Zod

Project roadmap

  1. 01

    Define the CSV format

    ~1h

    Create a project with npm create vite@latest using the react-ts template, and install zod and papaparse. Write README.md with the expected columns (date in YYYY-MM-DD, description, category, amount with a dot for decimals) and a sample file in public/sample.csv including a few broken rows. Done when: the project runs, and README.md describes the format.

  2. 02

    Validate rows with Zod

    ~1.5h

    Write a Zod schema for one expense row: a valid date, a non-empty description, a category (empty becomes Uncategorized) and an amount greater than 0 (converted from text with z.coerce.number). Derive the Expense TypeScript type from the schema with z.infer. Write a function that splits rows into valid expenses and errors, each error with the line number and the reason. Done when: the function sorts the sample rows into valid and invalid correctly.

  3. 03

    Upload and parse the file

    ~1.5h

    Add a file input that accepts .csv. Parse the file with Papa Parse using the header option, check that the required columns exist (and show which ones are missing if not), then validate the rows. Show how many rows were imported and how many were rejected. Done when: uploading the sample file shows the imported and rejected counts.

  4. 04

    Show totals

    ~1.5h

    Show totals per category (largest first, with the percentage of the total) and per month (for example 2026-03), plus the grand total. Write the grouping as pure, typed functions. Format amounts with Intl.NumberFormat. Done when: the totals are correct for the sample file.

  5. 05

    Show expenses and errors

    ~1.5h

    Show all valid expenses in a table that can be sorted by date or amount and filtered by category and month. Show the rejected rows in a separate list with their line number and reason, so the user can fix the file. Show a clear message for an empty file. Done when: filtering updates the table and totals together, and every rejected row explains why.

  6. 06

    Test it

    ~1.5h

    Add Vitest and write tests: the schema accepts good rows and rejects each kind of bad row, missing columns are detected, and totals per category and month are correct, including an empty list. Done when: npm test passes.

Ready to build this?

Get a GitHub repo and start building. Your AI reviewer checks each step as you go.

~8.5h · 6 steps

Tech stack

ReactZod