Interactive performance tracking dashboard for Turkish investment funds (TEFAS). Built with React, Express.js, and Supabase.
- Multi-Fund Comparison: Track up to 5 funds simultaneously
- Interactive Charts: Recharts-powered visualizations with tooltips
- Time Periods: 1D, 1W, 1M, 3M, 6M, YBB, 1Y, 3Y, 5Y
- Metrics: Price, Market Cap, Investor Count
- Fund Types: YAT (Investment Funds), EMK (Pension Funds), BYF (ETFs)
- π Technical Indicators: MA50 and MA200 moving averages
- π Percentage Normalization: Compare funds with different price scales
- πΎ Supabase Caching: 15-30x faster load times for historical data
- π GitHub Authentication: Save and sync your fund portfolios
- π Manual Refresh: Force update data from TEFAS
- First Load: 10-15 seconds (fetches from TEFAS + caches to Supabase)
- Cached Load: <1 second (serves from Supabase)
- Multi-Fund: Parallel loading for optimal performance
- React + TypeScript
- Vite (build tool)
- Recharts (charting library)
- Supabase Client (auth + database)
- Express.js (API server)
- Supabase (PostgreSQL database + auth)
- TEFAS Crawler (Python library for data fetching)
- Node.js 18+
- Python 3.8+
- Supabase account
git clone https://github.com/yourusername/tefas-crawler.git
cd tefas-crawler# Backend
npm install
# Frontend
cd frontend
npm install
cd ..Create .env in the root directory:
SUPABASE_URL=your_supabase_url
SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_keyCreate frontend/.env:
VITE_SUPABASE_URL=your_supabase_url
VITE_SUPABASE_ANON_KEY=your_anon_keyRun this SQL in your Supabase SQL Editor:
-- Fund metadata
CREATE TABLE funds (
code TEXT PRIMARY KEY,
title TEXT NOT NULL,
kind TEXT NOT NULL,
latest_date DATE,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Historical price/investor/market cap data
CREATE TABLE historical_data (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
fund_code TEXT REFERENCES funds(code),
date DATE NOT NULL,
price NUMERIC,
market_cap NUMERIC,
investor_count INTEGER,
UNIQUE(fund_code, date)
);
-- User portfolios
CREATE TABLE portfolios (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id),
name TEXT DEFAULT 'My Portfolio',
fund_list JSONB NOT NULL DEFAULT '[]',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);- Go to Supabase Dashboard β Authentication β Providers
- Enable GitHub provider
- Create GitHub OAuth App at https://github.com/settings/developers
- Set callback URL:
https://your-project.supabase.co/auth/v1/callback - Copy Client ID and Secret to Supabase
# Start both backend and frontend
npm run dev
# Or separately:
# Backend (port 3000)
node scripts/dev-server.js
# Frontend (port 5173)
cd frontend && npm run devVisit http://localhost:5173
git add .
git commit -m "Add Supabase integration and advanced features"
git push origin main- Import your GitHub repository
- Framework Preset: Vite
- Root Directory:
frontend - Add environment variables:
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY
The api/ directory will be automatically deployed as Vercel Serverless Functions.
Returns list of available funds for the specified type.
Returns historical data for a specific fund.
Parameters:
code: Fund code (e.g., TLY, AAK)kind: Fund type (YAT, EMK, BYF)days: Number of days or 'ybb' for year-to-date
- Select Fund Type: Choose between YAT, EMK, or BYF
- Search Funds: Type to filter the fund list
- Select Funds: Click to add (max 5 funds)
- Choose Time Period: Select from 1D to 5Y
- Select Metric: Price, Market Cap, or Investor Count
- Enable Features:
- Toggle "Percentage Change (%)" for normalized comparison
- Toggle "Moving Averages" to show MA50/MA200
- Save Portfolio: Login with GitHub and click "πΎ Kaydet"
Edit api/fund-history.js to adjust cache validation:
expectedDays: Trading days estimationcoversFullRange: Date range tolerance (default: 7 days)isFresh: Freshness threshold (default: 2 days)
Edit frontend/src/components/PerformanceChart.tsx:
const colors = ['#2563eb', '#dc2626', '#16a34a', '#d97706', '#9333ea'];
const maColors = { MA50: '#f97316', MA200: '#22c55e' };- TEFAS API for providing fund data
- tefas-crawler Python library
- Supabase for database and authentication
- Recharts for beautiful charts