A complete web app to track trips, calculate costs, and visualize statistics for the Austrian Klimaticket.
Live Demo: https://jhoelzl.github.io/klimaticket-rechner/
- π₯ Heatmap calendar β Visualize trips per day with intensity levels.
- π 12-month year overview β All months at a glance with stats.
- π Monthly trends β Trips and costs by month.
- πΊοΈ States overview β Emoji cards for all 9 Austrian states.
- π Top 10 routes β Your most frequent routes.
- π PDF export β Professional summary with all statistics.
- π Achievements system β 12 Austria-themed badges (Obus Fan, S-Bahn Pro, State Hopper, etc.)
- βοΈ Cloud sync with Supabase β Multi-device synchronization.
- π± Offline support β Works without internet (PWA).
- πΎ Local fallback β localStorage for anonymous users.
- π₯ JSON/CSV export & import β Data portability.
- π Authentication β Email-based login via Supabase Auth.
- π Multilingual β English and German with:
- π Automatic browser language detection
- ποΈ Manual language switching in settings
- πΎ Language preference storage (cloud & local)
- β¨ Full UI translation support
- π Dark mode β Fully implemented with:
- π Automatic system detection (prefers-color-scheme)
- ποΈ Manual toggle in settings
- πΎ User preference storage
- β¨ Smooth transitions between themes
- π¨ Optimized colors for better readability
- β‘ Quick-add buttons β Add frequent trips instantly (pre-configured routes)
- π±οΈ Trip tooltip β Hover on calendar days for trip details
- π Filters & search β Filter by route, state, date
- β Modal UX β Close via X button or ESC key
- π± Responsive design β Mobile-first, works on all devices
- π Language setting β Choose between English and German
- πΆ Adjust ticket cost β Dynamic savings calculation
- π Set validity period β Start/end dates for ticket validity
- β° Automatic countdown β Days remaining until expiry
- π Dark mode β Toggle with automatic system detection
# Clone the repository
git clone https://github.com/jhoelzl/klimaticket-rechner.git
cd klimaticket_rechner
# Start locally with Python
python3 -m http.server 8000
# Open in browser
# http://localhost:8000- iPhone: Safari β Share button β "Add to Home Screen"
- Android: Chrome β Menu β "Install app"
- App works offline with automatic cloud sync!
CREATE TABLE trips (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
user_id UUID NOT NULL DEFAULT auth.uid(),
date TEXT NOT NULL, -- ISO: YYYY-MM-DD
route TEXT NOT NULL, -- e.g. "Salzburg - Vienna"
cost DECIMAL(10,2) NOT NULL, -- Cost in EUR
distance DECIMAL(10,1), -- Distance in kilometers (optional)
bundeslaender TEXT[] DEFAULT '{}', -- States array
notes TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
CONSTRAINT fk_user FOREIGN KEY (user_id)
REFERENCES auth.users(id) ON DELETE CASCADE
);
CREATE INDEX idx_user_date ON trips(user_id, date);
CREATE INDEX idx_user_route ON trips(user_id, route);
CREATE INDEX idx_distance ON trips(distance);CREATE TABLE users (
user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
ticket_cost DECIMAL(10,2) DEFAULT 1400.00,
start_date DATE,
end_date DATE,
language VARCHAR(5) DEFAULT 'en', -- Language preference: 'en', 'de'
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);ALTER TABLE trips ENABLE ROW LEVEL SECURITY;
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- Trips: Users can only view/modify their own trips
CREATE POLICY "Users can view own trips" ON trips FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own trips" ON trips FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own trips" ON trips FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "Users can delete own trips" ON trips FOR DELETE
USING (auth.uid() = user_id);
-- Users: Users can only view/modify their own settings
CREATE POLICY "Users can manage own settings" ON users
FOR ALL USING (auth.uid() = user_id);1. Click "π§ Sign in" button
2. Enter email address
3. Open confirmation link from email
4. β
Done! Data stored in Supabase
5. π± Multi-device sync enabled
1. Open the app
2. Data stored directly in browser storage (localStorage)
3. Export/Import available for backup
4. β οΈ No sync across devices
https://supabase.com β Sign Up β New Project
Region: Frankfurt (closest to Austria)
Password: Choose securely!
Supabase Dashboard β SQL Editor β Copy-paste the SQL above
# .env.local (NOT pushed to git)
VITE_SUPABASE_URL=https://YOUR-PROJECT.supabase.co
VITE_SUPABASE_ANON_KEY=YOUR-ANON-KEYFind these at: Supabase Settings β API β Project URL + Publishable Key
Supabase Dashboard β Email Templates β Customize branding
klimaticket_rechner/
βββ index.html # Main HTML with embedded CSS/JS
βββ manifest.json # PWA manifest
βββ sw.js # Service Worker (offline support)
βββ README.md # This file
βββ docs/
β βββ FEATURES.md # Feature roadmap
β βββ TEST_ANALYSIS.md # Test analysis
β βββ COVERAGE.md # Coverage report
βββ .gitignore # Git ignore file
βββ .env.example # Environment variables template
- Frontend: Vanilla HTML/CSS/JavaScript (no frameworks!)
- Backend: Supabase (PostgreSQL + Auth)
- Deployment: GitHub Pages
- PWA: Service Worker + Web Manifest
- π₯ Heatmap calendar (current month)
- π Year overview (all 12 months)
- πΊοΈ States overview with statistics
- π Achievements with progress tracking
- π Trip list with filtering
The achievement system rewards frequent public transport usage with 12 Austria-themed badges:
Transit & Location Achievements:
- π Obus Fan β 20 trips with the Obus
- π S-Bahn Pro β 50 trips with the S-Bahn
- ποΈ Salzburg Local Hero β 100 trips in Salzburg
- π¦πΉ Austria Explorer β Visit 5 different states
- π Austria Master β Visit all 9 states
- πΊοΈ State Hopper β 10 cross-state trips
Variety & Consistency:
- π§ Route Collector β 15 unique routes
- ποΈ Monthly Champion β Trips in 6 different months
- π Weekend Warrior β 20 weekend trips
Savings Achievements:
- π° First Break-Even β Ticket paid off!
- π± Climate Champion β β¬500 in savings
- π― Transit Pro β 100 trips total
Each badge shows your progress and unlocks with a toast notification!
- β‘ Quick-add buttons (frequent routes)
- βοΈ Edit trip modal for adjustments
- π PDF export (complete summary)
- π₯ JSON/CSV import & export
- βοΈ Settings for ticket configuration
1. Click "β‘ Quick Buttons"
2. E.g. "S-Bahn Sbg (β¬3.60)"
3. β
Done β Trip added with today's date
1. Click trip in trip list
2. βοΈ Edit trip modal opens
3. Modify data β Save
1. π₯ Heatmap β See daily trips
2. π
Year overview β Monthly trends
3. πΊοΈ States β Which states visited most?
1. Bottom β "π PDF Summary"
2. PDF with all stats is generated
3. Download or print
Local Changes β Supabase β All Devices
Automatic on changes
Without internet β Changes buffered locally
β Auto-sync when back online
- JSON Export β Backup
- CSV Export β Spreadsheet-compatible
- Import from file supported
| Problem | Solution |
|---|---|
| Supabase Connection Error | Check .env.local β URL & key correct? |
| Data won't load | Supabase Dashboard β trips table exists? |
| Auth not working | Supabase β Email Templates β SMTP correct? |
| Offline not working | Browser Service Workers enabled? |
| PDF text cut off | Set browser zoom to 100%, then 1 month per line |
git push origin main
# Automatically deploys to:
# https://jhoelzl.github.io/klimaticket-rechner/# Python SimpleHTTPServer
python3 -m http.server 8000
# or
npx http-serverSee docs/FEATURES.md for complete roadmap with 50+ feature ideas:
- Advanced filtering & search
- Excel export (.xlsx)
- COβ tracking
- π Always use correct date
- ποΈ Add all states involved in trip
- π¬ Notes help with tracking later
- π Use strong password
- βοΈ With login = cloud backup
- πΎ Export backups regularly
- π Use offline mode when needed
- π± Install PWA for faster access
- ποΈ Archive old data if too much
Contributions welcome!
# 1. Fork the repo
# 2. Create feature branch
git checkout -b feature/my-feature
# 3. Commit your changes
git commit -m "Add: my awesome feature"
# 4. Push to branch
git push origin feature/my-feature
# 5. Create pull requestMIT License β Free to use!
- Issues: Use GitHub Issues
- Features: Check docs/FEATURES.md + create issue
- Bugs: Report with screenshot/stacktrace