diff --git a/docs/assets/uteke-banner.png b/docs/assets/uteke-banner.png index d8d1800a..82530e94 100644 Binary files a/docs/assets/uteke-banner.png and b/docs/assets/uteke-banner.png differ diff --git a/docs/assets/uteke-banner.svg b/docs/assets/uteke-banner.svg new file mode 100644 index 00000000..56fe0693 --- /dev/null +++ b/docs/assets/uteke-banner.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + codecoradev / uteke + + + Offline Semantic Memory + for AI Agents + + + ~45ms recall · single Rust binary · zero cloud + + + + curl -sSL codecora.dev/uteke/install | sh + + + Apache 2.0 · offline-first · CPU-only + + + Mobile: https://uteke.app · local-first · your data never leaves your device + + + HNSW + FTS5 + RRF(k=60) · ONNX EmbeddingGemma · MCP server + diff --git a/docs/assets/uteke-icon.png b/docs/assets/uteke-icon.png new file mode 100644 index 00000000..691dd0f7 Binary files /dev/null and b/docs/assets/uteke-icon.png differ diff --git a/docs/comparison.md b/docs/comparison.md index e715a3f2..c310398a 100644 --- a/docs/comparison.md +++ b/docs/comparison.md @@ -302,7 +302,7 @@ There's no "best" memory layer. There's the **right one for your constraints**. **Uteke chose simplicity, privacy, and multi-agent collaboration.** If those are your priorities too, give it a try: ```bash -curl -sSL codecora.dev/install | sh +curl -sSL codecora.dev/uteke/install | sh uteke onboard ``` diff --git a/scripts/regen-banner.py b/scripts/regen-banner.py new file mode 100644 index 00000000..a8b60af8 --- /dev/null +++ b/scripts/regen-banner.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +"""Regenerate docs/assets/uteke-banner.png from the evergreen SVG source. + +The banner is intentionally EVERGREEN: no version, star, or test counts are +baked in — dynamic figures belong to the shields.io badges in README.md. +The mascot is the OFFICIAL Uteke icon from uteke-mobile +(docs/assets/uteke-icon.png), composited with rounded corners by this +script after the SVG render — cairosvg cannot embed raster images. + +Usage: + python3 scripts/regen-banner.py + +Renders @2x (2560x1280) for retina crispness (README displays at width=640). +Requires: cairosvg, pillow (pip install cairosvg pillow). +""" + +from pathlib import Path + +import cairosvg +from PIL import Image, ImageDraw + +ROOT = Path(__file__).resolve().parent.parent +SVG = ROOT / "docs" / "assets" / "uteke-banner.svg" +ICON = ROOT / "docs" / "assets" / "uteke-icon.png" +PNG = ROOT / "docs" / "assets" / "uteke-banner.png" + +RENDER_SCALE = 2 # SVG is authored at 1280x640, rendered at 2560x1280 +# Avatar slot in SVG authoring coords — keep in sync with uteke-banner.svg +ICON_XY = (56, 150) +ICON_SIZE = 48 # SVG units; rendered at 96px +ICON_RADIUS = 13 # matches the app-icon corner radius of uteke-mobile + + +def main() -> None: + if not SVG.exists(): + raise SystemExit(f"missing source: {SVG}") + if not ICON.exists(): + raise SystemExit(f"missing icon: {ICON}") + + cairosvg.svg2png(url=str(SVG), write_to=str(PNG), output_width=1280 * RENDER_SCALE, + output_height=640 * RENDER_SCALE) + banner = Image.open(PNG).convert("RGBA") + + size = ICON_SIZE * RENDER_SCALE + icon = Image.open(ICON).convert("RGBA").resize((size, size), Image.Resampling.LANCZOS) + mask = Image.new("L", (size, size), 0) + draw = ImageDraw.Draw(mask) + draw.rounded_rectangle([0, 0, size - 1, size - 1], radius=ICON_RADIUS * RENDER_SCALE, fill=255) + banner.paste(icon, (ICON_XY[0] * RENDER_SCALE, ICON_XY[1] * RENDER_SCALE), mask) + + banner.convert("RGB").save(PNG, "PNG", optimize=True) + size_kb = PNG.stat().st_size // 1024 + print(f"rendered {PNG.relative_to(ROOT)} ({PNG.stat().st_size} bytes, {size_kb} KB)") + + +if __name__ == "__main__": + main()