Files
vision/card-renderer/app/models.py
Gregor Klevze 58ee1b3bdd feat: add card-renderer internal service (v1)
- New card-renderer FastAPI service (Python 3.11 + Pillow)
  - GET /health, GET /templates
  - POST /render (URL input)
  - POST /render/file (multipart upload)
  - POST /render/meta (dry-run layout metadata)
  - nova-artwork-v1 template: cover crop, gradient overlay, text, logo
  - SSRF-safe async image fetch with redirect validation
  - Smart center cover crop isolated for future YOLO focal-point support
  - Graceful font/logo fallback when assets are absent

- docker-compose.yml: add card-renderer service + healthcheck;
  extend gateway with CARD_RENDERER_URL and depends_on

- gateway/main.py: proxy endpoints under /cards/*
  - GET  /cards/templates
  - POST /cards/render
  - POST /cards/render/file
  - POST /cards/render/meta
  All protected by existing APIKeyMiddleware
2026-03-31 10:39:29 +02:00

32 lines
885 B
Python

from __future__ import annotations
from typing import Literal
from pydantic import BaseModel, Field, HttpUrl
class CardRenderRequest(BaseModel):
template: str = Field(default="nova-artwork-v1")
width: int = Field(default=1200, ge=100, le=4000)
height: int = Field(default=630, ge=100, le=4000)
output: Literal["png", "jpeg", "jpg", "webp"] = "webp"
quality: int = Field(default=90, ge=1, le=100)
image_url: HttpUrl
title: str | None = None
subtitle: str | None = None
username: str | None = None
category: str | None = None
tags: list[str] = []
show_logo: bool = True
show_avatar: bool = False
avatar_url: HttpUrl | None = None
theme: Literal["dark", "light", "nova"] = "dark"
class CardMetaResponse(BaseModel):
template: str
width: int
height: int
crop_box: list[int]
safe_area: dict
theme: str