Skip to contentRyan Katayi
    All work

    Claro / Independent product / iOS

    A bank statement you can ask questions.

    A personal finance app for importing statements, categorizing transactions, and asking questions about spending.

    RoleIndependent developer
    StatusTestFlight build

    Built with

    Application
    • TypeScript
    • React Native
    • Expo
    Data & sync
    • SQLite
    • Supabase
    Statement processing
    • Claude

    Statement normalization · Import deduplication · Local storage and sync

    Inside the engineering
    My contributionI built statement importing, transaction categorization, financial chat, and local storage with cloud sync.

    Under the surface

    The engineering.

    The application starts with bank statements, but its useful unit is a transaction: a record that can be categorized, aggregated, and carried from local storage into a synced account.

    1. Import

      CSV records or PDF statement extraction.

    2. Normalize

      Categorize transactions and check fingerprints.

    3. Store

      SQLite locally, with Supabase cloud sync.

    4. Ask

      Financial chat supplied with precomputed transaction context.

    Decision / 01

    An imported file is not a transaction identity.

    The same transaction can appear in overlapping statements or in a file imported again. Treating every row as new would distort the spending history.

    How it works

    I built CSV and PDF importing with fingerprint-based transaction deduplication. Claude handles PDF extraction and categorization, producing records the rest of the application can use.

    The tradeoff

    A fingerprint must balance duplicate suppression against legitimate repeated purchases. Matching depends on the quality and consistency of the extracted fields; the presence of deduplication does not guarantee perfect imports.

    Decision / 02

    Build the financial context before the conversation.

    Questions about spending depend on the user’s actual transaction records and their interpretation. The chat needs application data to provide relevant answers.

    How it works

    Financial chat receives precomputed context from imported transactions. SQLite provides local storage, with Supabase used for cloud sync, connecting the import workflow to the information available in the conversation.

    The tradeoff

    Local and cloud state can diverge, and precomputed context can lag changes to the underlying records. Those boundaries are distinct from the quality of the model’s wording.

    Engineering considerations

    Where the boundaries matter.

    Statement periods overlap
    Transaction identity matters independently of which source file supplied the row.
    A transaction changes category
    Any derived spending context needs to reflect that change before it informs an answer.
    Next

    Droplyst

    An app that recognizes the music around you and turns a listening session into a playlist.

    Independent product / iOS