From 8d5ad6a809965b064c8f097944a7b23ed014840d Mon Sep 17 00:00:00 2001 From: serversdwn Date: Tue, 25 Nov 2025 20:39:40 +0000 Subject: [PATCH] Reworked variable system, no longer hardcoded --- backend/.env.example | 14 ++++++++++ backend/app/database.py | 3 ++- backend/app/main.py | 9 ++++--- backend/app/settings.py | 37 +++++++++++++++++++++++++++ docker-compose.yml | 10 +++++--- frontend/.env.example | 18 +++++++++++++ frontend/src/App.jsx | 2 +- frontend/src/components/SearchBar.jsx | 3 ++- frontend/src/utils/api.js | 2 +- frontend/vite.config.js | 24 +++++++++-------- 10 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 backend/.env.example create mode 100644 backend/app/settings.py create mode 100644 frontend/.env.example diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..e7dd4cc --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,14 @@ +# Database Configuration +DATABASE_URL=sqlite:///./tesseract.db + +# API Configuration +API_TITLE=Tesseract - Nested Todo Tree API +API_DESCRIPTION=API for managing deeply nested todo trees +API_VERSION=1.0.0 + +# CORS Configuration (comma-separated list of allowed origins) +CORS_ORIGINS=http://localhost:5173,http://localhost:3000 + +# Server Configuration +HOST=0.0.0.0 +PORT=8000 diff --git a/backend/app/database.py b/backend/app/database.py index 20a85c7..5e6f0b3 100644 --- a/backend/app/database.py +++ b/backend/app/database.py @@ -1,8 +1,9 @@ from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker +from .settings import settings -SQLALCHEMY_DATABASE_URL = "sqlite:///./tesseract.db" +SQLALCHEMY_DATABASE_URL = settings.database_url engine = create_engine( SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} diff --git a/backend/app/main.py b/backend/app/main.py index 7640ff3..6c5bf9e 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -6,20 +6,21 @@ import json from . import models, schemas, crud from .database import engine, get_db +from .settings import settings # Create database tables models.Base.metadata.create_all(bind=engine) app = FastAPI( - title="Tesseract - Nested Todo Tree API", - description="API for managing deeply nested todo trees", - version="1.0.0" + title=settings.api_title, + description=settings.api_description, + version=settings.api_version ) # CORS middleware for frontend app.add_middleware( CORSMiddleware, - allow_origins=["http://localhost:5173", "http://localhost:3000"], # Vite default port + allow_origins=settings.cors_origins_list, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], diff --git a/backend/app/settings.py b/backend/app/settings.py new file mode 100644 index 0000000..631c72b --- /dev/null +++ b/backend/app/settings.py @@ -0,0 +1,37 @@ +from pydantic_settings import BaseSettings, SettingsConfigDict +from typing import List + + +class Settings(BaseSettings): + """Application settings loaded from environment variables""" + + # Database Configuration + database_url: str = "sqlite:///./tesseract.db" + + # API Configuration + api_title: str = "Tesseract - Nested Todo Tree API" + api_description: str = "API for managing deeply nested todo trees" + api_version: str = "1.0.0" + + # CORS Configuration + cors_origins: str = "http://localhost:5173,http://localhost:3000" + + # Server Configuration + host: str = "0.0.0.0" + port: int = 8000 + + model_config = SettingsConfigDict( + env_file=".env", + env_file_encoding="utf-8", + case_sensitive=False, + extra="ignore" + ) + + @property + def cors_origins_list(self) -> List[str]: + """Parse comma-separated CORS origins into a list""" + return [origin.strip() for origin in self.cors_origins.split(",")] + + +# Global settings instance +settings = Settings() diff --git a/docker-compose.yml b/docker-compose.yml index 6c081c6..dc9b7e1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: backend: build: @@ -7,10 +5,12 @@ services: dockerfile: Dockerfile container_name: tesseract-backend ports: - - "8000:8000" + - "8002:8002" volumes: - ./backend/app:/app/app - tesseract-db:/app + env_file: + - ./backend/.env environment: - PYTHONUNBUFFERED=1 restart: unless-stopped @@ -21,7 +21,9 @@ services: dockerfile: Dockerfile container_name: tesseract-frontend ports: - - "3000:80" + - "3002:80" + env_file: + - ./frontend/.env depends_on: - backend restart: unless-stopped diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 0000000..e73b3ba --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1,18 @@ +# API Configuration +# Base URL for API requests (relative path used in production) +VITE_API_BASE_URL=/api + +# Backend API URL (used for development proxy) +VITE_API_URL=http://localhost:8000 + +# Development Configuration +# Port for Vite development server +VITE_DEV_PORT=5173 + +# Application Configuration +# Application version displayed in UI +VITE_APP_VERSION=0.1.5 + +# UI/UX Configuration +# Search input debounce delay in milliseconds +VITE_SEARCH_DEBOUNCE_MS=300 diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index d3d3ed9..9c77261 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -13,7 +13,7 @@ function App() {

TESSERACT Task Decomposition Engine - v0.1.5 + v{import.meta.env.VITE_APP_VERSION || '0.1.5'}

diff --git a/frontend/src/components/SearchBar.jsx b/frontend/src/components/SearchBar.jsx index eeaea18..74714ce 100644 --- a/frontend/src/components/SearchBar.jsx +++ b/frontend/src/components/SearchBar.jsx @@ -84,9 +84,10 @@ function SearchBar() { return } + const debounceMs = parseInt(import.meta.env.VITE_SEARCH_DEBOUNCE_MS || '300') const timeoutId = setTimeout(() => { handleSearch(query) - }, 300) + }, debounceMs) return () => clearTimeout(timeoutId) }, [query, selectedProjects]) diff --git a/frontend/src/utils/api.js b/frontend/src/utils/api.js index 4805c54..2e94812 100644 --- a/frontend/src/utils/api.js +++ b/frontend/src/utils/api.js @@ -1,4 +1,4 @@ -const API_BASE = '/api'; +const API_BASE = import.meta.env.VITE_API_BASE_URL || '/api'; async function fetchAPI(endpoint, options = {}) { const response = await fetch(`${API_BASE}${endpoint}`, { diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 460f68a..57b2151 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -1,15 +1,19 @@ -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' -export default defineConfig({ - plugins: [react()], - server: { - host: '0.0.0.0', - port: 5173, - proxy: { - '/api': { - target: 'http://localhost:8000', - changeOrigin: true, +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), '') + + return { + plugins: [react()], + server: { + host: '0.0.0.0', + port: parseInt(env.VITE_DEV_PORT || '5173'), + proxy: { + '/api': { + target: env.VITE_API_URL || 'http://localhost:8000', + changeOrigin: true, + } } } }