Skip to content

Repository files navigation

HoodPrivate

The web app for HoodPrivate: private-by-default banking on Robinhood Chain, for people and for the AI agents that spend on their behalf.

This repository holds the marketing site and the authenticated product that sits behind it. Full product documentation lives at docs.hoodprivate.com, so this README sticks to the app itself, how it is put together and how to run it locally.

Stack

  • Next.js 16 with the App Router and React 19
  • TypeScript throughout
  • Tailwind CSS v4 for styling, with a small set of shadcn primitives
  • Supabase for authentication, Postgres and row level security

Getting started

You need Node 20 or newer and a Supabase project.

npm install
npm run dev

The app runs on http://localhost:3000.

Before it will do anything useful, create a .env.local with these three values:

Variable Purpose
NEXT_PUBLIC_SUPABASE_URL Supabase project URL
NEXT_PUBLIC_SUPABASE_ANON_KEY Supabase anon key, safe to expose to the browser
NEXT_PUBLIC_DEPOSIT_ADDRESS Address shown on the wallet top up screen

Database migrations live outside this folder in supabase/migrations. Apply those before signing in, otherwise the app will authenticate fine but every query will come back empty.

Scripts

  • npm run dev starts the development server
  • npm run build produces a production build
  • npm run start serves that build
  • npm run lint runs ESLint

How the code is laid out

src/
  app/
    page.tsx          landing page
    roadmap/          public roadmap
    token/            token page
    status/           service status
    login/            sign in
    signup/           sign up
    auth/callback/    Supabase email confirmation handler
    app/              the authenticated product
  components/         landing page sections and shared UI
  lib/supabase/       browser and server clients, plus hand written DB types
  middleware.ts       session refresh and route guards

Everything under src/app/app sits behind auth. The sidebar groups it into banking (accounts, send payment, cards, wallet), agents (agent accounts, activity, analytics) and developer tooling (API keys, alerts), with settings pinned to the bottom.

A few things worth knowing

Money never moves from the client. Transfers, top ups and policy changes all go through Postgres functions defined in the migrations. The app calls those functions and reads back the result. No code path in src writes a balance directly, which is deliberate: the database enforces the same rules the UI shows, so a bug in a form cannot become a bug in someone's balance.

Database types are hand written. src/lib/supabase/database.types.ts mirrors the schema by hand rather than being generated by the Supabase CLI. If you change a migration, change that file too. One catch that has caught us more than once: every Row, Insert, Update and Args shape in there has to be declared with type, never interface. The Supabase client constrains them against Record<string, unknown>, and TypeScript only accepts object literal type aliases for that check. Use an interface and every .from() call quietly resolves to never, with no error pointing at the cause.

Agent accounts are ordinary accounts with a policy attached. An agent gets its own account, its own handle and its own balance, plus a spend policy that caps what it can move per day and per transaction. Revoking an agent does not delete its history, it only stops the account from sending.

Privacy tiers

Every account carries one of three tiers, and the tier decides what a transfer reveals on chain:

  • Public, amounts and counterparties are visible
  • Confidential, amounts are encrypted, counterparties are not
  • Shielded, both are hidden

Confidential is the default. The tier belongs to the account rather than to the individual transfer, so an agent cannot quietly downgrade its own privacy mid session.

Releases

Packages

Contributors

Languages