{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "fastapi-service",
  "type": "registry:base",
  "title": "tneemo/fastapi-service",
  "description": "Python REST API starter with FastAPI: typed settings from env, JSON error handling, health check, router layout and pytest.",
  "author": "tneemo",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": ".env.example",
      "type": "registry:file",
      "target": "~/.env.example",
      "content": "APP_NAME=service\nENVIRONMENT=development\n# JSON list of allowed browser origins, e.g. [\"http://localhost:5173\"]\nCORS_ORIGINS=[]\n"
    },
    {
      "path": ".gitignore",
      "type": "registry:file",
      "target": "~/.gitignore",
      "content": ".venv/\n__pycache__/\n.pytest_cache/\n.env\n*.db\n"
    },
    {
      "path": "AGENTS.md",
      "type": "registry:file",
      "target": "~/AGENTS.md",
      "content": "# Conventions\n\n- The FastAPI app is assembled in `app/main.py` (`create_app`). Add each feature as a router module in `app/routers/` and include it there: `app.include_router(items.router, prefix=\"/items\")`.\n- Use Pydantic models for request and response bodies. Raise `HTTPException` for expected errors.\n- Settings come from environment variables via `app/config.py` (`get_settings()`); document new ones in `.env.example`.\n- Tests live in `tests/` and use `fastapi.testclient.TestClient`. Run them with `.venv/bin/python -m pytest` (`.venv\\Scripts\\python -m pytest` on Windows).\n- Run the server with `.venv/bin/python -m uvicorn app.main:app --reload`.\n- Builds installed with pkg are listed in `pkg.lock.json`. Look for existing ones before writing a common feature: `npx -y @tneemo/pkg search \"<need>\" --stack python,fastapi`.\n"
    },
    {
      "path": "app/__init__.py",
      "type": "registry:file",
      "target": "~/app/__init__.py",
      "content": ""
    },
    {
      "path": "app/config.py",
      "type": "registry:file",
      "target": "~/app/config.py",
      "content": "from functools import lru_cache\n\nfrom pydantic_settings import BaseSettings, SettingsConfigDict\n\n\nclass Settings(BaseSettings):\n    \"\"\"Settings read from environment variables (and .env). Add new ones here.\"\"\"\n\n    model_config = SettingsConfigDict(env_file=\".env\", extra=\"ignore\")\n\n    app_name: str = \"service\"\n    environment: str = \"development\"\n    cors_origins: list[str] = []\n\n\n@lru_cache\ndef get_settings() -> Settings:\n    return Settings()\n"
    },
    {
      "path": "app/main.py",
      "type": "registry:file",
      "target": "~/app/main.py",
      "content": "import logging\n\nfrom fastapi import FastAPI, Request\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom fastapi.responses import JSONResponse\n\nfrom app.config import get_settings\nfrom app.routers import health\n\nlogger = logging.getLogger(\"app\")\n\n\ndef create_app() -> FastAPI:\n    settings = get_settings()\n    app = FastAPI(title=settings.app_name)\n\n    if settings.cors_origins:\n        app.add_middleware(\n            CORSMiddleware,\n            allow_origins=settings.cors_origins,\n            allow_methods=[\"*\"],\n            allow_headers=[\"*\"],\n        )\n\n    @app.exception_handler(Exception)\n    async def unhandled(request: Request, exc: Exception) -> JSONResponse:\n        logger.exception(\"Unhandled error on %s %s\", request.method, request.url.path)\n        return JSONResponse(status_code=500, content={\"detail\": \"Internal server error\"})\n\n    app.include_router(health.router)\n    # Include feature routers here, e.g. app.include_router(items.router, prefix=\"/items\")\n\n    return app\n\n\napp = create_app()\n"
    },
    {
      "path": "app/routers/__init__.py",
      "type": "registry:file",
      "target": "~/app/routers/__init__.py",
      "content": ""
    },
    {
      "path": "app/routers/health.py",
      "type": "registry:file",
      "target": "~/app/routers/health.py",
      "content": "from fastapi import APIRouter\n\nrouter = APIRouter(tags=[\"health\"])\n\n\n@router.get(\"/health\")\ndef health() -> dict[str, str]:\n    return {\"status\": \"ok\"}\n"
    },
    {
      "path": "pytest.ini",
      "type": "registry:file",
      "target": "~/pytest.ini",
      "content": "[pytest]\ntestpaths = tests\npythonpath = .\n"
    },
    {
      "path": "requirements-dev.txt",
      "type": "registry:file",
      "target": "~/requirements-dev.txt",
      "content": "-r requirements.txt\npytest>=8\nhttpx>=0.27\n"
    },
    {
      "path": "requirements.txt",
      "type": "registry:file",
      "target": "~/requirements.txt",
      "content": "fastapi>=0.115\nuvicorn>=0.30\npydantic-settings>=2.4\n"
    },
    {
      "path": "tests/__init__.py",
      "type": "registry:file",
      "target": "~/tests/__init__.py",
      "content": ""
    },
    {
      "path": "tests/test_health.py",
      "type": "registry:file",
      "target": "~/tests/test_health.py",
      "content": "from fastapi.testclient import TestClient\n\nfrom app.main import app\n\nclient = TestClient(app)\n\n\ndef test_health():\n    response = client.get(\"/health\")\n    assert response.status_code == 200\n    assert response.json() == {\"status\": \"ok\"}\n\n\ndef test_unknown_route_is_json_404():\n    response = client.get(\"/nope\")\n    assert response.status_code == 404\n    assert response.json() == {\"detail\": \"Not Found\"}\n"
    }
  ],
  "envVars": {},
  "docs": "This is a foundation: it creates the project. After installing (pkg creates `.venv` and installs the requirements):\n\n1. Run the tests: `.venv/bin/python -m pytest` (Windows: `.venv\\Scripts\\python -m pytest`).\n2. Start the server: `.venv/bin/python -m uvicorn app.main:app --reload`, then open http://localhost:8000/docs.\n3. Add features as routers in `app/routers/<feature>.py` and include them in `create_app()` in `app/main.py`. Follow `AGENTS.md`.\n",
  "categories": [
    "api",
    "rest",
    "http",
    "server",
    "backend",
    "starter",
    "python",
    "fastapi",
    "service"
  ],
  "meta": {
    "pkg": "https://pkg.tneemo.com/tneemo/fastapi-service",
    "version": "1.0.0",
    "license": "MIT"
  }
}