From 5b56fc16ea6c9b9059c4eb0369ac628da352f8b4 Mon Sep 17 00:00:00 2001 From: Amp Date: Tue, 15 Sep 2026 04:18:19 +0000 Subject: [PATCH] blog: BYOC post diagrams and colored hero Tightens the Rivet BYOC post into bullets, embeds the docs' BYOC architecture and multi-region diagrams, adds a data-locality/GDPR note, and points the hero at the new colored diagram (image.png?v=5). Adds scripts/render-byoc-hero.ts to the create-launch-post skill, which renders that hero and its social variant. Amp-Thread-ID: https://ampcode.com/threads/T-01a0a1ba-571f-72d8-a85e-924a49ba90b7 Co-authored-by: Nicholas Kissel --- .claude/skills/create-launch-post/SKILL.md | 1 + .../scripts/render-byoc-hero.ts | 145 ++++++++++++++++++ package.json | 1 + .../page.mdx | 47 ++++-- 4 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 .claude/skills/create-launch-post/scripts/render-byoc-hero.ts diff --git a/.claude/skills/create-launch-post/SKILL.md b/.claude/skills/create-launch-post/SKILL.md index be73d855..01d731b7 100644 --- a/.claude/skills/create-launch-post/SKILL.md +++ b/.claude/skills/create-launch-post/SKILL.md @@ -107,6 +107,7 @@ pnpm render-tile-images -- \ ``` 4. When Rivet itself is one of the tiles, pass `src/images/rivet-logos/icon-white.svg` and add `--ink-tile ` (1-based, left to right) for that position. That tile is painted as the product-mark badge — ink fill, `34.375%` radius, white ring and R filling the tile — instead of a black badge floating inside a white app tile. Never place a Rivet or product wordmark in a light tile. The badge is sized level with the smallest neighboring tile. Add `--no-wordmark` to drop the Rivet wordmark above the title when the title or a tile already carries the Rivet mark; the title and tiles shift up to stay balanced. +5. For a diagram hero instead of tiles, start from `scripts/render-byoc-hero.ts` (`pnpm render-byoc-hero -- --output-dir `): a colored, simplified architecture diagram on paper using pine, sage, ink, one accent arrow, and brand-colored provider marks. Copy and adapt it per launch rather than adding flags. 5. Inspect both PNGs. If a title wraps to a third line or a tile crowds the title, shorten the title rather than hand-editing the output. Tile geometry lives in `TILE_LAYOUTS` in the renderer; change it there if a lockup genuinely needs different placement. When short code demonstrations would help launch distribution, create a temporary JSON file outside the repository with one to four sections: diff --git a/.claude/skills/create-launch-post/scripts/render-byoc-hero.ts b/.claude/skills/create-launch-post/scripts/render-byoc-hero.ts new file mode 100644 index 00000000..443f596f --- /dev/null +++ b/.claude/skills/create-launch-post/scripts/render-byoc-hero.ts @@ -0,0 +1,145 @@ +import { mkdir, readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { chromium } from "playwright"; + +// Rivet BYOC hero: a colored, simplified hero-scale take on the docs' +// ByocArchitectureDiagram. Writes image.png (2048x1024) and social.png +// (2048x1238) plus scene.html. +// +// pnpm render-byoc-hero -- --output-dir /tmp/byoc-hero +const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url)); +const REPO = path.resolve(SCRIPT_DIR, "../../../.."); +const CARD_W = 2048; +const CARD_H = 1024; + +const INK = "#1B1916"; +const INK_SOFT = "#56524A"; +const PAPER = "#EFEFEF"; +const CREAM = "#F4F1E7"; +const PINE = "#2E4034"; +const SAGE = "#93A286"; +const ACCENT = "#CB5A33"; +const AWS_ORANGE = "#FF9900"; +const GCP_BLUE = "#4285F4"; + +const strip = (s: string) => s.replace(/<\?xml[^>]*\?>/i, "").replace(/]*>/i, ""); +const ensureViewBox = (svg: string) => { + const open = svg.match(/]*>/i)?.[0]; + if (!open || /\bviewBox=/i.test(open)) return svg; + const w = open.match(/\bwidth="([\d.]+)(px)?"/i)?.[1]; + const h = open.match(/\bheight="([\d.]+)(px)?"/i)?.[1]; + return w && h ? svg.replace(open, open.replace(/ svg.match(/\sd="([^"]+)"/)![1]; + +// The registry AWS mark is one path: four subpaths for "aws" then two for the +// smile. Split them so the smile can take the brand orange. +function awsMark(svg: string): string { + const subs = pathData(svg).split("z").filter((s) => s.trim()).map((s) => s + "z"); + const letters = subs.slice(0, 4).join(""); + // Absolute starts of the two smile subpaths, resolved from the relative moves. + const smile = + "M578.59 368.94" + subs[4].replace(/^m[\d.\- ]+/, "") + + "M607.78 335.65" + subs[5].replace(/^m[\d.\- ]+/, ""); + return ``; +} + +async function buildHtml(): Promise { + const [font, badgeRaw, awsRaw, gcpRaw] = await Promise.all([ + readFile(path.join(REPO, "public/fonts/manrope/Manrope-Variable-latin.woff2")), + readFile(path.join(REPO, "src/images/rivet-logos/icon-white.svg"), "utf8"), + readFile(path.join(REPO, "public/images/registry/deploy-aws-ecs.svg"), "utf8"), + readFile(path.join(REPO, "public/images/registry/deploy-gcp-cloud-run.svg"), "utf8"), + ]); + const badge = ensureViewBox(strip(badgeRaw)).replace(/#f0f0f0\b/gi, "#FFFFFF").replace(/#0f0f0f\b/gi, INK); + const aws = awsMark(strip(awsRaw)); + const gcp = strip(gcpRaw).replace(/fill="#1b1916"/i, `fill="${GCP_BLUE}"`); + + // Diagram geometry in card pixels. + const num = (x: number, y: number, n: number, stroke = PINE) => + ` + ${n}`; + + return `
+

