================= Flask Integration ================= Overview ======== The Flask bridge provides a simple way to serve wilco components from any Flask application. It exposes API endpoints via a Flask Blueprint for listing, fetching, and getting metadata for components. Installation ============ Install wilco with Flask support using the optional extra: .. code-block:: bash pip install wilco[flask] This installs wilco with Flask (>= 3.0.0). For development, you'll also want a WSGI server like gunicorn or werkzeug's built-in server. Quick start =========== Here's a minimal example that serves components from a directory: .. code-block:: python from pathlib import Path from flask import Flask from wilco import ComponentRegistry from wilco.bridges.flask import create_blueprint app = Flask(__name__) # Create a registry pointing to your components registry = ComponentRegistry(Path("./components")) # Register the wilco blueprint app.register_blueprint(create_blueprint(registry), url_prefix="/api") if __name__ == "__main__": app.run(host="0.0.0.0", port=8200) This creates three endpoints: - ``GET /api/bundles`` - List available components - ``GET /api/bundles/{name}.js`` - Get bundled JavaScript - ``GET /api/bundles/{name}/metadata`` - Get component metadata API reference ============= create_blueprint ---------------- .. code-block:: python from wilco.bridges.flask import create_blueprint def create_blueprint( registry: ComponentRegistry, build_dir: Path | None = None, ) -> Blueprint: """Create a Flask Blueprint with component serving endpoints. Args: registry: The component registry to serve components from. build_dir: Optional path to pre-built bundles directory. When provided, serves pre-built bundles from the manifest and falls back to live bundling for missing components. Returns: A Flask Blueprint that can be registered on any app. """ The returned blueprint provides the following endpoints: GET /bundles ^^^^^^^^^^^^ List all available component bundles. **Response:** .. code-block:: json [ {"name": "counter"}, {"name": "product_card"}, {"name": "ui.button"} ] GET /bundles/{name}.js ^^^^^^^^^^^^^^^^^^^^^^ Get the bundled JavaScript for a component. **Parameters:** - ``name``: Component name (e.g., ``counter``, ``ui.button``) **Response:** - Content-Type: ``application/javascript`` - Cache-Control: ``public, max-age=31536000, immutable`` The response contains the bundled ESM JavaScript with inline source maps. **Errors:** - ``404``: Component not found - ``422``: Invalid component name GET /bundles/{name}/metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Get metadata for a component, including its JSON schema and content hash. **Parameters:** - ``name``: Component name **Response:** .. code-block:: json { "title": "Counter", "description": "A simple counter component", "version": "1.0.0", "properties": { "initialValue": {"type": "number", "default": 0}, "step": {"type": "number", "default": 1} }, "hash": "abc123def456" } The ``hash`` field can be used for cache busting on the frontend. **Errors:** - ``404``: Component not found - ``422``: Invalid component name Component registry ================== Multiple sources ---------------- You can register components from multiple directories: .. code-block:: python registry = ComponentRegistry() # Add components from multiple sources registry.add_source(Path("./shared_components")) registry.add_source(Path("./app_components"), prefix="app") app.register_blueprint(create_blueprint(registry), url_prefix="/api") With a prefix, components are namespaced: - ``./shared_components/button/`` becomes ``button`` - ``./app_components/header/`` becomes ``app:header`` Caching ======= The Flask bridge returns long-lived cache headers for component bundles: .. code-block:: text Cache-Control: public, max-age=31536000, immutable To enable cache busting: 1. Fetch the metadata endpoint to get the ``hash`` 2. Append the hash as a query parameter: ``/api/bundles/counter.js?abc123`` The hash changes whenever the component source changes. Template-based rendering ======================== For server-rendered applications using Jinja2 templates, you can embed wilco components directly in your HTML templates using a widget helper: .. code-block:: python import html import json import uuid from markupsafe import Markup class WilcoComponentWidget: def __init__(self, component_name: str, props: dict = None, api_base: str = "/api"): self.component_name = component_name self.props = props or {} self.api_base = api_base def render(self) -> str: props_json = html.escape(json.dumps(self.props), quote=True) container_id = f"wilco-{uuid.uuid4().hex[:8]}" return f'''