feat: add app foundation (config.py, app.py, home page) #8

Merged
lmiranda merged 1 commits from feature/sprint1-app-foundation into development 2026-01-11 19:09:44 +00:00
3 changed files with 85 additions and 0 deletions

37
portfolio_app/app.py Normal file
View File

@@ -0,0 +1,37 @@
"""Dash application factory with Pages routing."""
import dash
from dash import html
from .config import get_settings
def create_app() -> dash.Dash:
"""Create and configure the Dash application."""
settings = get_settings()
app = dash.Dash(
__name__,
use_pages=True,
suppress_callback_exceptions=True,
title="Analytics Portfolio",
)
app.layout = html.Div(
[
dash.page_container,
]
)
return app
def main() -> None:
"""Run the development server."""
settings = get_settings()
app = create_app()
app.run(debug=settings.dash_debug, host="0.0.0.0", port=8050)
if __name__ == "__main__":
main()

34
portfolio_app/config.py Normal file
View File

@@ -0,0 +1,34 @@
"""Application configuration using Pydantic BaseSettings."""
from functools import lru_cache
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
# Database
database_url: str = "postgresql://portfolio:portfolio_dev@localhost:5432/portfolio"
postgres_user: str = "portfolio"
postgres_password: str = "portfolio_dev"
postgres_db: str = "portfolio"
# Application
dash_debug: bool = True
secret_key: str = "change-me-in-production"
# Logging
log_level: str = "INFO"
@lru_cache
def get_settings() -> Settings:
"""Get cached settings instance."""
return Settings()

View File

@@ -0,0 +1,14 @@
"""Bio landing page."""
import dash
from dash import html
dash.register_page(__name__, path="/", name="Home")
layout = html.Div(
[
html.H1("Analytics Portfolio"),
html.P("Welcome to Leo's analytics portfolio."),
html.P("Dashboard coming soon."),
]
)