This document provides specific instructions for AI agents working on the PowerNight codebase.
PowerNight uses a React SPA (Single Page Application) with a Flask backend. There is ONLY ONE frontend implementation.
Frontend Stack:
- React 18 + TypeScript
- Vite (build tool)
- Tailwind CSS (styling)
- React Router v6 (client-side routing)
- Axios (API client)
Backend Stack:
- Flask (Python web framework)
- Serves both the React SPA and REST API endpoints
IMPORTANT: The following were permanently removed and should NEVER be recreated:
- ❌ Vanilla JavaScript files (formerly
src/powernight/web/static/js/) - ❌ Jinja2 templates (formerly
src/powernight/web/templates/) - ❌ Custom CSS files (formerly
src/powernight/web/static/css/)
Reason for removal: Complete duplication with the React app. Over 12,993 lines of duplicate code were removed.
src/powernight/web/
├── src/ # React source code (ONLY frontend)
│ ├── components/ # Reusable React components
│ │ ├── ErrorBoundary.tsx
│ │ ├── Header.tsx
│ │ ├── LoadingSpinner.tsx
│ │ ├── StatusBadge.tsx
│ │ ├── ConfirmDialog.tsx
│ │ ├── Tooltip.tsx
│ │ └── LogsTable.tsx
│ ├── pages/ # Page components
│ │ ├── Dashboard.tsx # Main dashboard - Powerwall System Status
│ │ ├── Settings.tsx # Settings page - Tesla OAuth, Auth Info, Version Info
│ │ ├── Planner.tsx # Task management (formerly Scheduling)
│ │ ├── History.tsx # Task execution history and logs
│ │ └── Login.tsx # Login page
│ ├── hooks/ # Custom React hooks
│ │ ├── useAuth.ts # Authentication hook
│ │ ├── useApi.ts # API integration hook
│ │ └── useLocalStorage.ts # LocalStorage hook
│ ├── contexts/ # React contexts
│ │ └── TimezoneContext.tsx # Timezone management context
│ ├── utils/ # Utilities
│ │ ├── api.ts # Axios API client with typed methods
│ │ └── helpers.ts # Helper functions
│ ├── types/ # TypeScript type definitions
│ │ └── index.ts
│ ├── App.tsx # Main app component with routing
│ ├── main.tsx # React entry point
│ └── index.css # Tailwind CSS imports
├── api/ # Flask API (Backend only)
│ ├── routes.py # Main routes + SPA catch-all
│ ├── api.py # Main API blueprint (/api/v1/*)
│ ├── auth_api.py # Auth endpoints
│ ├── config_api.py # Config endpoints
│ ├── logs_api.py # Logs endpoints
│ ├── tasks_api.py # Tasks/cronjobs endpoints
│ ├── docs.py # API documentation (Swagger/ReDoc)
│ ├── auth.py # Authentication utilities
│ ├── config_manager.py # Configuration management
│ ├── decorators.py # API decorators
│ ├── errors.py # Error handling
│ ├── middleware.py # Flask middleware
│ ├── monitoring.py # Performance monitoring
│ ├── schemas.py # Data schemas
│ └── validation.py # Input validation
├── app.py # Flask app factory
├── middleware.py # Flask middleware
└── index.html # HTML entry point for Vite
dist/ # Built React app (git-ignored)
├── index.html # Built HTML
└── assets/ # Bundled JS/CSS
├── index-*.js
└── index-*.css
The Flask app serves the React SPA using this routing hierarchy:
- API Routes (
/api/v1/*) - Flask blueprints handle all API calls - Health Routes (
/health,/version) - Basic system endpoints - Assets (
/assets/*) - Serves React bundles fromdist/assets/ - Root (
/) - Servesdist/index.html - Catch-all (
/<path:path>) - Servesdist/index.htmlfor React Router
Key Implementation Details:
app.py: Configuresstatic_folderto point todist/routes.py: Implements SPA routing withsend_from_directory()api_blueprint: Registered with/api/v1prefix inapp.py
Frontend Development:
cd /path/to/PowerNight
npm run dev # Vite dev server on :3000 with HMR
./build.sh --no-docker # Production build with version increment (RECOMMENDED)
npm run build # Frontend-only build (version info won't update)
npm run preview # Preview production buildBackend Development:
python -m powernight.main # Full app with web interface
# Or directly start web interface programmaticallyFull Stack:
- Frontend proxies API calls to
http://localhost:8020/api(seevite.config.ts) - Backend serves React SPA from
dist/in production
Adding a New React Component:
- Create component in
src/powernight/web/src/components/ - Import and use in page components
- Rebuild:
./build.sh --no-docker(recommended) ornpm run build
Adding a New Page:
- Create page component in
src/powernight/web/src/pages/ - Add route in
src/powernight/web/src/App.tsx - Add navigation link in
Header.tsxif needed - Rebuild:
./build.sh --no-docker(recommended) ornpm run build
Current Routes:
/- Dashboard (Powerwall System Status)/planner- Task Management (formerly Scheduling)/history- Task Execution History and Logs/settings- Tesla OAuth, Auth Info, Version Info
Adding a New API Endpoint:
- Add endpoint to appropriate blueprint in
src/powernight/web/api/ - Add TypeScript method to
src/powernight/web/src/utils/api.ts - Use in React components via
useApihook - Rebuild frontend:
./build.sh --no-docker(recommended) ornpm run build
Styling:
- Use Tailwind CSS utility classes
- Global styles in
src/powernight/web/src/index.css - Component-specific styles use Tailwind classes inline
Build Script Usage:
./build.sh # Complete build with Docker image
./build.sh --no-docker # Build without Docker (recommended for development)Build Script Features:
- ✅ Increments build number automatically
- ✅ Generates fresh build timestamp
- ✅ Creates
version-info.jsonwith build metadata - ✅ Copies version info to
dist/directory - ✅ Builds frontend with Vite
- ✅ Optionally builds Docker image with build labels
Vite Configuration (vite.config.ts):
{
root: 'src/powernight/web', // Source root
base: '/', // Base URL path
build: {
outDir: '../../../dist', // Output to project root
rollupOptions: {
input: 'src/powernight/web/index.html'
}
}
}Version Information:
- Build Number: Auto-incremented from
BUILD_NUMBERfile - Build Timestamp: Current UTC timestamp in format "YYYY-MM-DD HH:MM:SS UTC +0000"
- Version: Read from
pyproject.toml - Dependencies: Extracted from
package.jsonandpyproject.toml - Runtime Info: Python, Node.js, npm versions
Docker Build:
- Dockerfile includes
npm run buildstep - Copies
dist/to/app/distin container - Flask serves from
/app/dist(viaPOWERNIGHT_STATIC_PATHenv var)
The React app uses Tesla authentication via pypowerwall framework in cloud mode:
- Tesla tokens stored in
.pypowerwall.authfile - Managed by
useAuthhook for authentication state - Tesla login flow handled through Settings page
- Authentication state managed by
useAuthhook with loading states
Authentication Flow:
- User initiates Tesla login via Settings page
- Redirects to tesla.com for login
- After successful login, pypowerwall framework handles token storage
- Tokens stored in
.pypowerwall.authfile for future use - Authentication state checked on app startup
TypeScript API Client (src/utils/api.ts):
- Axios-based
- Typed methods for all endpoints
- Automatic authentication handling
- Error handling with custom events
- Example:
import api from '@/utils/api'; const status = await api.getStatus(); const tasks = await api.getTasks();
Issue: 404 on React routes after deployment
- Cause: Flask catch-all route not configured
- Solution: Ensure
routes.pyhas/<path:path>route servingindex.html
Issue: Assets not loading
- Cause: Incorrect static folder path
- Solution: Verify
app.pysetsstatic_foldertodist/
Issue: API calls failing from React
- Cause: CORS or incorrect API prefix
- Solution: Check API blueprint registered with
/api/v1prefix
Issue: Old vanilla JS code references
- Cause: Stale imports or documentation
- Solution: Remove references; use React app only
Frontend Tests:
npm run test # Vitest unit tests
npm run test:ui # Vitest UI
npm run test:e2e # Playwright E2E tests
npm run test:e2e:ui # Playwright E2E test UI
npm run lint # ESLint
npm run type-check # TypeScript checkBackend Tests:
pytest tests/ # Python unit/integration tests| File | Purpose |
|---|---|
src/powernight/web/src/App.tsx |
Main React app with routing |
src/powernight/web/src/utils/api.ts |
TypeScript API client |
src/powernight/web/api/routes.py |
Flask SPA routing |
src/powernight/web/api/api.py |
Main API blueprint |
src/powernight/web/app.py |
Flask app factory |
vite.config.ts |
Vite build configuration |
package.json |
Frontend dependencies & scripts |
DO NOT use docker run for production deployments!
Why:
docker rundoes NOT mount volumes by default- All data (SQLite DB, OAuth tokens) will be LOST on container restart
docker-compose.ymlis configured with proper volume mounts
Container Path: /app/data/
Host Path: ./PowerNight-Data/
Files Stored:
PowerNight-Data/
├── powernight.db # SQLite database (schedules, tasks, config)
├── .pypowerwall.auth # Tesla OAuth tokens (PKCE, refresh tokens)
├── .pypowerwall.site # Selected Powerwall site ID
├── logs/ # Application logs
└── tokens/ # Token cache directory
# ✅ CORRECT - Start with persistent volumes
docker-compose up -d
# ✅ CORRECT - Rebuild and restart
docker-compose up -d --build
# ✅ CORRECT - Stop service
docker-compose down
# ✅ CORRECT - View logs
docker-compose logs -f PowerNight
# ❌ WRONG - Data will be lost on restart!
docker run -d -p 8020:8020 powernight:latestdocker-compose.yml:
services:
PowerNight:
image: zaaicom/powernight:latest
container_name: PowerNight
restart: unless-stopped
ports:
- "8020:8020"
environment:
- POWERNIGHT_AUTH_ENABLED=true
- POWERNIGHT_API_KEY=${POWERNIGHT_API_KEY:-your-secure-api-key-here}
- TESLA_CLIENT_ID=${TESLA_CLIENT_ID:-ownerapi}
- TESLA_EMAIL=${TESLA_EMAIL:-your-email@example.com}
- POWERNIGHT_AUTOMATION_ENABLED=${AUTOMATION_ENABLED:-true}
- POWERNIGHT_LOG_LEVEL=${LOG_LEVEL:-INFO}
volumes:
- ./PowerNight-Data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8020/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s# Backup
tar -czf powernight-backup-$(date +%Y%m%d).tar.gz PowerNight-Data/
# Restore
tar -xzf powernight-backup-20251019.tar.gz
# Verify data exists
ls -la PowerNight-Data/Problem: Container running but no data directory
# Check if volume is mounted
docker inspect PowerNight | grep -A 5 "Mounts"
# Should show:
# "Source": "/path/to/PowerNight-Data"
# "Destination": "/app/data"Problem: Lost Tesla OAuth tokens after restart
- Cause: Used
docker runinstead ofdocker-compose - Solution: Always use
docker-compose up -d - Recovery: Re-authenticate via Settings page
File: src/powernight/web/src/pages/Dashboard.tsx
Purpose: Real-time Powerwall system status display
API Endpoint: GET /api/auth/site-details
Features:
- System Information (Site Name, Site ID, Operating Mode, Battery Level)
- Power Data (Grid, Home, Battery, Solar power readings)
- Grid Settings (Backup Reserve, Grid Charging, Grid Export Mode)
- Additional Data (Load Power, Site Power, Last Updated timestamp)
- Raw Data (Collapsible JSON view of complete site details)
- Manual refresh button (no auto-fetch on mount)
File: src/powernight/web/src/pages/Planner.tsx
Purpose: Task management and scheduling (formerly Scheduling)
API Endpoints: GET /api/v1/tasks, POST /api/v1/tasks, PUT /api/v1/tasks/{id}, DELETE /api/v1/tasks/{id}
Features:
- Task creation and editing
- Command parameter configuration
- Task execution tracking
- Real-time status updates
- Task enable/disable functionality
File: src/powernight/web/src/pages/History.tsx
Purpose: Task execution history and logs
API Endpoints: GET /api/v1/logs/executions
Features:
- Task execution history
- Execution status tracking
- Error logging and debugging
- Filtering and pagination
File: src/powernight/web/src/pages/Settings.tsx
Purpose: Tesla OAuth, authentication info, version info, timezone management
API Endpoints: GET /api/auth/status, GET /api/config, GET /api/version-info
Features:
- Tesla OAuth flow management
- Authentication status display
- Version information
- Timezone configuration
- Site selection for multi-site setups
File: src/powernight/web/src/pages/Login.tsx
Purpose: Tesla authentication flow
Features:
- Tesla login flow initiation
- Authentication state management
- Error handling for authentication failures
- Redirect to Settings page for Tesla login
- ErrorBoundary.tsx - Error boundary for React error handling
- Header.tsx - Navigation header with route highlighting
- LoadingSpinner.tsx - Loading indicator component
- StatusBadge.tsx - Status display component
- ConfirmDialog.tsx - Confirmation dialog for destructive actions
- Tooltip.tsx - Tooltip component for help text
- LogsTable.tsx - Table component for displaying execution logs
- useAuth.ts - Authentication state management
- useApi.ts - API integration with loading states
- useLocalStorage.ts - LocalStorage persistence hook
- TimezoneContext.tsx - Timezone management and display
- AuthStatus - Authentication state interface
- Task - Task management interface
- CommandDefinition - Command parameter definitions
- LogEntry - Log entry structure
- ApiResponse - Standardized API response format
When working on PowerNight:
Web UI Features:
- ✅ Edit React components in
src/powernight/web/src/ - ✅ Use TypeScript for type safety
- ✅ Use Tailwind CSS for styling
- ✅ Add API methods to
utils/api.ts - ✅ Rebuild with
./build.sh --no-docker(recommended) ornpm run build - ❌ NEVER recreate vanilla JS/templates/CSS
- ❌ NEVER bypass the React app
Current Routes:
/- Dashboard (Powerwall System Status)/planner- Task Management (formerly Scheduling)/history- Task Execution History and Logs/settings- Tesla OAuth, Auth Info, Version Info
Docker Deployment:
- ✅ ALWAYS use
docker-compose up -d - ✅ Verify volumes are mounted
- ✅ Backup
PowerNight-Data/directory - ❌ NEVER use
docker runfor production - ❌ NEVER ignore volume configuration
Data Persistence:
- All critical data in
/app/data(container) →./PowerNight-Data/(host) - SQLite database, OAuth tokens, logs all require persistent storage
- Data loss occurs if container runs without volume mounts
Authentication:
- Tesla authentication via pypowerwall framework in cloud mode
- Authentication state managed by
useAuthhook - Tesla tokens stored in
.pypowerwall.authfile - Login flow initiated through Settings page
The React SPA is the single source of truth for the PowerNight web interface.