|
| 1 | +# Deploy Anywhere — `/deploy` page + homepage section |
| 2 | + |
| 3 | +**Date:** 2026-06-22 |
| 4 | +**Status:** Approved design, ready for implementation plan |
| 5 | +**Repo:** `libredb-website` (Astro 6, Tailwind v4, static output) |
| 6 | + |
| 7 | +> **Amendment (2026-06-22, post-implementation).** This spec captures the |
| 8 | +> original design. The shipped feature evolved during the PR; where the text |
| 9 | +> below says otherwise, the implementation is authoritative: |
| 10 | +> - **5 categories, not 4.** A `kubernetes` ("Kubernetes & orchestration") |
| 11 | +> category was added between `oss-paas` and `managed-paas`. So `CategoryId` is |
| 12 | +> `'registry' | 'oss-paas' | 'kubernetes' | 'managed-paas' | 'cloud'`, the stat |
| 13 | +> strip reads "5 categories", and the classification grids span ①–⑤. |
| 14 | +> - **Stars show on all open-source platforms**, i.e. targets with a `github` |
| 15 | +> repo in *either* `oss-paas` or `kubernetes` — not "OSS PaaS only". The |
| 16 | +> aggregate sums those. |
| 17 | +> - Koyeb and Render gained one-click `deployUrl`s (Render moved `planned → |
| 18 | +> available`); the Koyeb URL ships no default credentials. |
| 19 | +
|
| 20 | +## 1. Purpose & audience |
| 21 | + |
| 22 | +LibreDB Studio is now distributed as one-click apps / marketplace listings and as |
| 23 | +package-registry artifacts across the modern deploy stack. The website does not |
| 24 | +reflect this — `GetStarted.astro` only shows a stale generic "Deploy to Render" |
| 25 | +button. This work replaces that with a strategic **"Deploy Anywhere"** story. |
| 26 | + |
| 27 | +The narrative spine: **one open-source OCI image → therefore it runs on every layer |
| 28 | +of the deploy stack.** That single technical fact is what lets LibreDB be everywhere, |
| 29 | +so the page leads with it, then fans out: **big picture → why → classification → |
| 30 | +detail → depth.** |
| 31 | + |
| 32 | +Three audiences served by one page: |
| 33 | + |
| 34 | +- **Users** — "how do I run this on my platform?" → find their platform fast, get a |
| 35 | + deploy button or docs link. |
| 36 | +- **Open-source world** — "LibreDB adds value to ecosystems you already use" → we meet |
| 37 | + teams where they deploy. |
| 38 | +- **Customers / investors** — reach and momentum at a glance: number of platforms, |
| 39 | + categories, install methods, and the combined GitHub-star weight of the open-source |
| 40 | + ecosystems LibreDB is embedded in. |
| 41 | + |
| 42 | +## 2. Success criteria |
| 43 | + |
| 44 | +- A visitor can locate their platform and reach a deploy action (button or docs) in |
| 45 | + one scan. |
| 46 | +- Official integrations (Railway, CapRover) are visually distinct and offer real |
| 47 | + one-click deploy actions. |
| 48 | +- Open-source PaaS cards show **live GitHub star counts** (build-time baked + client |
| 49 | + refresh), and the page surfaces an **aggregate star figure** as an investor signal. |
| 50 | +- Status (`Official` / `Available` / `Planned`) is accurate and trivially updatable |
| 51 | + (one-line data edit per platform). |
| 52 | +- Page matches existing site conventions: dark slate theme, `gradient-text`/`glow` |
| 53 | + utilities, `primary`/`accent` tokens, breadcrumb + JSON-LD pattern, copy-button |
| 54 | + script reuse. |
| 55 | +- No broken images, no layout shift from star loading, no horizontal page scroll. |
| 56 | + |
| 57 | +## 3. Architecture & files |
| 58 | + |
| 59 | +### New files |
| 60 | + |
| 61 | +| File | Role | |
| 62 | +|---|---| |
| 63 | +| `src/data/deploy-targets.ts` | **Single source of truth** — every platform/registry as a typed entry. Bumping `planned → available → official` is a one-line edit. | |
| 64 | +| `src/data/deploy-categories.ts` | Category metadata (id, title, icon, one-line description, display order). | |
| 65 | +| `src/lib/github-stars.ts` | Build-time fetch helper: given the list of `github` repos, returns `Record<repo, number>`. Includes a hardcoded **fallback map** so a failed/rate-limited/offline build still renders numbers. | |
| 66 | +| `src/components/DeployAnywhere.astro` | **Homepage section** — condensed: stat band + category overview + the two official spotlights + "See all N platforms →" linking to `/deploy`. | |
| 67 | +| `src/components/deploy/PlatformCard.astro` | Reusable card: logo, name, status badge, optional star count, action button (Deploy / Docs / View). | |
| 68 | +| `src/components/deploy/StatusBadge.astro` | Pill for `official` / `available` / `planned`. | |
| 69 | +| `src/pages/deploy.astro` | **Full page**: hero/stat band → primitives strip → official spotlight → classification grids → investor depth band → CTA. SEO + JSON-LD. | |
| 70 | +| `public/logos/deploy/*.svg` | Vendored brand SVGs (local = reliable, no external image dependency). Lettermark fallback tile where no brand SVG exists. | |
| 71 | + |
| 72 | +### Edited files |
| 73 | + |
| 74 | +| File | Change | |
| 75 | +|---|---| |
| 76 | +| `src/components/Header.astro` | Add a **Deploy** link to desktop nav (`/deploy`). | |
| 77 | +| `src/components/Footer.astro` | Add a **Deploy** link under the Product (or Resources) column. | |
| 78 | +| `src/components/GetStarted.astro` | Replace the stale "One-Click Deploy" block (generic Render button + GitHub) with a concise pointer to `/deploy` ("Deploy on Railway, CapRover, Kubernetes, and more →"). Keep the Docker quick-start and clone steps as-is. | |
| 79 | +| `src/pages/index.astro` | Insert `<DeployAnywhere />` into the homepage flow, directly before `<GetStarted />` (so the "where it runs" story leads into the "how to install" steps). | |
| 80 | + |
| 81 | +## 4. Data model |
| 82 | + |
| 83 | +```ts |
| 84 | +// src/data/deploy-targets.ts |
| 85 | +export type DeployStatus = 'official' | 'available' | 'planned'; |
| 86 | +export type CategoryId = 'registry' | 'oss-paas' | 'managed-paas' | 'cloud'; |
| 87 | + |
| 88 | +export interface DeployTarget { |
| 89 | + name: string; |
| 90 | + category: CategoryId; |
| 91 | + status: DeployStatus; |
| 92 | + logo: string; // '/logos/deploy/coolify.svg' |
| 93 | + url: string; // platform marketing site |
| 94 | + deployUrl?: string; // one-click deploy link (Railway template, Koyeb button…) |
| 95 | + docsUrl?: string; // our deploy docs / repo instructions |
| 96 | + github?: string; // 'coollabsio/coolify' → live star count (OSS PaaS only) |
| 97 | + blurb?: string; // one line, e.g. "Self-hosted Heroku alternative" |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +```ts |
| 102 | +// src/data/deploy-categories.ts |
| 103 | +export interface DeployCategory { |
| 104 | + id: CategoryId; |
| 105 | + title: string; // "Open-source / self-hosted PaaS" |
| 106 | + tagline: string; // one-line description |
| 107 | + order: number; // display order on the page |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +Cards within a category sort `official → available → planned` so ready options lead. |
| 112 | + |
| 113 | +## 5. Platform inventory (authoritative content) |
| 114 | + |
| 115 | +Status legend: 🟢 `official` (listed in their marketplace) · 🟡 `available` |
| 116 | +(works today via button/manual/registry) · 🔵 `planned` (roadmap). |
| 117 | + |
| 118 | +### ① Install primitives / registries — all Available |
| 119 | + |
| 120 | +| Platform | Status | URL | |
| 121 | +|---|---|---| |
| 122 | +| GHCR image | 🟡 available | `ghcr.io/libredb/libredb-studio:latest` | |
| 123 | +| Docker Hub | 🟡 available | hub.docker.com/r/libredb/libredb-studio | |
| 124 | +| Helm chart (GHCR OCI) | 🟡 available | `ghcr.io/libredb/charts/libredb-studio` | |
| 125 | +| ArtifactHub (Helm) | 🟡 available | artifacthub.io/packages/helm/libredb-studio/libredb-studio | |
| 126 | +| npm `@libredb/studio` | 🟡 available | npmjs.com/package/@libredb/studio | |
| 127 | + |
| 128 | +### ② Open-source / self-hosted PaaS — stars shown here |
| 129 | + |
| 130 | +| Platform | Status | Stars repo | |
| 131 | +|---|---|---| |
| 132 | +| **CapRover** | 🟢 official | caprover/caprover | |
| 133 | +| Dokploy | 🔵 planned | Dokploy/dokploy | |
| 134 | +| Coolify | 🔵 planned | coollabsio/coolify | |
| 135 | +| Dokku | 🔵 planned | dokku/dokku | |
| 136 | +| Easypanel | 🔵 planned | — (closed core; lettermark, no star) | |
| 137 | +| Kubero | 🔵 planned | kubero-dev/kubero | |
| 138 | +| Kamal | 🔵 planned | basecamp/kamal | |
| 139 | +| Portainer | 🔵 planned | portainer/portainer | |
| 140 | +| Rancher | 🔵 planned | rancher/rancher | |
| 141 | +| OpenShift / OKD | 🔵 planned | okd-project/okd | |
| 142 | +| Cloudron | 🔵 planned | — (closed core; lettermark, no star) | |
| 143 | +| Cosmos | 🔵 planned | azukaar/Cosmos-Server | |
| 144 | +| Appwrite | 🔵 planned | appwrite/appwrite | |
| 145 | +| Nhost | 🔵 planned | nhost/nhost | |
| 146 | + |
| 147 | +### ③ Managed / commercial PaaS — no stars (closed platforms) |
| 148 | + |
| 149 | +| Platform | Status | |
| 150 | +|---|---| |
| 151 | +| **Railway** | 🟢 official (template marketplace; real one-click deploy URL) | |
| 152 | +| **Koyeb** | 🟡 available (deploy button live; catalog submission pending) | |
| 153 | +| Render | 🔵 planned | |
| 154 | +| Fly.io | 🔵 planned | |
| 155 | +| Netlify | 🔵 planned | |
| 156 | +| Heroku | 🔵 planned | |
| 157 | +| Northflank | 🔵 planned | |
| 158 | +| Qovery | 🔵 planned | |
| 159 | +| Platform.sh | 🔵 planned | |
| 160 | + |
| 161 | +### ④ Cloud hyperscalers — no stars |
| 162 | + |
| 163 | +AWS, GCP, Azure, DigitalOcean, Alibaba Cloud — all 🔵 planned. Framed as "runs as a |
| 164 | +container on any 'run a container' service (ECS/Fargate, Cloud Run, ACI, App Platform)." |
| 165 | + |
| 166 | +### Known deploy links (from `libredb-studio/deploy/`) |
| 167 | + |
| 168 | +- Railway template: |
| 169 | + `https://railway.com/deploy/libredb-studio?referralCode=bGijnc&utm_medium=integration&utm_source=template&utm_campaign=generic` |
| 170 | +- CapRover: install via dashboard search (official, once merged) or 3rd-party repo |
| 171 | + `https://libredb.org/caprover-one-click-apps`. Docs: repo `deploy/caprover`. |
| 172 | +- Koyeb: "Deploy to Koyeb" button (URL maintained in studio repo README). |
| 173 | + |
| 174 | +## 6. Page sections (`/deploy`) |
| 175 | + |
| 176 | +1. **Hero / big-picture band** — H1 "Deploy LibreDB Studio anywhere"; subtitle on the |
| 177 | + dual value (open-source for the world + meet teams where they deploy). **Stat strip:** |
| 178 | + `4 categories · N platforms · 5 install methods · MIT licensed`. |
| 179 | +2. **"Why it runs everywhere" primitives strip** — tiles for Docker image (GHCR), |
| 180 | + Helm chart, npm, compose — the technical reason it's portable. Each links to the |
| 181 | + relevant artifact / the existing `/docker-compose-example` page. |
| 182 | +3. **Spotlight: Official integrations** — Railway + CapRover as large cards with real |
| 183 | + one-click deploy buttons + 2-line steps. Proof it's real today. |
| 184 | +4. **Classification grids** — one block per category (①–④), responsive `PlatformCard` |
| 185 | + grid, cards sorted official→available→planned. |
| 186 | +5. **Investor depth band** — "Published across ecosystems totaling **NN k+ GitHub |
| 187 | + stars**" (sum of category ② live stars) + compact roadmap line of planned platforms. |
| 188 | +6. **CTA footer** — links to `/docker-compose-example`, GitHub repo, live demo |
| 189 | + (`app.libredb.org`). |
| 190 | + |
| 191 | +## 7. GitHub stars mechanism (build-time + client refresh) |
| 192 | + |
| 193 | +- **Build time:** `src/lib/github-stars.ts` `getStars(repos)` runs in `deploy.astro` |
| 194 | + frontmatter (Astro builds static; `fetch` runs in Node at build). One request per |
| 195 | + repo to `https://api.github.com/repos/{repo}` reading `stargazers_count`. Results |
| 196 | + baked into HTML. A hardcoded `FALLBACK_STARS` map (approximate known counts) is used |
| 197 | + for any repo whose fetch fails — the build never produces a blank or throws. |
| 198 | +- **Client refresh:** a small inline `<script>` on `/deploy` re-fetches the same repos |
| 199 | + from the GitHub API on load and updates `[data-stars-repo="owner/repo"]` spans. On |
| 200 | + any error (rate limit, offline), it silently leaves the baked number in place. |
| 201 | +- **Formatting:** counts render compact — `41200 → "41.2k"`, `980 → "980"`. |
| 202 | +- Stars render **only on category ② (OSS PaaS)** cards. |
| 203 | +- Aggregate figure in the investor band = sum of the (refreshed-or-baked) category ② |
| 204 | + counts, also recomputed client-side after refresh. |
| 205 | + |
| 206 | +## 8. Logos & assets |
| 207 | + |
| 208 | +Vendored SVGs in `public/logos/deploy/<slug>.svg`, referenced by path (static site, |
| 209 | +no CSP constraint, but local files avoid external-host fragility). Where no clean |
| 210 | +brand SVG exists (Easypanel, Cloudron, some clouds), `PlatformCard` renders a |
| 211 | +**lettermark fallback** — first initial on a branded tile — so there is never a broken |
| 212 | +image. Logo acquisition (which SVGs to vendor) is an implementation task. |
| 213 | + |
| 214 | +## 9. SEO / structured data |
| 215 | + |
| 216 | +Mirror `docker-compose-example.astro`: breadcrumb nav, page `<title>` + description, |
| 217 | +and JSON-LD — an `ItemList` enumerating deploy targets (name + url) and a reference to |
| 218 | +the existing `SoftwareApplication` (`https://libredb.org/#application`). Add `/deploy` |
| 219 | +to the sitemap automatically (handled by `@astrojs/sitemap`). |
| 220 | + |
| 221 | +## 10. Out of scope (YAGNI) |
| 222 | + |
| 223 | +- No per-platform sub-pages (one `/deploy` page covers all; deep instructions live in |
| 224 | + the studio repo `deploy/` folders and are linked). |
| 225 | +- No CMS / admin UI for the platform list — it is code-edited data. |
| 226 | +- No authenticated GitHub API token in the client (unauth is sufficient with the |
| 227 | + baked fallback). |
| 228 | +- No live status checks / uptime pings of marketplace listings. |
| 229 | + |
| 230 | +## 11. Open implementation details (decided during build, not blocking) |
| 231 | + |
| 232 | +- Exact homepage insertion point for `<DeployAnywhere />` (default: before |
| 233 | + `GetStarted`). |
| 234 | +- Final `FALLBACK_STARS` values (snapshot real counts at build of the data file). |
| 235 | +- Which brand SVGs are vendored vs lettermark fallback. |
0 commit comments