Introducing Rivet BYOC

+ + + + + + + + + Your VPC + + + + Rivet Cloud + + + + Outbound only + Updates and status + + + + + Rivet operator + + Rivet control plane + + FoundationDB + Managed by Rivet + + + + + + + +
`; +} + +function parseOutputDir(argv: string[]): string { + const args = argv[0] === "--" ? argv.slice(1) : argv; + const index = args.indexOf("--output-dir"); + const value = index >= 0 ? args[index + 1] : undefined; + if (!value) throw new Error("Usage: pnpm render-byoc-hero -- --output-dir "); + return path.resolve(value); +} + +async function main() { + const OUT = parseOutputDir(process.argv.slice(2)); + await mkdir(OUT, { recursive: true }); + const html = await buildHtml(); + await writeFile(path.join(OUT, "scene.html"), html); + const browser = await chromium.launch(); + for (const target of [ + { name: "image", w: 2048, h: 1024 }, + { name: "social", w: 2048, h: 1238 }, + ]) { + const page = await browser.newPage({ viewport: { width: target.w, height: target.h }, deviceScaleFactor: 1 }); + await page.setContent(html, { waitUntil: "load" }); + await page.evaluate(() => document.fonts.ready); + await page.evaluate((h) => { + document.getElementById("stage")!.style.height = h + "px"; + document.getElementById("card")!.style.top = Math.round((h - 1024) / 2) + "px"; + }, target.h); + await page.screenshot({ path: path.join(OUT, `${target.name}.png`) }); + await page.close(); + console.log(`wrote ${target.name}.png`); + } + await browser.close(); +} +main().catch((e) => { console.error(e); process.exitCode = 1; }); diff --git a/package.json b/package.json index c17e7dc6..6a80c3e7 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "new-post": "tsx ./scripts/new-post.ts", "render-launch-images": "tsx ./.claude/skills/create-launch-post/scripts/render-launch-images.ts", "render-tile-images": "tsx ./.claude/skills/create-launch-post/scripts/render-tile-images.ts", + "render-byoc-hero": "tsx ./.claude/skills/create-launch-post/scripts/render-byoc-hero.ts", "render-technical-image": "tsx ./.claude/skills/create-launch-post/scripts/render-technical-image.ts", "gen:markdown": "tsx ./scripts/generate-markdown.ts", "gen:skills": "tsx ./scripts/generate-skills.ts", diff --git a/src/content/posts/2026-09-15-introducing-rivet-byoc/page.mdx b/src/content/posts/2026-09-15-introducing-rivet-byoc/page.mdx index ec4c88e6..61c9ec52 100644 --- a/src/content/posts/2026-09-15-introducing-rivet-byoc/page.mdx +++ b/src/content/posts/2026-09-15-introducing-rivet-byoc/page.mdx @@ -2,36 +2,59 @@ author: nicholas-kissel published: "2026-09-15" category: changelog -image: { file: "image.png?v=2" } +image: { file: "image.png?v=5" } keywords: ["byoc", "bring your own cloud", "vpc", "aws", "google cloud", "terraform", "kubernetes", "enterprise", "self-host", "rivet actors"] title: "Introducing Rivet BYOC" description: "Run the Rivet control plane inside your own AWS or Google Cloud VPC, fully managed by Rivet. Your data stays in your account and Rivet Cloud never needs inbound access." --- +import ByocArchitectureDiagram from '@/components/docs/ByocArchitectureDiagram.astro'; +import ByocRegionsDiagram from '@/components/docs/ByocRegionsDiagram.astro'; + Today we're releasing **Rivet BYOC** (Bring Your Own Cloud): the Rivet control plane deployed inside your own AWS or Google Cloud VPC and managed by Rivet. -Until now you had two options. Rivet Cloud runs everything for you, or you self-host the control plane and own the provisioning, upgrades, and on-call that come with it. BYOC sits between them. Your data and compute stay in your account. Rivet handles deployment, updates, and maintenance. +- **Rivet Cloud**: Rivet runs everything. +- **Self-host**: you run everything. +- **BYOC**: your data and compute stay in your account. Rivet handles deployment, updates, and maintenance. + +## How deployments work + + -## Your VPC, operated by Rivet +A Rivet operator runs in your Kubernetes cluster and connects outbound to Rivet Cloud. -A Rivet operator runs inside your Kubernetes cluster and connects outbound to Rivet Cloud to receive deployment instructions. It applies updates to the control plane and FoundationDB locally and reports status back. +1. Request a deployment or update +2. The operator pulls instructions from Rivet Cloud +3. The operator applies the update inside your cluster +4. The operator reports status back to Rivet Cloud - **No inbound access**: your VPC needs no inbound rules from Rivet Cloud. Your admin token stays in your cloud secret manager. -- **Public or private**: expose Rivet over HTTPS on your own hostname, or keep it reachable only from your private network. -- **Multi-region**: each region gets its own VPC, cluster, operator, and control plane. Regions share a container registry and talk over private connectivity. -- **Dashboard included**: inspect and manage your actors from the Rivet dashboard, tunneled to your deployment. +- **Public or private**: expose Rivet over HTTPS on your own hostname, or keep it on your private network. +- **Dashboard included**: manage your actors from the Rivet dashboard, tunneled to your deployment. + +## Multi-region + + + +- Each region gets its own VPC, cluster, operator, and control plane +- Data stays in the region that produced it. Pin EU users to an EU region for GDPR, or keep regulated workloads in-country. +- Regions talk over private connectivity and share a container registry +- Workers connect to their regional endpoint ## BYOC for your product too -If you build on Rivet, BYOC is also how you offer BYOC to your own customers. When a customer needs your product running inside their cloud, you create a BYOC project for them and they apply the setup kit in their AWS or Google Cloud account. Rivet brings up the control plane in their VPC and keeps it updated. You deploy your workers against it the same way you deploy against Rivet Cloud. +If you build on Rivet, BYOC is also how you offer BYOC to your own customers. -- **Same build everywhere**: the code you ship to your hosted offering is the code you ship into a customer's VPC. -- **Isolated per customer**: each deployment has its own VPC, cluster, storage, and admin token. -- **Nothing extra to operate**: Rivet handles upgrades and maintenance in every customer environment, not you. +- Create a BYOC project per customer. They apply the setup kit in their AWS or Google Cloud account. +- Rivet brings up the control plane in their VPC and keeps it updated. +- Deploy your workers against it the same way you deploy against Rivet Cloud. Same build everywhere. +- Every deployment is isolated: its own VPC, cluster, storage, and admin token. ## Availability -BYOC is available today on AWS and Google Cloud as part of [Rivet Enterprise Edition](/enterprise/), with a free 14-day trial. Create a BYOC project in the [Rivet dashboard](https://dashboard.rivet.dev) and follow the [quickstart](/cloud/byoc/quickstart). The deployment shuts down automatically when the trial ends. For air-gapped deployments, [talk to an engineer](/talk-to-an-engineer/). +- Available today on AWS and Google Cloud with [Rivet Enterprise Edition](/enterprise/) +- Free 14-day trial: create a BYOC project in the [Rivet dashboard](https://dashboard.rivet.dev) and follow the [quickstart](/cloud/byoc/quickstart). The deployment shuts down automatically when the trial ends. +- Air-gapped deployment? [Talk to an engineer](/talk-to-an-engineer/) ## Links