Skip to content

Personal investing tracker with watchlist, portfolio analytics, and corporate events tracking. Built with Next.js 15, tRPC v11, Prisma, and InfluxDB.

Notifications You must be signed in to change notification settings

PanagiotisKaraliolios/invest-igator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ” Invest-igator

An opinionated personal investing tracker

Next.js TypeScript tRPC Prisma Bun

Docker Image Size

Built with Next.js App Router, tRPC v11, Prisma/PostgreSQL, shadcn/ui, and InfluxDB for fast timeseries. Auth is powered by Better Auth (Prisma adapter) with email/password, magic links, 2FA, and Discord OAuth.

Getting Started โ€ข Features โ€ข Documentation โ€ข Contributing


โœจ Features

  • ๐Ÿ“Š Watchlist with historical OHLCV from InfluxDB (AAPL, MSFT, etc.)
    • ๐Ÿ“… Date range filtering with customizable presets and max date constraints
    • ๐Ÿ“ˆ Interactive charts with Recharts integration
  • ๐Ÿ’ฐ Corporate events: dividends, splits, capital gains
  • ๐Ÿ“ˆ Transactions with CSV import/export, duplicate detection, and FX-aware currencies
    • ๐Ÿ”„ Sortable columns with visual indicators
    • ๐Ÿ” Advanced filtering and search
  • ๐ŸŽฏ Portfolio analytics: structure and performance calculations (TWR/MWR via tRPC)
  • ๐ŸŽช Goals tracking: simple personal financial goals model
  • ๐ŸŽจ Modern UI: theming, toasts, and shadcn/ui + Recharts
    • โšก TanStack Table v8 for complex data tables
    • ๐Ÿ”Ž Debounced search inputs (300ms) for better UX
    • ๐Ÿ’€ Skeleton loading states for professional loading experience
    • ๐ŸŽฏ Active navigation indicators in sidebar
  • ๐Ÿ”„ Auto-sync: Yahoo Finance ingestion job for OHLCV and events; FX rates via Alpha Vantage
  • ๐Ÿ” Admin interface: comprehensive user management and audit logging
    • ๐Ÿ‘ฅ User management with sorting, filtering, and role-based permissions
    • ๐Ÿ“‹ Audit logs with date range filtering and action tracking
    • ๐Ÿ“Š Statistics dashboard with user metrics
    • ๐Ÿ” Debounced search across users and logs
  • ๐Ÿ”‘ API Keys: programmatic access with granular permissions
    • ๐ŸŽฏ 8 permission scopes (account, admin, apiKeys, fx, goals, portfolio, transactions, watchlist)
    • ๐Ÿ“‹ 4 built-in templates (read-only, full-access, portfolio-manager, custom)
    • ๐Ÿšฆ Rate limiting and expiration controls
    • ๐Ÿ”’ SHA-256 hashed keys with secure generation
    • ๐Ÿ“Š Usage tracking and management UI

๐Ÿ› ๏ธ Tech stack

Layer Technology
Frontend Next.js 15 (App Router) โ€ข React 19
API tRPC v11 + React Query (RSC + CSR hydration)
Database Prisma + PostgreSQL
Auth Better Auth (email/password, magic link, 2FA, Discord)
UI shadcn/ui + TailwindCSS 4 โ€ข TanStack Table v8
Charts Recharts
Timeseries InfluxDB 2.x (daily_bars + event measurements)

๐Ÿ—๏ธ Architecture (high level)

graph TB
    A[Client: React 19 + Next.js 15] --> B[tRPC v11]
    B --> C[API Routers]
    C --> D[Prisma ORM]
    C --> E[InfluxDB Client]
    D --> F[(PostgreSQL)]
    E --> G[(InfluxDB 2.x)]
    C --> H[Better Auth]
    H --> F
Loading

