Roadmap
Synced read-only from
/home/synvirt/synvirt-platform/docs-internal/roadmap.md. Edit at the source, not here.
Roadmap
Section titled “Roadmap”MVP goal: a visitor can understand SynVirt, see the product, download it, find documentation and get support without leaving the ecosystem — on one server, but architected to split across hosts without touching app code.
Attack order: Phase 0 → M0 → M1 → M2 → M3 → M4 → M5 → M6 → M7 → M8.
Phase 0 — Devbox ✅ done
Section titled “Phase 0 — Devbox ✅ done”Reproducible dev environment on Ubuntu Server (24.04 dev / 26.04 prod).
-
devbox-bootstrap.sh(idempotent) -
compose.yaml+ dev/prod overrides - Multi-database Postgres init (per-service role + owner)
- Caddy
tls internalfor*.synvirt.test - SOPS/age secret layout, Taskfile, monorepo skeleton
- Acceptance verified on the box 2026-06-28 (bootstrap,
task up, CA trusted, 4 DBs present,sqlx migrate run)
M0 — Foundations ✅ done
Section titled “M0 — Foundations ✅ done”Monorepo, design tokens, base UI (shadcn), i18n (en/es), dark/light, Storybook, Next.js 16 app scaffolded.
- Next.js 16 (App Router, Turbopack) scaffolded in
apps/web;/(en) and/esprerender statically and serve through Caddy atsynvirt.test - Design tokens in
@synvirt/ui/tokens.css(raw palette + shadcn-style semantic aliases), Tailwind v4 CSS-first theme in@synvirt/ui/theme.css(replaces the oldpackages/configTailwind v3 preset) - Base UI in
@synvirt/ui: Button, Card, Badge (shadcn pattern: cva + radix Slot +cn);components.jsonready forshadcn add - i18n en/es via next-intl (
localePrefix: as-needed,src/proxy.ts) - Dark/light via next-themes (
data-themeattribute, default dark) - Storybook 10 (react-vite) in
packages/uiwith dark/light toolbar (task storybook)
M1 — Identity & SSO
Section titled “M1 — Identity & SSO”Keycloak realm (synvirt-web, synvirt-portal-api, synvirt-discourse),
OIDC login in Next.js, MFA + passkeys/WebAuthn, Google + Microsoft providers.
Risk: test Keycloak↔Discourse SSO early.
M2 — Marketing site + CMS
Section titled “M2 — Marketing site + CMS”Payload CMS embedded in web. Collections: Pages, BlogPosts, Releases, FAQs,
CaseStudies, Banners, SecurityAdvisories (stub). Homepage + Product +
Architecture + Pricing (preliminary) + Blog. ES/EN, dark/light, green Lighthouse.
2026-07-15 — CMS core pulled forward (the owner needs the content admin before M1): Payload 3.86 embedded in
apps/webwith local email/password auth — Keycloak SSO still lands in M1. en/es localization mirroring next-intl,users/mediacollections (media on local disk per ADR-0003),homeglobal driving the landing with 60 s ISR, initial migration inapps/web/src/migrations/and a seed from the static messages (pnpm payload run src/seed.ts). Admin athttps://synvirt.mx/admin(SynVirt-branded: wordmark + brand-blue primary actions). Same day: cdn.synvirt.mx — Caddy servesapps/web/mediadirectly (read-only bind mount, 7-day cache) and a PayloadafterReadhook rewrites media URLs toCDN_URL; smoke test inapps/web/src/scripts/cdn-smoke.ts. Remaining M2 scope (full collections, marketing pages, blog) unchanged.
2026-07-29 — marketing site migrated to WordPress (owner’s call: the site is to be client-editable and modular).
synvirt.mxnow serves WordPress 7.0.2 / PHP 8.4 (apps/wordpress) with a bespoke block theme carrying the same design tokens; the marketing sections became 15 server-rendered Gutenberg blocks, so pages are composed in the editor rather than coded. Content (en/es) was migrated out of the Payloadhomeglobal and the next-intl catalogues intoapps/wordpress/scripts/content.jsonand seeded by an idempotentprovision.sh. Polylang keeps the URL shape (/en,/es/es); topics moved to/platform/<topic>/.Scope of the swap: only the apex.
portal.synvirt.mx,docs.synvirt.mx,api.synvirt.mx,auth.synvirt.mxandsynvirt.mx/devare untouched and still run on the Next.js app / Rust API —synvirt-web.servicekeeps running. Payload is no longer reachable atsynvirt.mx/admin; WordPress admin is at/wp-admin.cdn.synvirt.mx was already built (see above) but had never served a byte — the media collection was empty and every image was in Next’s
public/. It now serves WordPress uploads: the 12 product/brand images were imported into the media library, the vhost points atapps/wordpress/uploads, andmu-plugins/synvirt-cdn.phprewrites attachment URLs, srcsets and post content. Verified: 8/8 homepage images load from the CDN, 0 local.2026-07-29 (later) — comparison page.
/compare/+/es/comparar/: a 10-row table against four named platforms (vSphere, Nutanix AHV, Proxmox VE, Morpheus), the six migrator adapters framed as “leaving what you have today”, the five host roles, and a substantiation notice. SynVirt claims are sourced from the productCLAUDE.mdon10.10.26.1and fromcrates/migrator/src(6 live-pull adapters, 10 offline formats — the site had been saying nine). The homepage table was rebuilt to the same four competitors and carries the same notice.Note: the product repo forbids naming those vendors inside that repository. That rule governs product code and docs; the marketing site names them by the owner’s decision. Comparison copy must not be copied back into the product repo.
Fixed while doing it: the header and footer navigation had never rendered since the theme was built. Polylang answers
theme_mod_nav_menu_locationsfrom its ownpolylang[nav_menus]option, which the seed was not writing — sohas_nav_menu()returned true under wp-cli (no language context) and false on the front end, and the menus silently disappeared.Infra note: the box’s LV only used half its disk (18.5 of 37 GB) and hit 100 % during the install; extended to the full VG (
lvextend -l +100%FREE).
M3 — Portal API core
Section titled “M3 — Portal API core”Axum + SQLx + OpenAPI (utoipa) → generates packages/api-client. Entities:
Organizations, Users (Keycloak sub mirror), Subscriptions, Licenses,
Downloads, SupportCases, AuditLog. JWT auth via Keycloak JWKS.
M4 — Customer Portal UI
Section titled “M4 — Customer Portal UI”Dashboard + 9 MVP modules (org, subscriptions, licenses, downloads, support, security, notifications). Soft warnings over hard restrictions.
M5 — Downloads & artifact integrity
Section titled “M5 — Downloads & artifact integrity”S3-compatible storage returns here (pgsty/minio fork, Garage or cloud S3/R2 —
see ADR-0003 amendment); signed URLs issued by portal-api after entitlement
check. Per-artifact SHA-256, signature, size, build ID, channel, arch. Never
serve binaries from the web server’s disk. Move Payload media from local disk
to the same backend (@payloadcms/storage-s3).
M6 — Commerce (Stripe + Odoo)
Section titled “M6 — Commerce (Stripe + Odoo)”Stripe Checkout + Billing; webhooks → entitlement + Odoo push (idempotent). SPEI/transfer + quote + PO manual flow. Pricing page wired to Stripe products.
M7 — Docs + Community + Status
Section titled “M7 — Docs + Community + Status”Fumadocs (versioned: 1.0/, latest/, release-notes/). Discourse self-hosted
(official discourse_docker, NOT in base compose) + DiscourseConnect SSO.
Structured bug-report form → support case. status.synvirt.mx hosted separately.
M8 — Search · Analytics · SEO · Hardening · Launch
Section titled “M8 — Search · Analytics · SEO · Hardening · Launch”Meilisearch universal search + command palette. Privacy-friendly analytics
(Plausible/Umami). SEO. Network segmentation verified, SOPS secrets, rate limit,
WAF/Turnstile, verified backups, runbooks. Deploy on 10.10.26.4 via Cloudflare
Tunnel → Caddy. Launch checklist.
Later (post-MVP)
Section titled “Later (post-MVP)”- Phase 2: orgs, advanced license admin, offline activation, full support cases, HCL, Knowledge Base, security advisories, public roadmap, installs.
- Phase 3: partner portal, Academy/certifications, marketplace, Enterprise trials, opt-in telemetry, Trust Center, Lifecycle Matrix, Security Center.