From b45cd2d508ac84c830a4d00fa73c16b42dd9300a Mon Sep 17 00:00:00 2001 From: juvdiaz Date: Wed, 10 Jun 2026 11:37:57 -0600 Subject: [PATCH] Document translation workflow architecture --- README.md | 12 ++++++++---- apps/website/README.md | 12 ++++++++++++ apps/website/blog.php | 25 ++++++++++++++++++++----- apps/website/lang/en.php | 5 +++-- apps/website/lang/nah.php | 5 +++-- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a28fd57..621b324 100644 --- a/README.md +++ b/README.md @@ -652,16 +652,20 @@ cleaned unless you explicitly include it. ## Website App The website is a PHP app under `apps/website`. It includes a home page, CV page, -blog page, and demos page, plus a lightweight translation flow backed by Ollama. +blog page, and demos page, plus a lightweight translation flow backed by Redis, +n8n, and Ollama. Static language files live in `apps/website/lang`; `en.php` and `nah.php` are curated source files, with the Nahuatl home page intentionally biased toward as many Nahuatl words as possible while keeping technical terms understandable. Unsupported browser languages use the same-origin `/translate.php` endpoint, which calls Ollama server-side through `OLLAMA_HOST` and `OLLAMA_MODEL`; the -browser never calls the private Ollama IP directly. The default model is the -custom `website-translator` Ollama model defined in +browser never calls the private Ollama IP directly. Redis caches per-string +translation results in the `website-production` namespace, while n8n is +available for translation prewarming and batch workflow jobs. The default model +is the custom `website-translator` Ollama model defined in `apps/website/ollama/Modelfile`. Generated runtime language JSON is saved -through `save_lang.php` on the website PVC. +through `save_lang.php` on the website PVC, and `translate.php` emits structured +logs for cache hits, misses, Ollama latency, JSON parse failures, and timeouts. Create or refresh the Ollama model on the Debian server before deploying a website image that points at it: diff --git a/apps/website/README.md b/apps/website/README.md index 21199b3..83625f7 100644 --- a/apps/website/README.md +++ b/apps/website/README.md @@ -55,6 +55,18 @@ The OCI edge nginx layer handles gzip, cache HITs, HTTP/2, TLS session reuse, client keepalive, and upstream keepalive to the Traefik backend. CSS and JavaScript keep the edge's longer immutable asset policy. +## Translation Flow + +Unsupported browser languages call the same-origin `translate.php` endpoint. +The endpoint sanitizes and batches text, checks Redis per string, calls the +custom `website-translator` Ollama model only for cache misses, writes fresh +translations back to Redis with a TTL, then returns results in the original +order. The browser never calls the private Ollama address directly. + +n8n is deployed separately at `https://n8n.lab2025.duckdns.org` and receives +`OLLAMA_BASE_URL=http://192.168.100.68:11434` so workflows can prewarm +translations or run batch jobs against the Debian-host Ollama API. + ## Translation Observability `translate.php` emits one structured JSON log event for each valid translation diff --git a/apps/website/blog.php b/apps/website/blog.php index b79c407..d7bdde0 100644 --- a/apps/website/blog.php +++ b/apps/website/blog.php @@ -57,6 +57,7 @@ $stackKeys = [ 'blog_stack_16', 'blog_stack_17', 'blog_stack_18', + 'blog_stack_19', ]; $caseStudyCards = [ @@ -174,6 +175,12 @@ $stackSourceLinks = [ ['label' => 'Cosign build flow', 'path' => 'lab.sh'], ['label' => 'apps variables', 'path' => 'bootstrap/apps/variables.tf'], ], + 'blog_stack_19' => [ + ['label' => 'translate.php', 'path' => 'apps/website/translate.php'], + ['label' => 'website Redis manifest', 'path' => 'apps/website/web-app.yaml'], + ['label' => 'n8n app manifest', 'path' => 'apps/n8n/web-app.yaml'], + ['label' => 'Ollama Modelfile', 'path' => 'apps/website/ollama/Modelfile'], + ], ]; function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $sourceBase): void { @@ -310,7 +317,7 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so
Homelab architecture map - Git push enters Gitea, Gitea Actions validates and builds app images, OpenTofu manages cluster and provisioning layers, Debian keeps the control plane and PXE services, Pimox app workers run Argo CD, Kyverno, and app workloads on NVMe-backed VMs, OpenWrt can run as an opt-in firewall VM, and the OCI edge routes traffic into Kubernetes services. + Git push enters Gitea, Gitea Actions validates and builds app images, OpenTofu manages cluster and provisioning layers, Debian keeps the control plane, PXE services, and Ollama translation model, Pimox app workers run Argo CD, Kyverno, Redis-backed website translation, n8n workflow automation, and app workloads on NVMe-backed VMs, OpenWrt can run as an opt-in firewall VM, and the OCI edge routes traffic into Kubernetes services. @@ -405,8 +412,8 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so Storage and backups - OpenEBS retained PVs - Gitea dumps and monitoring data + OpenEBS retained PVs, n8n data + Gitea dumps, logs, Redis cache @@ -437,8 +444,8 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so Orange Pi 5 Plus Pimox pimox-worker app nodes workers on nvme_thin_pool - Argo CD, Kyverno, apps - idempotent qm automation + Argo CD, Kyverno, website, n8n + Redis cache and app workloads @@ -457,6 +464,12 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so pulled by app workers + + + Ollama translation API + website-translator on Debian + + @@ -476,6 +489,7 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so + push workflow @@ -491,6 +505,7 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so secure tunnel service traffic image pulls + translation calls
diff --git a/apps/website/lang/en.php b/apps/website/lang/en.php index 999b073..2082b6f 100644 --- a/apps/website/lang/en.php +++ b/apps/website/lang/en.php @@ -150,10 +150,11 @@ return [ 'blog_stack_16' => 'The monitoring layer now includes Prometheus Stack, Grafana, Loki, Promtail, node-exporter, and kube-state-metrics, with placement guardrails so platform add-ons stop defaulting to the control plane.', 'blog_stack_17' => 'The portfolio website keeps Apache at the core, runs PHP through PHP-FPM with OPcache, pre-renders read-heavy pages into static HTML during the image build, and leaves PHP for write and translation endpoints.', 'blog_stack_18' => 'The supply-chain path now uses BuildKit SBOM attestations, Cosign signatures, a cluster-published public key, and an audit-first Kyverno ImageValidatingPolicy that can be promoted to deny unsigned local-registry pods.', + 'blog_stack_19' => 'The translation path now uses Redis for per-string cache hits, a custom Ollama website-translator model on the Debian server for cache misses, n8n for prewarming and batch workflow automation, and structured logs for cache, latency, JSON parse, and timeout signals.', 'blog_arch_kicker' => 'Architecture map', 'blog_arch_title' => 'The homelab, end to end', - 'blog_arch_intro' => 'The current delivery path starts with a push to Gitea, runs local validation, builds arm64 images, syncs the validated commit into the GitOps mirror, and lets Argo CD reconcile from the app workers. The infrastructure path stays manual through lab.sh, including the PXE/Pimox template builder, NVMe-backed worker clones, Kyverno policy placement, and the opt-in OpenWrt firewall VM, while the OCI edge routes public traffic back through the private path.', - 'blog_arch_caption' => 'The diagram is intentionally operational: it shows the app delivery loop, image flow, provisioning path, worker-placement boundary, monitoring layer, OpenWrt firewall option, and public traffic path without hiding the practical bits that make a small lab behave like a platform.', + 'blog_arch_intro' => 'The current delivery path starts with a push to Gitea, runs local validation, builds arm64 images, syncs the validated commit into the GitOps mirror, and lets Argo CD reconcile from the app workers. The infrastructure path stays manual through lab.sh, including the PXE/Pimox template builder, NVMe-backed worker clones, Kyverno policy placement, Redis-backed website translation, n8n workflow automation, and the opt-in OpenWrt firewall VM, while the OCI edge routes public traffic back through the private path.', + 'blog_arch_caption' => 'The diagram is intentionally operational: it shows the app delivery loop, image flow, provisioning path, worker-placement boundary, monitoring layer, Redis/n8n/Ollama translation path, OpenWrt firewall option, and public traffic path without hiding the practical bits that make a small lab behave like a platform.', 'blog_arch_fun_link' => 'Open the Christmas-tree version', 'blog_activity_kicker' => 'Recent activity log', 'blog_activity_title' => 'What changed since the first build', diff --git a/apps/website/lang/nah.php b/apps/website/lang/nah.php index 74a2f94..3f05656 100644 --- a/apps/website/lang/nah.php +++ b/apps/website/lang/nah.php @@ -150,10 +150,11 @@ return [ 'blog_stack_16' => 'Monitoring layer axcan includes Prometheus Stack, Grafana, Loki, Promtail, node-exporter, ihuan kube-state-metrics, ika placement guardrails para platform add-ons ma amo default to control plane.', 'blog_stack_17' => 'Portfolio website keeps Apache at core, runs PHP through PHP-FPM ika OPcache, pre-renders read-heavy pages into static HTML during image build, ihuan leaves PHP para write ihuan translation endpoints.', 'blog_stack_18' => 'Supply-chain path axcan uses BuildKit SBOM attestations, Cosign signatures, public key ipan cluster, ihuan audit-first Kyverno ImageValidatingPolicy in huel mopromote para deny unsigned local-registry pods.', + 'blog_stack_19' => 'Translation path axcan uses Redis para per-string cache hits, custom Ollama website-translator model ipan Debian server para cache misses, n8n para prewarming ihuan batch workflows, ihuan structured logs para cache, latency, JSON parse, ihuan timeout signals.', 'blog_arch_kicker' => 'Architecture mapa', 'blog_arch_title' => 'Homelab, end to end', - 'blog_arch_intro' => 'Current delivery path starts ika push to Gitea, runs local validation, builds arm64 images, syncs validated commit into GitOps mirror, ihuan lets Argo CD reconcile from app workers. Infrastructure path stays manual through lab.sh, including PXE/Pimox template builder, NVMe-backed worker clones, Kyverno policy placement, ihuan opt-in OpenWrt firewall VM, while OCI edge routes public traffic back through private path.', - 'blog_arch_caption' => 'Diagram intentionally operational: quinextia app delivery loop, image flow, provisioning path, worker-placement boundary, monitoring layer, OpenWrt firewall option, ihuan public traffic path ahmo hiding practical bits in quichihua small lab behave like platform.', + 'blog_arch_intro' => 'Current delivery path starts ika push to Gitea, runs local validation, builds arm64 images, syncs validated commit into GitOps mirror, ihuan lets Argo CD reconcile from app workers. Infrastructure path stays manual through lab.sh, including PXE/Pimox template builder, NVMe-backed worker clones, Kyverno policy placement, Redis-backed website translation, n8n workflow automation, ihuan opt-in OpenWrt firewall VM, while OCI edge routes public traffic back through private path.', + 'blog_arch_caption' => 'Diagram intentionally operational: quinextia app delivery loop, image flow, provisioning path, worker-placement boundary, monitoring layer, Redis/n8n/Ollama translation path, OpenWrt firewall option, ihuan public traffic path ahmo hiding practical bits in quichihua small lab behave like platform.', 'blog_arch_fun_link' => 'Xiquitta Christmas-tree version', 'blog_activity_kicker' => 'Yancuic activity log', 'blog_activity_title' => 'Tlein omopatla since first build',