Key components:

  • ๐Ÿ“ App Router under src/app/*; dashboard shell in src/app/(dashboard)/layout.tsx
  • ๐Ÿ”Œ tRPC routers in src/server/api/routers/*, composed in src/server/api/root.ts
  • ๐Ÿ” Context includes db (Prisma) and session from Better Auth in src/server/api/trpc.ts
  • โšก Influx helpers in src/server/influx.ts
  • ๐Ÿ“ฅ Yahoo ingestion in src/server/jobs/ingest-yahoo.ts with helpers in yahoo-lib.ts
  • ๐Ÿช Client hooks in src/trpc/react.tsx; RSC callers via src/trpc/server.ts

Example API usage:

// Server (RSC)
import { api } from "@/trpc/server";
const me = await api.account.getMe.query();

// Client (CSR)
import { api } from "@/trpc/react";
const { data } = api.watchlist.list.useQuery();

๐Ÿš€ Getting started (local dev)

Prerequisites

  • โœ… Bun 1.0+
  • โœ… Node 20+ (optional, Bun runs everything)
  • โœ… A PostgreSQL 16 database (use ./start-database.sh)
  • โœ… An InfluxDB 2.x instance (local or remote)

Setup steps

1๏ธโƒฃ Install dependencies

bun install

2๏ธโƒฃ Create and fill .env

See the Environment variables section below. For a smoke test you can set placeholders and use SKIP_ENV_VALIDATION=1 while you iterate.

3๏ธโƒฃ Start Postgres (dev helper)

./start-database.sh

4๏ธโƒฃ Generate and apply Prisma schema

bun run db:generate

5๏ธโƒฃ Start the dev server

bun run dev

๐ŸŽ‰ Open http://localhost:3000


๐Ÿ” Environment variables

Validated in src/env.js via @t3-oss/env-nextjs. Server-side vars are required unless noted.

๐Ÿ“‹ Core application
  • DATABASE_URL: Postgres connection URL (required)
  • BETTER_AUTH_SECRET: Secret for Better Auth JWT/cookies (required in production)
  • BETTER_AUTH_URL: Public base URL of the app (default: http://localhost:3000)
  • PASSWORD_PEPPER: Extra pepper for hashing local passwords (required)
  • EMAIL_SERVER: Nodemailer connection string (e.g. SMTP URI) (required)
  • EMAIL_FROM: From address for transactional emails (required)
  • NEXT_PUBLIC_SITE_URL: Public site URL exposed to client (default: http://localhost:3000)
๐Ÿ”‘ Auth providers
  • AUTH_DISCORD_ID, AUTH_DISCORD_SECRET: Discord OAuth credentials (required if enabling Discord)
๐Ÿ’พ Data backends
  • INFLUXDB_URL (default http://localhost:8086)
  • INFLUXDB_ORG
  • INFLUXDB_BUCKET
  • INFLUXDB_TOKEN
  • DATABASE_URL (Postgres, repeated for clarity)
๐ŸŒ External APIs
โš™๏ธ Optional/infra
  • CLOUDFLARE_* (R2 image storage wiring present; optional)
  • NEXT_PUBLIC_* for Ads/Analytics (Umami/GA/AdSense) are optional and stubbed in E2E tests

๐Ÿ’ก Tip: during early setup, export SKIP_ENV_VALIDATION=1 to bypass strict checks until you've filled everything in.


๐Ÿ—„๏ธ Database (Prisma)

Command Description
bun run db:generate Generate/apply in dev (migrate dev)
bun run db:migrate Deploy migrations
bun run db:push Push schema (no migrations)
bun run db:studio Prisma Studio (defaults to port 5000)

Schema: prisma/schema.prisma

Relevant models: User, Account, Session, WatchlistItem, Transaction, FxRate, Goal, ApiKey and Better Auth support tables TwoFactor, Verification, VerificationToken.


๐Ÿ“Š Timeseries (InfluxDB)

Measurement Fields Tags Purpose
daily_bars open, high, low, close, volume symbol OHLCV data
dividends amount symbol Dividend events
splits numerator, denominator, ratio symbol Stock split events
capital_gains amount symbol Capital gain distributions

Helper code: src/server/influx.ts


๐Ÿ”„ Ingestion jobs

Yahoo Finance โ†’ InfluxDB

bun run ingest:yahoo

What it does:

  • โœ… Reads distinct symbols from your WatchlistItems
  • โœ… Fetches full-range daily bars plus dividends, splits, capital gains
  • โœ… Writes to Influx in batches with retries and gentle pacing (~2s/request)
  • โœ… Also updates watchlist currency when available
  • โœ… Adding a symbol to your watchlist triggers a background ingest for that symbol

FX rates (Alpha Vantage)

bun run ingest:fx

What it does:

  • โœ… Fetches pivoted rates through USD and upserts cross rates into FxRate

๐Ÿงช Running tests

E2E tests with Playwright:

# Install browsers once
bun run test:e2e:install

# Run headless
bun run test:e2e

# Run headed or with the UI
bun run test:e2e:headed
bun run test:e2e:ui

Config: playwright.config.ts (uses a built-in dev server unless PW_SKIP_WEBSERVER=1).


๐Ÿ“ฎ API Testing with Postman

Comprehensive Postman collections are available in the postman/ directory for testing all API endpoints.

Collections include:

  • ๐Ÿ” Authentication - Sign up, login, password reset (Better Auth)
  • ๐Ÿ‘ค Account - Profile management, 2FA, email changes, OAuth
  • ๐Ÿ“Š Watchlist - Symbol management, price history, corporate events
  • ๐Ÿ’ฐ Transactions - CRUD operations, CSV import/export, filtering
  • ๐Ÿ“ˆ Portfolio - Structure and performance analytics (TWR/MWR)
  • ๐ŸŽฏ Goals - Financial goals tracking
  • ๐Ÿ”‘ API Keys - Programmatic access management
  • ๐Ÿ‘ฅ Admin - User management, audit logs (admin only)
  • ๐Ÿ’ฑ Currency & Theme - User preferences
  • ๐ŸŒ FX - Foreign exchange rates

Quick start:

# Import into Postman
# 1. Open Postman
# 2. Import postman/Invest-igator-API.postman_collection.json
# 3. Import postman/Invest-igator.postman_environment.json
# 4. Configure environment variables (baseUrl, etc.)
# 5. Sign in via Better Auth endpoints

๐Ÿ“š See postman/README.md for detailed usage instructions

All 59 endpoints are documented with:

  • โœ… Request/response examples
  • โœ… Input validation details
  • โœ… Authentication requirements
  • โœ… Environment variables for easy configuration

โœ… Linting and typecheck

bun run check       # Biome
bun run typecheck   # TypeScript

๐Ÿณ Docker

Build locally

docker build -t invest-igator:local .

Run (minimum env)

docker run --rm -p 3000:3000 \
  -e DATABASE_URL=postgresql://user:pass@host:5432/db \
  -e BETTER_AUTH_SECRET=change-me \
  -e PASSWORD_PEPPER=change-me \
  -e EMAIL_SERVER=smtp://user:pass@mail:587 \
  -e [email protected] \
  -e FINNHUB_API_KEY=... \
  -e ALPHAVANTAGE_API_KEY=... \
  -e INFLUXDB_URL=http://influx:8086 \
  -e INFLUXDB_ORG=... \
  -e INFLUXDB_BUCKET=... \
  -e INFLUXDB_TOKEN=... \
  invest-igator:local

Docker Compose (App + Postgres + Scheduler)

This repo includes a Compose file that runs:

  • invest-igator: the app container (published on port 3311)
  • db: internal Postgres 16
  • scheduler: Ofelia to run ingestion jobs inside the app container on a cron

Quick start:

cp .env.example .env  # if you have one; otherwise create .env from the vars above
# Fill DATABASE_URL, BETTER_AUTH_SECRET, PASSWORD_PEPPER, INFLUXDB_*, FINNHUB/ALPHAVANTAGE, EMAIL_*
docker compose up -d

Notes:

  • โš ๏ธ Compose expects you to point INFLUXDB_URL to an existing Influx instance (not included in the stack)
  • โฐ Cron labels run ingest-yahoo daily at 02:15 UTC and ingest-fx at 06:00/18:00 UTC
  • ๐Ÿ”„ Migrations run automatically on container start

Stop and remove:

docker compose down -v

๐Ÿ“‚ Project structure

.
โ”œโ”€โ”€ prisma/
โ”‚   โ”œโ”€โ”€ schema.prisma          # ๐Ÿ—„๏ธ  Relational models (User, WatchlistItem, Transaction, etc.)
โ”‚   โ””โ”€โ”€ migrations/            # ๐Ÿ“ฆ Schema migrations
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ server/
โ”‚   โ”‚   โ”œโ”€โ”€ api/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ root.ts        # ๐Ÿ”— tRPC router composition
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ trpc.ts        # โš™๏ธ  Context, middleware, procedures
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ routers/       # ๐Ÿงฉ Feature routers (watchlist, transactions, admin, etc.)
โ”‚   โ”‚   โ”œโ”€โ”€ jobs/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ingest-yahoo.ts  # ๐Ÿ“ˆ Yahoo Finance ingestion job
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ingest-fx.ts     # ๐Ÿ’ฑ FX rates ingestion job
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ yahoo-lib.ts     # ๐Ÿ› ๏ธ  Yahoo data helpers
โ”‚   โ”‚   โ”œโ”€โ”€ auth/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ config.ts      # ๐Ÿ” Better Auth configuration
โ”‚   โ”‚   โ”œโ”€โ”€ db.ts              # ๐Ÿ—ƒ๏ธ  Prisma client singleton
โ”‚   โ”‚   โ”œโ”€โ”€ influx.ts          # ๐Ÿ“Š InfluxDB client & helpers
โ”‚   โ”‚   โ”œโ”€โ”€ fx.ts              # ๐Ÿ’ฐ FX rate conversion utilities
โ”‚   โ”‚   โ””โ”€โ”€ r2.ts              # โ˜๏ธ  Cloudflare R2 storage client
โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”œโ”€โ”€ (dashboard)/       # ๐Ÿ  Protected dashboard routes
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ watchlist/     # ๐Ÿ“Š Watchlist with charts and date filtering
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ portfolio/     # ๐Ÿ’ผ Portfolio analytics
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ transactions/  # ๐Ÿ“ˆ Transaction management with sorting
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ account/       # ๐Ÿ‘ค Account settings with API Keys tab
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ admin/         # ๐Ÿ” Admin section
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ users/     # ๐Ÿ‘ฅ User management page
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ audit-logs/  # ๐Ÿ“‹ Audit logs page
โ”‚   โ”‚   โ”œโ”€โ”€ (auth)/            # ๐Ÿ”‘ Auth routes (login, signup, verify-request)
โ”‚   โ”‚   โ”œโ”€โ”€ api/               # ๐ŸŒ API endpoints (tRPC, auth, email verification)
โ”‚   โ”‚   โ””โ”€โ”€ layout.tsx         # ๐ŸŽจ Root layout with providers
โ”‚   โ”œโ”€โ”€ components/
โ”‚   โ”‚   โ”œโ”€โ”€ ui/                # ๐Ÿงฑ shadcn/ui primitives (incl. DateRangePicker, Skeleton)
โ”‚   โ”‚   โ”œโ”€โ”€ ads/               # ๐Ÿ“ข AdSense integration
โ”‚   โ”‚   โ”œโ”€โ”€ consent/           # โœ… Cookie consent provider
โ”‚   โ”‚   โ””โ”€โ”€ theme/             # ๐ŸŒ“ Theme provider
โ”‚   โ”œโ”€โ”€ hooks/
โ”‚   โ”‚   โ”œโ”€โ”€ use-debounce.ts    # โฑ๏ธ  Debounce hook (300ms)
โ”‚   โ”‚   โ””โ”€โ”€ use-currency.ts    # ๐Ÿ’ฑ Currency utilities
โ”‚   โ”œโ”€โ”€ trpc/
โ”‚   โ”‚   โ”œโ”€โ”€ react.tsx          # โš›๏ธ  Client-side tRPC hooks
โ”‚   โ”‚   โ”œโ”€โ”€ server.ts          # ๐Ÿ–ฅ๏ธ  Server-side tRPC helpers
โ”‚   โ”‚   โ””โ”€โ”€ query-client.ts    # ๐Ÿ“ก React Query configuration
โ”‚   โ”œโ”€โ”€ lib/
โ”‚   โ”‚   โ”œโ”€โ”€ auth.ts            # ๐Ÿ”’ Better Auth instance
โ”‚   โ”‚   โ”œโ”€โ”€ api-key-permissions.ts  # ๐Ÿ”‘ API key permission framework
โ”‚   โ”‚   โ”œโ”€โ”€ api-key-utils.ts   # ๐Ÿ”ง API key generation & validation
โ”‚   โ”‚   โ””โ”€โ”€ utils.ts           # ๐Ÿ”ง Utility functions (cn, etc.)
โ”‚   โ””โ”€โ”€ env.js                 # โœ”๏ธ  Environment validation (@t3-oss/env-nextjs)
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ e2e/                   # ๐Ÿงช Playwright E2E tests
โ”œโ”€โ”€ docker/
โ”‚   โ””โ”€โ”€ entrypoint.sh          # ๐Ÿณ Container startup script (migrations, server)
โ”œโ”€โ”€ Dockerfile                 # ๐Ÿ“ฆ Multi-stage build (deps, builder, runner)
โ”œโ”€โ”€ docker-compose.yml         # ๐Ÿ™ Compose stack (app, db, scheduler)
โ””โ”€โ”€ start-database.sh          # ๐Ÿ—„๏ธ  Dev Postgres script

Quick pointers:

  • Dashboard shell: src/app/(dashboard)/layout.tsx
  • Sidebar with active navigation: src/app/(dashboard)/_components/app-sidebar.tsx
  • tRPC glue: src/server/api/trpc.ts, src/trpc/react.tsx, src/trpc/server.ts
  • API key system:
    • Permission framework: src/lib/api-key-permissions.ts
    • Key utilities: src/lib/api-key-utils.ts
    • Router: src/server/api/routers/api-keys.ts
    • Middleware: src/server/api/middleware/with-api-key.ts
    • UI components: src/app/(dashboard)/account/_components/api-keys-*.tsx
  • Admin routers with sorting: src/server/api/routers/admin.ts
  • Table components (reference): src/app/(dashboard)/admin/_components/user-management-table.tsx, audit-logs-table.tsx
  • Influx helpers: src/server/influx.ts
  • Ingestion: src/server/jobs/ingest-yahoo.ts
  • Example router: src/server/api/routers/watchlist.ts
  • Reusable components: src/components/ui/date-range-picker.tsx, src/components/ui/skeleton.tsx
  • Debounce hook: src/hooks/use-debounce.ts

๏ฟฝ API Keys

Invest-igator supports programmatic API access via API keys with granular permission control.

Features

  • ๐ŸŽฏ 8 permission scopes: account, admin, apiKeys, fx, goals, portfolio, transactions, watchlist
  • ๐Ÿ“‹ 4 built-in templates:
    • read-only: Read access to all non-admin endpoints
    • full-access: Read + write + delete for all user resources
    • portfolio-manager: Portfolio, transactions, and goals management
    • custom: Build your own permission set
  • ๐Ÿšฆ Rate limiting: Configure per-key request limits with automatic refills
  • โฐ Expiration control: Set expiry dates or create permanent keys
  • ๐Ÿ”’ Secure by design: SHA-256 hashed keys, cryptographically secure generation
  • ๐Ÿ“Š Management UI: Create, view, and revoke keys from your account page

Quick Start

  1. Create an API key: Go to Account โ†’ API Keys tab and click "Create API Key"
  2. Select permissions: Choose a template or create custom permissions
  3. Copy your key: Save it securely - it's only shown once!
  4. Make requests: Include x-api-key header in your API calls

Example Usage

# Get your user profile
curl https://your-app.com/api/trpc/account.getMe \
  -H "x-api-key: your_api_key_here"

# Get FX rates matrix
curl https://your-app.com/api/trpc/fx.matrix \
  -H "x-api-key: your_api_key_here"

# List watchlist items
curl https://your-app.com/api/trpc/watchlist.list \
  -H "x-api-key: your_api_key_here"

Documentation


๏ฟฝ๐Ÿ› Troubleshooting

Issue Solution
โŒ Env validation failing at boot Set SKIP_ENV_VALIDATION=1 temporarily and fill missing vars (see src/env.js)
โŒ Prisma migrate errors Ensure Postgres is reachable; try prisma migrate reset in dev
โŒ Influx writes fail Verify INFLUXDB_URL/ORG/BUCKET/TOKEN and token has write permissions
โŒ Emails not sending Verify EMAIL_SERVER URI and that your provider allows SMTP from containers
โŒ 401s in tRPC Confirm cookies are set and BETTER_AUTH_URL matches your external origin

๐Ÿค Contributing

PRs are welcome! Before submitting:

โœ… Run bun run check (Biome linting)
โœ… Run bun run typecheck (TypeScript)
โœ… Include/update E2E tests where relevant

Quick demo dataset:

Add a few symbols to your watchlist and run the Yahoo ingest job; the watchlist add flow also triggers a background ingest for that symbol.

Star History

Star History Chart

About

Personal investing tracker with watchlist, portfolio analytics, and corporate events tracking. Built with Next.js 15, tRPC v11, Prisma, and InfluxDB.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages