diff --git a/.claude/launch.json b/.claude/launch.json index 89f96814131..75e2d44c79e 100644 --- a/.claude/launch.json +++ b/.claude/launch.json @@ -7,6 +7,12 @@ "runtimeArgs": ["--filter", "docs", "exec", "next", "dev", "--port", "3105"], "port": 3105 }, + { + "name": "blog", + "runtimeExecutable": "pnpm", + "runtimeArgs": ["--filter", "blog", "exec", "next", "dev", "--port", "3002"], + "port": 3002 + }, { "name": "site", "runtimeExecutable": "pnpm", diff --git a/.claude/skills/content-create-hero-image/SKILL.md b/.claude/skills/content-create-hero-image/SKILL.md index d4a904a62d5..db15223a96f 100644 --- a/.claude/skills/content-create-hero-image/SKILL.md +++ b/.claude/skills/content-create-hero-image/SKILL.md @@ -1,16 +1,17 @@ --- name: content-create-hero-image -description: Use when the operator wants a hero or meta image for a Prisma blog post; asks to create or generate a blog hero, cover, social card, Open Graph, or YouTube image; mentions cover art, a blog thumbnail, cover.svg/hero.svg/meta.png; references content-create-hero-image; or wants to interactively design cover imagery in Prisma's Eclipse house style. Produces an editable SVG hero plus a pixel-exact PNG meta image, and includes an interactive mode and a built-in design-review pass. +description: Use when the operator wants a hero or meta image for a Prisma blog post; asks to create or generate a blog hero, cover, social card, Open Graph, or YouTube image; mentions cover art, a blog thumbnail, cover.svg/hero.svg/meta.png; references content-create-hero-image; or wants to interactively design cover imagery in Prisma's 2026 brand (light paper, prism accents, Sora). Produces an editable SVG hero plus a pixel-exact PNG meta image, and includes an interactive mode and a built-in design-review pass. metadata: author: Prisma - version: "2026.6.23" + version: "2026.8.11" --- # Create blog hero & meta images -Produce the **hero** and **meta** (Open Graph) images for a Prisma blog post in the Eclipse -house style, styled from the bundled reference assets and from the most recent posts in the -operator's checkout, then wire them into the post's frontmatter. +Produce the **hero** and **meta** (Open Graph) images for a Prisma blog post in the **2026 +brand** — light paper surfaces, the prism accent family (cyan/yellow/red), Sora display type — +styled from the bundled reference assets and from the most recent posts in the operator's +checkout, then wire them into the post's frontmatter. The hero is a hand-authored, layered **SVG** — the editable source of truth — rendered to a **pixel-exact PNG**. The meta image is **raster (PNG)** because social platforms do not render @@ -32,8 +33,8 @@ Use [`README.md`](README.md) for usage and sample prompts; this `SKILL.md` is th - [`assets/logos/`](assets/logos/) — official Prisma logo/symbol, Prisma 8 mark + lockup, Postgres/Compute icons (`README.md`). - [`assets/fonts/`](assets/fonts/) — bundled brand fonts (Mona Sans, Inter, Geist Mono); used by the scripts. - [`assets/templates/cover.svg`](assets/templates/cover.svg) — parameterized starting template. -- [`assets/examples/`](assets/examples/) — one worked hero/meta pair per house content module; the quality bar for new work. -- [`assets/hero1.svg`](assets/hero1.svg)–[`hero4.svg`](assets/hero4.svg) — abstract reference heroes in the house style; study for palette, type, and motif alongside the worked examples. +- [`assets/examples/`](assets/examples/) — worked hero/meta pairs per content module. **Pre-rebrand (dark Eclipse era): study for composition and module structure ONLY — their palette, fonts, and surfaces are retired.** The current quality bar is the newest committed covers in `apps/blog/public/*/imgs/`. +- [`assets/hero1.svg`](assets/hero1.svg)–[`hero4.svg`](assets/hero4.svg) — abstract reference heroes, also pre-rebrand; same structure-only caveat. - [`scripts/embed-fonts.py`](scripts/embed-fonts.py) — inline the brand fonts into the SVG as base64 `@font-face`. **Run first.** - [`scripts/export-png.sh`](scripts/export-png.sh) — render the font-embedded SVG to PNG via headless Chrome so the PNG matches the SVG in a browser exactly. **Run second.** @@ -42,6 +43,25 @@ Use [`README.md`](README.md) for usage and sample prompts; this `SKILL.md` is th Two images: a `hero` shown on the post itself, and a `meta` image for Open Graph and social cards. A single design may serve both files. +**Contexts of use — design for all three.** A cover lives as (1) a **grid thumbnail** in the +blog index, cropped to ~16:9 by `object-cover` and rendered ~400px wide **directly beside the +post's real title**, on light AND dark card surfaces; (2) the full-size social/OG card; (3) the +in-post hero. The thumbnail-next-to-title context drives the hardest rules: + +- **Headline**: a compressed thesis of ≤6 words, or no copy at all — never a restatement of the + post title it will sit beside. Across a batch, vary composition (no-copy graphic-led, + corner-stripe brand moment, headline+module) so adjacent covers don't read as one template. +- **Kicker**: ≥20px with a ≥5.5px dot, or omit it — a 17px kicker is noise at thumbnail scale. +- **Sign-off**: prefer the **full-color lockup** (`assets/logos/prisma-lockup-color.svg`, + ~112px wide, inlined as a group) over the plain-text wordmark; the mark carries at thumbnail + scale where small grey type disappears. +- **Crop-safe zone**: every critical element (lockup, kicker, headline, module edges) stays + ≥72px from every canvas edge and must survive a centered 16:9 crop of the 1200×630 frame. +- **Dual-surface**: the artwork never theme-switches; it must read as an intentional object on + both white and ink (#1a1a1a) surrounds. Avoid vast empty pure-white regions — washes on + covers run a step stronger than page washes (~0.18–0.28 per stop) so the piece carries color + at small sizes and on dark. + 1. **Format.** - **hero: SVG by default** — the prisma.io/blog standard, and it suits the typographic, geometric heroes the blog favours. The SVG is the editable source of truth; always export @@ -57,10 +77,14 @@ cards. A single design may serve both files. - Other canvases (in-post hero `844×474`, YouTube `1280×720`, custom) are produced on request — change `width`/`height`/`viewBox` and scale font sizes proportionally (≈ ×0.70 for the 844-wide hero). -3. **Size budget.** Keep the meta PNG **under 1 MB** (1x normally lands ~200–500 KB; re-export - at 1x if a denser export overshoots). Keep the SVG lean: **subset, embedded fonts** (see step - 6) land each hero around ~20–30 KB. Prefer vector paths over embedded raster; flag any SVG - over ~1 MB. +3. **Size budget.** Keep the meta PNG **under 1 MB**. A 1x export normally lands ~200–500 KB; + a cover whose art is mostly smooth wash gradients can overshoot (one landed at 1.4 MB), so + check the file and re-export at 1x, or flatten a redundant wash layer, if it does. Keep the + SVG lean with **subset, embedded fonts** (step 6): a typographic cover lands ~30–55 KB, and + a code/terminal-heavy one ~55–75 KB because the mono glyph subset is larger. Above ~120 KB, + check that fonts actually subset (the venv python needs `fonttools` + `brotli`; without them + `embed-fonts.py` silently falls back to embedding whole WOFF2 files). Prefer vector paths + over embedded raster; flag any SVG over ~1 MB. 4. **Naming.** Base names `hero` and `meta`, extension following the format: `hero.svg` (or `hero.png` when raster) and `meta.png`. **No content hashes, no dimensions** in filenames. For N explored directions, suffix the base name (`hero-a.svg`/`meta-a.png`, …). @@ -141,8 +165,8 @@ the Workflow'"_. | 3 | **Custom copy** (if text) | quote the post's own thesis as the suggestion | the post's thesis verbatim; blank = no text | | 4 | **What should the graphic symbolise?** | restate the post's core idea in concrete terms | the literal mechanism from the post | | 5 | **Isometric skew on the graphic?** | "Default yes for card/table modules; flow/loop diagrams usually read best **flat**." | yes for cards/tables, flat for flows | -| 6 | **Background family** | name the product's surface | teal (Postgres/Compute/Next/platform); indigo only for ORM | -| 7 | **Mood** | launch / educational / conceptual / editorial / technical | educational, dark | +| 6 | **Accent color** | name the owning product | cyan (ORM / Prisma 8 / platform); yellow (Postgres); red (Compute) | +| 7 | **Mood** | launch / educational / conceptual / editorial / technical | educational, light paper | | 8 | **Product logo** | which mark, if any | the post's product mark when it clarifies; else just the `Prisma` wordmark | | 9 | **How many directions to explore?** | 1–4 distinct concepts | 1 (offer up to 4) | @@ -154,8 +178,8 @@ obeys the anti-patterns and the design-review bar — creative ≠ slop. ### 3. Choose a visual direction -Decide a concept that's literal-but-elegant, never generic. Pick: surface (dark default / light -editorial), product accent, eyebrow label, the **content module** that fits the content (see +Decide a concept that's literal-but-elegant, never generic. Pick: surface (light paper default / +ink dark only with a stated reason), product accent, kicker label, the **content module** that fits the content (see `design-system.md` → _Content modules_: pipeline/flow, data/log panel, terminal, code card, comparison card), and whether a product lockup belongs in the composition. Anchor every choice in `design-system.md`. One accent, one idea, strong hierarchy, generous space. @@ -185,9 +209,10 @@ the message (e.g. a chart) — keep the layer groups (`background`, `badge`, `he chars). Set the eyebrow/badge pill width to roughly `(label length × 14) + 48`. Include the ``/`<desc>` metadata. -**Fonts (avoid the #1 off-brand bug):** the brand faces are **Mona Sans** (headings/display, 800), -**Inter** (body, 400), and **Geist Mono** (data/code, 500), bundled in `assets/fonts/`. Do **not** -use Barlow — it is the legacy docs face and reads off-brand. A wrong family/weight falls back to a +**Fonts (avoid the #1 off-brand bug):** the brand faces are **Sora** (headings/display, weight +500, emphasis 600 — never 700+), **Inter** (body 400, kicker labels 600), and **Mona Sans Mono** +(data/code, 500), bundled in `assets/fonts/`. Do **not** use Mona Sans display, Geist Mono, or +Barlow — those are the retired pre-rebrand faces. A wrong family/weight falls back to a generic sans. For emphasis, change colour or size, **not** weight. When the graphic _is_ the message, let it own the canvas — center it, drop competing chrome, use the standalone product logo as the brand mark, and label data with real numbers. @@ -208,8 +233,14 @@ Tie any header number to the data it labels, and highlight the "live"/current el - **Whitespace between `<tspan>`s is stripped.** With the default `xml:space`, librsvg trims whitespace on each `tspan`, so `export default` + `<tspan> defineComputeConfig` renders as `export defaultdefineComputeConfig`. For any multi-`tspan` line that needs internal spaces (code - snippets especially), put **`xml:space="preserve"`** on the parent `<text>`/`<g>`, and keep the + snippets especially), put **`xml:space="preserve"` on each `<text>` element itself**, and keep the text content on a single source line so `preserve` doesn't pull in indentation. + **Put it on the `<text>`, never only on a wrapping `<g>`:** Chrome does not inherit + `xml:space` from a group, so a `<g xml:space="preserve">` around code `<text>` nodes **fails + silently** — the SVG looks right in source and every leading space and column alignment + vanishes in the exported PNG. This is the single most expensive gotcha in the pipeline because + nothing errors; it is only visible by opening the raster. Grep your finished SVG for + `<g[^>]*xml:space` and move any hit down onto the individual `<text>` elements. - **Long words don't wrap.** SVG `<text>` has no auto-wrap — hand-split into `<tspan>` lines with explicit `x`/`dy`. - **Centering: avoid `text-anchor="middle"` + `dx`.** For a bold-name + quiet-label pair (e.g. @@ -226,7 +257,7 @@ python3 scripts/embed-fonts.py <hero.svg> # 1. inline b bash scripts/export-png.sh <hero.svg> <meta.png> 1200 630 # 2. render PNG (Chrome) ``` -`embed-fonts.py` inlines Mona Sans/Inter/Geist Mono as base64 `@font-face` — subsetting to the +`embed-fonts.py` inlines Sora/Inter/Mona Sans Mono as base64 `@font-face` — subsetting to the glyphs the SVG uses (with `fonttools` + `brotli`, ~20–30 KB) or embedding the whole WOFF2 when those are unavailable (larger, still self-contained). `export-png.sh` renders with **headless Chrome/Chromium**, which honors `@font-face`, so the PNG looks exactly like the SVG in a @@ -281,8 +312,9 @@ product, why the metaphor fits). Example: ```text hero: apps/blog/public/query-insights-ga/imgs/hero.svg meta: apps/blog/public/query-insights-ga/imgs/meta.png -Direction: Dark Eclipse surface with the Postgres teal accent; Query Insights framed as a GA -launch via the pill eyebrow; restraint keeps it premium and thumbnail-legible. +Direction: Paper surface with a bottom spectral wash and the Postgres yellow accent; Query +Insights framed as a GA launch via the kicker dot; one white metric card carries the idea and +restraint keeps it premium and thumbnail-legible. ``` ## Validation — must pass before finalizing @@ -293,9 +325,11 @@ Visually inspect the rendered PNG, then verify: preserved). SVG declares `viewBox="0 0 1200 630"` with matching `width`/`height`. - [ ] The meta image is **PNG**; the hero is **SVG** (raster hero only on an explicit photographic request). Each asset is self-contained — the SVG resolves with no external references. -- [ ] Colors and gradient match `tokens.json` exactly — no off-system values. -- [ ] Fonts render in real Mona Sans/Inter/Geist Mono (not a fallback sans, and **not Barlow**); - heed the export warning. The committed SVG has embedded `@font-face` (ran `embed-fonts.py`). +- [ ] Colors match `tokens.json` exactly — no off-system values, and **no retired dark-aurora + teal/navy surfaces**. The surface is light paper unless a dark cover was explicitly chosen. +- [ ] Fonts render in real Sora/Inter/Mona Sans Mono (not a fallback sans; **not Mona Sans + display, Geist Mono, or Barlow** — all retired); heed the export warning. The committed SVG + has embedded `@font-face` (ran `embed-fonts.py`). Headlines are Sora **500**, sentence case. - [ ] One accent, one idea. Clear hierarchy; generous negative space. If a graphic is the message, it is centered and uncluttered. - [ ] Diagram cards sit ≥ 48px off the canvas edge; arrows are full-length; no node is jammed @@ -303,6 +337,11 @@ Visually inspect the rendered PNG, then verify: - [ ] Code/snippet text renders its spaces correctly (multi-`tspan` lines carry `xml:space="preserve"`). - [ ] Title text is legible as a small thumbnail **and** at full 1200px social-preview size. +- [ ] The cover reads as intentional artwork on BOTH white and ink (#1a1a1a) surrounds (render + the PNG onto each and look); no vast empty pure-white regions; critical elements are ≥72px + from every edge and survive a centered 16:9 crop. +- [ ] The headline (if any) is ≤6 words and does not restate the post title; the kicker (if any) + is ≥20px; the sign-off is the full-color lockup unless there's a reason for text. - [ ] Any logo/lockup is intentional, correctly colored, not stretched, and not paired with extra label text. The `Prisma` wordmark, if used, sits bottom-left with no mark beside it. - [ ] Any data/chart uses real numbers and the framing the prompt asked for. @@ -322,13 +361,17 @@ creative and brand traps a checklist can't catch.) filenames, and frontmatter fields from recent posts; the documented standard is a fallback. - **Generic AI look.** Glows everywhere, faux-3D blobs, busy gradients, literal robots. Prisma covers are restrained and typographic. When in doubt, remove an element. -- **Off-system styling.** Inventing colors, or swapping the Mona Sans + Inter pairing (Barlow is - off-brand). +- **Off-system styling.** Inventing colors, or swapping the Sora + Inter pairing (Mona Sans + display, Geist Mono, and Barlow are all retired/off-brand). +- **Reaching for the retired look.** The dark teal aurora surface, Mona Sans 800 headlines, + uppercase dash eyebrows, and glow-heavy cards are the pre-2026 style — old committed covers and + `assets/examples/` show it; do not reproduce their skin. - **Decorative logos.** Marks are a footer sign-off or the subject — never wallpaper. - **Centering text-only layouts.** Default covers are left-anchored with right-side breathing room. Center only a single graphic-led composition. -- **Fabricating product palettes.** Postgres = teal, ORM = indigo. Compute/Next have no official - tokens yet — use the platform teal and say so; don't invent a brand color. +- **Fabricating product palettes.** ORM / Prisma 8 = prism cyan, Postgres = prism yellow, + Compute = prism red (see `tokens.json → products`). One accent per cover; don't invent hues or + revive the old teal/indigo mapping. - **Tagline filler.** Avoid lines like `Resize. Encode. Cache.` If a secondary line is needed, make it concrete and informational. - **Copying a single reference.** Synthesise the house style from across the examples and recent diff --git a/.claude/skills/content-create-hero-image/assets/fonts/Inter-VF.woff2 b/.claude/skills/content-create-hero-image/assets/fonts/Inter-VF.woff2 new file mode 100644 index 00000000000..5a8d3e72ad7 Binary files /dev/null and b/.claude/skills/content-create-hero-image/assets/fonts/Inter-VF.woff2 differ diff --git a/.claude/skills/content-create-hero-image/assets/fonts/MonaSansMono-VF.woff2 b/.claude/skills/content-create-hero-image/assets/fonts/MonaSansMono-VF.woff2 new file mode 100644 index 00000000000..f4ccd616f12 Binary files /dev/null and b/.claude/skills/content-create-hero-image/assets/fonts/MonaSansMono-VF.woff2 differ diff --git a/.claude/skills/content-create-hero-image/assets/fonts/README.md b/.claude/skills/content-create-hero-image/assets/fonts/README.md index d200a6db7c8..88911f0854d 100644 --- a/.claude/skills/content-create-hero-image/assets/fonts/README.md +++ b/.claude/skills/content-create-hero-image/assets/fonts/README.md @@ -1,16 +1,24 @@ # Brand fonts -Static instances of the Eclipse brand fonts, bundled so covers render on-brand without a -`prisma/web` checkout. `scripts/export-png.sh` points fontconfig here automatically, and -`scripts/embed-fonts.py` subsets these into committed SVGs. +The 2026-brand faces, bundled so covers render on-brand without a `prisma/web` checkout. +`scripts/export-png.sh` points fontconfig here automatically, and `scripts/embed-fonts.py` +subsets these into committed SVGs. -| File | Family | Weight | Role | License | -| --------------------- | ---------- | ------ | ------------------------------------------------ | ------------------------------ | -| `MonaSans.woff2` | Mona Sans | 800 | Headings, display, product wordmark, big numbers | SIL OFL 1.1 (GitHub Mona Sans) | -| `Inter-Regular.woff2` | Inter | 400 | Body, subtitles, UI/category labels | SIL OFL 1.1 | -| `GeistMono.woff2` | Geist Mono | 500 | Data values, code, technical labels | SIL OFL 1.1 (Vercel Geist) | +## Current brand (use these) -`MonaSans.woff2` is a static instance (weight 800, extended width) cut from Mona Sans VF -(`prisma/web` → `packages/eclipse/src/static/fonts/MonaSansVF[wdth,wght,opsz,ital].woff2`). -To regenerate at a different weight/width, instance the VF with `fonttools` and rename the -family to `Mona Sans`. All three families are open-source (OFL) and safe to redistribute. +| File | Family | Weights used | Role | License | +| ----------------------- | -------------- | ------------ | ------------------------------------------- | ----------- | +| `Sora-VF.woff2` | Sora | 500, 600 | Headlines, big numbers, `Prisma` wordmark | SIL OFL 1.1 | +| `Inter-VF.woff2` | Inter | 400, 600 | Body, subtitles, kicker labels | SIL OFL 1.1 | +| `MonaSansMono-VF.woff2` | Mona Sans Mono | 500 | Code, data values, paths | SIL OFL 1.1 | + +All three are variable fonts copied from `prisma/web` → +`packages/eclipse/src/static/fonts/` (`SoraVF-latin.woff2`, `InterVariable.woff2`, +`MonaSansMonoVF[wght].woff2`). One `@font-face` with a weight range serves every weight. + +## Legacy (pre-rebrand — keep only to re-render old covers) + +`MonaSans.woff2` (Mona Sans 800 display), `Inter-Regular.woff2` (static Inter 400), and +`GeistMono.woff2` are the retired Eclipse-era faces. Do not use them on new covers. + +All families are open-source (OFL) and safe to redistribute. diff --git a/.claude/skills/content-create-hero-image/assets/fonts/Sora-VF.woff2 b/.claude/skills/content-create-hero-image/assets/fonts/Sora-VF.woff2 new file mode 100644 index 00000000000..6a4dd1072aa Binary files /dev/null and b/.claude/skills/content-create-hero-image/assets/fonts/Sora-VF.woff2 differ diff --git a/.claude/skills/content-create-hero-image/assets/logos/README.md b/.claude/skills/content-create-hero-image/assets/logos/README.md index 0837ca9c229..65a79ef5498 100644 --- a/.claude/skills/content-create-hero-image/assets/logos/README.md +++ b/.claude/skills/content-create-hero-image/assets/logos/README.md @@ -2,35 +2,31 @@ Official, reusable brand marks for covers. Prefer these over re-extracting each time. -## Sources - -- **Prisma logo + symbol** — official press kit [`prisma/presskit`](https://github.com/prisma/presskit). -- **Prisma 8 mark** — the layered-prism brand mark, vectorized to white/dark. -- **Prisma Postgres icon** — FontAwesome [`chart-pyramid`](https://fontawesome.com/icons/chart-pyramid) (solid). -- **Prisma Compute icon** — FontAwesome [`microchip`](https://fontawesome.com/icons/microchip) (solid). - -## Inventory - -| File | What | Use | -| ---------------------------- | --------------------------------------------- | ------------------------------ | -| `prisma-logo-white.svg` | Official Prisma logo (mark + wordmark), white | Brand sign-off on dark covers | -| `prisma-logo-dark.svg` | Official Prisma logo, dark | Brand sign-off on light covers | -| `prisma-logo-indigo.svg` | Official Prisma logo, brand indigo | Indigo-on-light contexts | -| `prisma-symbol-white.svg` | Prisma prism symbol, white | Brand mark, dark covers | -| `prisma-symbol-indigo.svg` | Prisma prism symbol, indigo | Brand mark, light contexts | -| `prisma-8-mark-white.svg` | Prisma 8 layered-prism mark, white | Prisma 8 mark on dark | -| `prisma-8-mark-dark.svg` | Prisma 8 mark, dark | Prisma 8 mark on light | -| `prisma-8-logo.svg` | Prisma 8 mark + "Prisma 8" (Mona Sans) | Prisma 8 lockup | -| `prisma-postgres-icon.svg` | Chart-pyramid, teal `#71e8df` | Prisma Postgres covers | -| `prisma-compute-icon.svg` | Microchip, teal `#71e8df` | Prisma Compute covers | +## Current brand (2026 — use these) + +| File | What | Use | +| -------------------------- | ----------------------------------------------------------------- | -------------------------------------------------- | +| `prisma-lockup-color.svg` | Full-color lockup: prism-stripe mark + ink wordmark (304×77) | Brand sign-off on light covers (~110px wide) | +| `prisma-lockup-white.svg` | Full-color mark + white wordmark | Brand sign-off on the rare dark cover | +| `prisma-mark-prism.svg` | The square prism mark alone (45° cyan/red/yellow stripes, 76×76) | Standalone brand mark; favicon-style corner glyph | + +Sourced from `prisma/web` → `apps/blog/public/logo/` and the marketing site app's icon. These +carry the prism colors (`#01d7e4` cyan, red `#f34a60` family, yellow `#f3c306` family) — never +recolor, stretch, or add effects. The plain-text alternative sign-off is the word `Prisma` set +in Sora 600 ink (no mark beside it). + +## Legacy (pre-rebrand — do not use on new covers) + +`prisma-logo-white/dark/indigo.svg` and `prisma-symbol-white/indigo.svg` are the old +triangle-logo era marks. `prisma-8-mark-*.svg` / `prisma-8-logo.svg` are the interim Prisma 8 +launch marks (Mona Sans lockup). `prisma-postgres-icon.svg` / `prisma-compute-icon.svg` are the +old teal FontAwesome product chips. Kept only so legacy covers can be re-rendered faithfully. ## Rules -- **Intentional, not decorative.** One brand mark per cover. Product icons/lockups are for - product-focused covers where the product is the subject. -- Use the official `prisma-logo-*` / `prisma-symbol-*` and the Prisma 8 mark as-is — do not - recolor (beyond the white/dark variants), stretch, rotate, or add effects. -- Product accents: Postgres = teal `#71e8df`, Compute = teal, Prisma 8 pairs the white mark with - a Mona Sans wordmark, ORM = indigo `#4f46e5`. -- The lockup uses live Mona Sans text; render/commit it with the brand fonts embedded - (`scripts/embed-fonts.py`) so it stays correct standalone. +- **Intentional, not decorative.** One brand mark per cover — the lockup as sign-off or the + prism mark as a deliberate subject; never wallpaper. +- Product accents on the new brand: ORM / Prisma 8 = prism cyan `#01d7e4`, Postgres = prism + yellow `#eaa700`/`#f3c306`, Compute = prism red `#f34a60`. There are no per-product icons in + the new system — the kicker dot in the product's accent does that work. +- Never pair a mark with extra "Prisma" text, and never place `prisma.io/blog` on the canvas. diff --git a/.claude/skills/content-create-hero-image/assets/logos/prisma-lockup-color.svg b/.claude/skills/content-create-hero-image/assets/logos/prisma-lockup-color.svg new file mode 100644 index 00000000000..19c4f1c037a --- /dev/null +++ b/.claude/skills/content-create-hero-image/assets/logos/prisma-lockup-color.svg @@ -0,0 +1,20 @@ +<svg width="264" height="67" viewBox="0 0 264 67" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M264 23.2767V52.6881H257.428V48.7257C256.351 50.1767 254.996 51.3115 253.362 52.13C251.728 52.9486 249.853 53.3578 247.737 53.3578C245.62 53.3578 243.671 52.9672 241.888 52.1858C240.143 51.4045 238.621 50.3441 237.321 49.0047C236.021 47.6281 235 46.0096 234.258 44.1493C233.552 42.2518 233.199 40.2055 233.199 38.0103C233.199 35.8152 233.552 33.806 234.258 31.9829C235 30.1226 236.021 28.5414 237.321 27.2392C238.621 25.8997 240.143 24.8766 241.888 24.1696C243.671 23.4255 245.62 23.0535 247.737 23.0535C249.853 23.0535 251.728 23.4441 253.362 24.2255C254.996 24.9696 256.351 26.0486 257.428 27.4624V23.2767H264ZM248.683 47.1072C249.946 47.1072 251.097 46.884 252.137 46.4375C253.176 45.991 254.067 45.3771 254.81 44.5958C255.59 43.7773 256.184 42.8099 256.592 41.6937C257.001 40.5775 257.205 39.3497 257.205 38.0103C257.205 35.2943 256.425 33.0991 254.866 31.4248C253.306 29.7506 251.245 28.9134 248.683 28.9134C247.458 28.9134 246.325 29.1367 245.286 29.5831C244.283 30.0296 243.411 30.6621 242.668 31.4806C241.925 32.2992 241.331 33.2665 240.886 34.3827C240.477 35.4989 240.273 36.7081 240.273 38.0103C240.273 39.3125 240.477 40.5217 240.886 41.6379C241.331 42.7541 241.925 43.7214 242.668 44.54C243.411 45.3213 244.283 45.9538 245.286 46.4375C246.325 46.884 247.458 47.1072 248.683 47.1072Z" fill="black"/> +<path d="M217.188 22.6069C219.007 22.6069 220.622 22.9232 222.033 23.5557C223.444 24.151 224.614 24.9881 225.542 26.0671C226.508 27.1089 227.232 28.3553 227.715 29.8063C228.197 31.2201 228.439 32.7642 228.439 34.4385V52.6322H221.365V35.7221C221.365 33.8246 220.845 32.2247 219.806 30.9225C218.803 29.5831 217.299 28.9134 215.294 28.9134C214.291 28.9134 213.4 29.0994 212.621 29.4715C211.841 29.8435 211.172 30.3086 210.615 30.8667C210.096 31.4248 209.687 32.0573 209.39 32.7642C209.13 33.4711 209 34.1594 209 34.8291V52.6322H201.927V35.7221C201.927 33.7874 201.407 32.1689 200.367 30.8667C199.327 29.5645 197.805 28.9134 195.8 28.9134C194.797 28.9134 193.906 29.0994 193.126 29.4715C192.347 29.8435 191.697 30.3086 191.177 30.8667C190.657 31.4248 190.249 32.0573 189.952 32.7642C189.655 33.4339 189.506 34.1222 189.506 34.8291V52.6322H182.433V23.2766H189.116V26.5136C190.045 25.3974 191.251 24.4672 192.737 23.7231C194.222 22.979 195.967 22.6069 197.972 22.6069C200.311 22.6069 202.224 23.0162 203.709 23.8347C205.231 24.6533 206.42 25.8439 207.274 27.4065C208.09 26.0299 209.316 24.8951 210.95 24.0022C212.621 23.072 214.7 22.6069 217.188 22.6069Z" fill="black"/> +<path d="M165.542 53.3578C162.349 53.3578 159.656 52.7253 157.466 51.4602C155.275 50.1952 153.771 48.3163 152.954 45.8235L159.137 43.4237C159.545 44.8004 160.306 45.8793 161.42 46.6607C162.571 47.4048 164.038 47.7768 165.82 47.7768C167.231 47.7768 168.345 47.4978 169.162 46.9397C170.016 46.3816 170.443 45.5817 170.443 44.5399C170.443 43.5726 170.035 42.8098 169.218 42.2517C168.438 41.6937 167.454 41.21 166.266 40.8007C165.078 40.3542 163.778 39.9264 162.367 39.5171C160.993 39.1078 159.712 38.5869 158.524 37.9544C157.336 37.2847 156.333 36.429 155.516 35.3872C154.737 34.3455 154.347 32.9874 154.347 31.3132C154.347 28.6343 155.368 26.5136 157.41 24.9509C159.452 23.3883 162.219 22.6069 165.709 22.6069C168.568 22.6069 170.963 23.165 172.894 24.2812C174.825 25.3974 176.106 26.96 176.737 28.9692L170.555 31.369C169.775 29.1738 168.122 28.0762 165.598 28.0762C164.298 28.0762 163.295 28.3367 162.59 28.8576C161.922 29.3784 161.587 30.0854 161.587 30.9783C161.587 31.8712 161.977 32.5782 162.757 33.099C163.574 33.5827 164.576 34.0106 165.765 34.3827C166.953 34.7175 168.234 35.0896 169.608 35.4988C171.019 35.8709 172.318 36.3918 173.507 37.0615C174.695 37.7312 175.679 38.6242 176.459 39.7403C177.275 40.8193 177.684 42.2517 177.684 44.0376C177.684 46.9769 176.57 49.2651 174.342 50.9022C172.151 52.5392 169.218 53.3578 165.542 53.3578Z" fill="black"/> +<path d="M145.094 18.5886C143.72 18.5886 142.569 18.1608 141.641 17.305C140.713 16.4121 140.249 15.2773 140.249 13.9007C140.249 12.524 140.713 11.3892 141.641 10.4963C142.569 9.56615 143.72 9.10107 145.094 9.10107C146.468 9.10107 147.619 9.56615 148.548 10.4963C149.476 11.3892 149.94 12.524 149.94 13.9007C149.94 15.2773 149.476 16.4121 148.548 17.305C147.619 18.1608 146.468 18.5886 145.094 18.5886ZM141.53 23.2766H148.603V52.688H141.53V23.2766Z" fill="black"/> +<path d="M128.687 26.5694C129.689 25.3788 130.933 24.43 132.418 23.7231C133.904 22.979 135.575 22.6069 137.431 22.6069V29.2482C134.869 29.2482 132.827 29.8621 131.304 31.0899C129.819 32.3177 129.077 33.9362 129.077 35.9453V52.6881H122.003V23.2766H128.687V26.5694Z" fill="black"/> +<path d="M104.318 13.9006C106.36 13.9006 108.198 14.1797 109.832 14.7378C111.466 15.2959 112.858 16.0958 114.01 17.1376C115.161 18.1793 116.033 19.4443 116.627 20.9326C117.259 22.3836 117.574 24.0021 117.574 25.788C117.574 27.6111 117.259 29.2667 116.627 30.755C115.996 32.206 115.105 33.4524 113.954 34.4942C112.803 35.536 111.41 36.3359 109.776 36.894C108.143 37.4521 106.323 37.7311 104.318 37.7311H96.1306V52.688H89.0013V13.9006H104.318ZM103.984 31.4805C106.1 31.4805 107.679 30.9596 108.718 29.9179C109.795 28.8389 110.333 27.4623 110.333 25.788C110.333 24.1137 109.795 22.7557 108.718 21.7139C107.679 20.6721 106.1 20.1513 103.984 20.1513H96.1306V31.4805H103.984Z" fill="black"/> +<g clip-path="url(#clip0_2_116)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5772 23.4756L0 38.0528V38.076L14.5772 23.4756Z" fill="#04D5E7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M66.8662 28.8965V28.9405L39.7771 56.0295L66.8662 28.8965Z" fill="#FEBE29"/> +<path d="M14.5772 23.4755L0 38.0527V13.5776L13.5284 0.0264573V0H38.0154L14.5772 23.4755Z" fill="#04D5E7"/> +<path d="M66.866 23.2838L23.1498 67H0V43.7095L43.7095 0H66.866V23.2838Z" fill="#FE4352"/> +<path d="M53.3113 67H28.8244L39.7771 56.0295L66.8662 28.9404V53.4224L53.3113 67Z" fill="#FEBE29"/> +</g> +<defs> +<clipPath id="clip0_2_116"> +<rect width="66.866" height="67" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/.claude/skills/content-create-hero-image/assets/logos/prisma-lockup-white.svg b/.claude/skills/content-create-hero-image/assets/logos/prisma-lockup-white.svg new file mode 100644 index 00000000000..19e803de053 --- /dev/null +++ b/.claude/skills/content-create-hero-image/assets/logos/prisma-lockup-white.svg @@ -0,0 +1,20 @@ +<svg width="264" height="67" viewBox="0 0 264 67" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M264 23.2767V52.6881H257.428V48.7257C256.351 50.1767 254.996 51.3115 253.362 52.13C251.728 52.9486 249.853 53.3578 247.737 53.3578C245.62 53.3578 243.671 52.9672 241.888 52.1858C240.143 51.4045 238.621 50.3441 237.321 49.0047C236.021 47.6281 235 46.0096 234.258 44.1493C233.552 42.2518 233.199 40.2055 233.199 38.0103C233.199 35.8152 233.552 33.806 234.258 31.9829C235 30.1226 236.021 28.5414 237.321 27.2392C238.621 25.8997 240.143 24.8766 241.888 24.1696C243.671 23.4255 245.62 23.0535 247.737 23.0535C249.853 23.0535 251.728 23.4441 253.362 24.2255C254.996 24.9696 256.351 26.0486 257.428 27.4624V23.2767H264ZM248.683 47.1072C249.946 47.1072 251.097 46.884 252.137 46.4375C253.176 45.991 254.067 45.3771 254.81 44.5958C255.59 43.7773 256.184 42.8099 256.592 41.6937C257.001 40.5775 257.205 39.3497 257.205 38.0103C257.205 35.2943 256.425 33.0991 254.866 31.4248C253.306 29.7506 251.245 28.9134 248.683 28.9134C247.458 28.9134 246.325 29.1367 245.286 29.5831C244.283 30.0296 243.411 30.6621 242.668 31.4806C241.925 32.2992 241.331 33.2665 240.886 34.3827C240.477 35.4989 240.273 36.7081 240.273 38.0103C240.273 39.3125 240.477 40.5217 240.886 41.6379C241.331 42.7541 241.925 43.7214 242.668 44.54C243.411 45.3213 244.283 45.9538 245.286 46.4375C246.325 46.884 247.458 47.1072 248.683 47.1072Z" fill="white"/> +<path d="M217.188 22.6069C219.007 22.6069 220.622 22.9232 222.033 23.5557C223.444 24.151 224.614 24.9881 225.542 26.0671C226.508 27.1089 227.232 28.3553 227.715 29.8063C228.197 31.2201 228.439 32.7642 228.439 34.4385V52.6322H221.365V35.7221C221.365 33.8246 220.845 32.2247 219.806 30.9225C218.803 29.5831 217.299 28.9134 215.294 28.9134C214.291 28.9134 213.4 29.0994 212.621 29.4715C211.841 29.8435 211.172 30.3086 210.615 30.8667C210.096 31.4248 209.687 32.0573 209.39 32.7642C209.13 33.4711 209 34.1594 209 34.8291V52.6322H201.927V35.7221C201.927 33.7874 201.407 32.1689 200.367 30.8667C199.327 29.5645 197.805 28.9134 195.8 28.9134C194.797 28.9134 193.906 29.0994 193.126 29.4715C192.347 29.8435 191.697 30.3086 191.177 30.8667C190.657 31.4248 190.249 32.0573 189.952 32.7642C189.655 33.4339 189.506 34.1222 189.506 34.8291V52.6322H182.433V23.2766H189.116V26.5136C190.045 25.3974 191.251 24.4672 192.737 23.7231C194.222 22.979 195.967 22.6069 197.972 22.6069C200.311 22.6069 202.224 23.0162 203.709 23.8347C205.231 24.6533 206.42 25.8439 207.274 27.4065C208.09 26.0299 209.316 24.8951 210.95 24.0022C212.621 23.072 214.7 22.6069 217.188 22.6069Z" fill="white"/> +<path d="M165.542 53.3578C162.349 53.3578 159.656 52.7253 157.466 51.4602C155.275 50.1952 153.771 48.3163 152.954 45.8235L159.137 43.4237C159.545 44.8004 160.306 45.8793 161.42 46.6607C162.571 47.4048 164.038 47.7768 165.82 47.7768C167.231 47.7768 168.345 47.4978 169.162 46.9397C170.016 46.3816 170.443 45.5817 170.443 44.5399C170.443 43.5726 170.035 42.8098 169.218 42.2517C168.438 41.6937 167.454 41.21 166.266 40.8007C165.078 40.3542 163.778 39.9264 162.367 39.5171C160.993 39.1078 159.712 38.5869 158.524 37.9544C157.336 37.2847 156.333 36.429 155.516 35.3872C154.737 34.3455 154.347 32.9874 154.347 31.3132C154.347 28.6343 155.368 26.5136 157.41 24.9509C159.452 23.3883 162.219 22.6069 165.709 22.6069C168.568 22.6069 170.963 23.165 172.894 24.2812C174.825 25.3974 176.106 26.96 176.737 28.9692L170.555 31.369C169.775 29.1738 168.122 28.0762 165.598 28.0762C164.298 28.0762 163.295 28.3367 162.59 28.8576C161.922 29.3784 161.587 30.0854 161.587 30.9783C161.587 31.8712 161.977 32.5782 162.757 33.099C163.574 33.5827 164.576 34.0106 165.765 34.3827C166.953 34.7175 168.234 35.0896 169.608 35.4988C171.019 35.8709 172.318 36.3918 173.507 37.0615C174.695 37.7312 175.679 38.6242 176.459 39.7403C177.275 40.8193 177.684 42.2517 177.684 44.0376C177.684 46.9769 176.57 49.2651 174.342 50.9022C172.151 52.5392 169.218 53.3578 165.542 53.3578Z" fill="white"/> +<path d="M145.094 18.5886C143.72 18.5886 142.569 18.1608 141.641 17.305C140.713 16.4121 140.249 15.2773 140.249 13.9007C140.249 12.524 140.713 11.3892 141.641 10.4963C142.569 9.56615 143.72 9.10107 145.094 9.10107C146.468 9.10107 147.619 9.56615 148.548 10.4963C149.476 11.3892 149.94 12.524 149.94 13.9007C149.94 15.2773 149.476 16.4121 148.548 17.305C147.619 18.1608 146.468 18.5886 145.094 18.5886ZM141.53 23.2766H148.603V52.688H141.53V23.2766Z" fill="white"/> +<path d="M128.687 26.5694C129.689 25.3788 130.933 24.43 132.418 23.7231C133.904 22.979 135.575 22.6069 137.431 22.6069V29.2482C134.869 29.2482 132.827 29.8621 131.304 31.0899C129.819 32.3177 129.077 33.9362 129.077 35.9453V52.6881H122.003V23.2766H128.687V26.5694Z" fill="white"/> +<path d="M104.318 13.9006C106.36 13.9006 108.198 14.1797 109.832 14.7378C111.466 15.2959 112.858 16.0958 114.01 17.1376C115.161 18.1793 116.033 19.4443 116.627 20.9326C117.259 22.3836 117.574 24.0021 117.574 25.788C117.574 27.6111 117.259 29.2667 116.627 30.755C115.996 32.206 115.105 33.4524 113.954 34.4942C112.803 35.536 111.41 36.3359 109.776 36.894C108.143 37.4521 106.323 37.7311 104.318 37.7311H96.1306V52.688H89.0013V13.9006H104.318ZM103.984 31.4805C106.1 31.4805 107.679 30.9596 108.718 29.9179C109.795 28.8389 110.333 27.4623 110.333 25.788C110.333 24.1137 109.795 22.7557 108.718 21.7139C107.679 20.6721 106.1 20.1513 103.984 20.1513H96.1306V31.4805H103.984Z" fill="white"/> +<g clip-path="url(#clip0_2_116)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5772 23.4756L0 38.0528V38.076L14.5772 23.4756Z" fill="#04D5E7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M66.8662 28.8965V28.9405L39.7771 56.0295L66.8662 28.8965Z" fill="#FEBE29"/> +<path d="M14.5772 23.4755L0 38.0527V13.5776L13.5284 0.0264573V0H38.0154L14.5772 23.4755Z" fill="#04D5E7"/> +<path d="M66.866 23.2838L23.1498 67H0V43.7095L43.7095 0H66.866V23.2838Z" fill="#FE4352"/> +<path d="M53.3113 67H28.8244L39.7771 56.0295L66.8662 28.9404V53.4224L53.3113 67Z" fill="#FEBE29"/> +</g> +<defs> +<clipPath id="clip0_2_116"> +<rect width="66.866" height="67" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/.claude/skills/content-create-hero-image/assets/logos/prisma-mark-prism.svg b/.claude/skills/content-create-hero-image/assets/logos/prisma-mark-prism.svg new file mode 100644 index 00000000000..8bfb36cafed --- /dev/null +++ b/.claude/skills/content-create-hero-image/assets/logos/prisma-mark-prism.svg @@ -0,0 +1,15 @@ +<svg width="263" height="264" viewBox="0 0 263 264" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="263" height="264" fill="white"/> +<g clip-path="url(#clip0_2_87)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M57.3357 92.5002L0 149.939V150.03L57.3357 92.5002Z" fill="#04D5E7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M263.001 113.861V114.034L156.453 220.773L263.001 113.861Z" fill="#FEBE29"/> +<path d="M57.3357 92.5003L0 149.939V53.5L53.2105 0.10425V0H149.524L57.3357 92.5003Z" fill="#04D5E7"/> +<path d="M263 91.7452L91.0537 264H0V172.229L171.92 0H263V91.7452Z" fill="#FE4352"/> +<path d="M209.686 264H113.373L156.453 220.773L263.001 114.034V210.5L209.686 264Z" fill="#FEBE29"/> +</g> +<defs> +<clipPath id="clip0_2_87"> +<rect width="263" height="264" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/.claude/skills/content-create-hero-image/assets/templates/cover.svg b/.claude/skills/content-create-hero-image/assets/templates/cover.svg index 4a142aacbd6..a5c7be1e306 100644 --- a/.claude/skills/content-create-hero-image/assets/templates/cover.svg +++ b/.claude/skills/content-create-hero-image/assets/templates/cover.svg @@ -1,59 +1,70 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - Prisma blog/social cover template (Eclipse style). - Canonical frame: 1200x630 (social/OG). For other formats change width/height/viewBox - and scale font sizes proportionally (hero 844x474, youtube 1280x720). - - Replace the {{TOKENS}} below. Delete unused title lines. Keep the layer groups intact - so the file stays editable in Figma / SVG editors. - - FONTS: brand faces are Mona Sans (headings/display, weight 800), Inter (body, 400), - Geist Mono (data/code, 500) — bundled in assets/fonts/. Do NOT use Barlow (off-brand). - Using a different family/weight makes renderers fall back to a generic sans. For an SVG - that renders correctly outside this repo (browser, Figma, GitHub preview), embed the - fonts with scripts/embed-fonts.py. - - The surface gradient is the standard vertical teal-green → near-black (do not change it). - - Placeholders: - {{ACCENT}} accent + badge color (default #5EEAD4) - {{BADGE}} eyebrow label, UPPERCASE (e.g. PRISMA POSTGRES) — delete the <g id="badge"> if none - {{TITLE_LINE_1}} / {{TITLE_LINE_2}} / {{TITLE_LINE_3}} headline, 1-3 lines, hand-wrapped - {{TITLE_COLOR}} default #f7fafc (dark cover) or #111827 (light cover) - {{SUBTITLE}} one-line description — delete the node if none - {{SUBTITLE_COLOR}} default #a0aec0 ---> -<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630" fill="none" role="img" aria-labelledby="cover-title cover-desc"> - <title id="cover-title">{{TITLE_LINE_1}} {{TITLE_LINE_2}} - Prisma blog cover. {{SUBTITLE}} - + + {{POST_TITLE}} + {{ONE_LINE_DESCRIPTION}} — Prisma blog cover, 2026 brand: light paper surface, spectral prism wash, {{ACCENT_NAME}} accent. - - - + + + + + + + + + + + + + + + + + - + + + + + - - - - {{BADGE}} + + + + {{KICKER_LABEL}} - - {{TITLE_LINE_1}} - {{TITLE_LINE_2}} - {{TITLE_LINE_3}} + + + {{TITLE_LINE_1}} + {{TITLE_LINE_2}} - {{SUBTITLE}} + + {{SUBTITLE}} + + + + + + + + {{MODULE_LABEL}} + - - + + + Prisma diff --git a/.claude/skills/content-create-hero-image/assets/tokens.json b/.claude/skills/content-create-hero-image/assets/tokens.json index fbae4e91b05..73dd5c4400e 100644 --- a/.claude/skills/content-create-hero-image/assets/tokens.json +++ b/.claude/skills/content-create-hero-image/assets/tokens.json @@ -1,154 +1,136 @@ { - "$comment": "Prisma blog/social cover design tokens. Color values are sourced from the Eclipse design system (prisma/web: packages/eclipse/src/styles/globals.css) and the canonical OG generator (apps/docs/src/app/og/[...slug]/route.tsx). Fonts and cover formats are cross-referenced with SOCIALS.fig. Treat this file as the single source of truth for generated covers; update it when Eclipse tokens change.", + "$comment": "Prisma blog/social cover design tokens — 2026 rebrand ('prism' brand). Values are sourced from the rebranded eclipse package (prisma/web: packages/eclipse/src/styles/globals.css) and the marketing site app's globals.css @theme block + product accent map (the app currently named apps/site-redesign; it replaces apps/site at cutover — check apps/site if that name is gone). Treat this file as the single source of truth for generated covers; update it when the brand tokens change. The pre-rebrand dark 'aurora' palette is retired — do not reach for it.", "cover": { "background": { - "$comment": "Signature Eclipse cover surface — a teal-green 'aurora': peak teal-green at the top (strongest top-left) fading through dark navy to near-black at the bottom. Built from a vertical base gradient PLUS a soft radial glow biased to the top-left, with a barely-there slate grid. This luminous teal top is the brand signature — never flatten it to a solid/near-flat dark. Layer order: bg gradient → aurora radial → grid.", - "gradientDirection": "vertical base (top → bottom) + top-left radial aurora", - "gradientTop": "#0C3B35", - "gradientUpperMid": "#0A1F23", - "gradientLowerMid": "#050E18", - "gradientBottom": "#03070D", - "aurora": { "type": "radial", "center": "cx 0.28, cy 0 (top, left-of-center)", "radius": 0.95, "stops": ["#1B6056 @0% opacity 0.6", "#0E433C @45% opacity 0.16", "transparent @100%"] }, - "grid": { "color": "#94A3B8", "opacity": 0.03, "cell": 48 }, - "lightAlt": "#ffffff" + "$comment": "Signature surface — LIGHT paper. A white (#ffffff) or paper (#f9faf5) canvas with (1) a subtle grain texture (SVG feTurbulence, multiply, ~0.05 opacity) and (2) an optional 'spectral wash': two-to-three soft radial gradients of the prism colors (cyan/yellow/red at 14-26% via color-mix) pooling along one edge or corner and dissolving to white. This luminous paper-plus-prism-wash is the brand signature. Dark covers are the exception (see inverse).", + "default": "#ffffff", + "paper": "#f9faf5", + "wash": { + "type": "2-3 radial gradients along one edge, dissolving to the surface color", + "cyan": "rgba(1, 215, 228, 0.20)", + "yellow": "rgba(243, 195, 6, 0.16)", + "red": "rgba(255, 118, 130, 0.17)", + "note": "positions vary per cover; a bottom-edge pool (like the site heroes) is the house default" + }, + "grain": { "how": "feTurbulence fractalNoise baseFrequency 0.9, opacity ~0.05, blend multiply", "note": "atmosphere, not decoration — barely visible" }, + "inverse": { "$comment": "Dark variant for the rare cover that needs it: brand ink surface, paper text, same prism accents.", "surface": "#151515", "surfaceAlt": "#0f0f0f", "text": "#f9faf5" } }, - "accent": { - "$comment": "Mint teal #5EEAD4 (Eclipse teal-300) is the cover accent: eyebrows, headline highlight, hero numbers, hairlines. #71e8df is an accepted near-equivalent (docs OG).", - "teal": "#5EEAD4", - "altCyan": "#71e8df", - "glow": "rgba(45, 212, 191, 0.55)" + "accents": { + "$comment": "The three prism colors. Use ONE as the cover's accent (dot, highlight, hero element), chosen by product (see products) or topic; the other two may appear only inside the spectral wash or a deliberate three-stripe prism motif. Never introduce other hues.", + "cyan": { "400": "#01d7e4", "500": "#00bbcb", "600": "#009aaa", "700": "#007f8d", "300": "#7be7f0", "200": "#b3f4f9", "100": "#dcfdff", "50": "#eeffff", "950": "#00353c" }, + "red": { "400": "#ff7682", "500": "#f34a60", "600": "#d02344", "300": "#ff9fa4", "200": "#ffc2c4", "100": "#ffdfdf", "50": "#ffeeee" }, + "yellow": { "300": "#f3c306", "400": "#eaa700", "500": "#d48700", "200": "#f8da85", "100": "#fcedc2", "50": "#fff7e0" } }, - "bars": { - "$comment": "Horizontal/vertical data bars. Neutral/reference (the 100% ceiling) = slate gradient; hero/product = teal gradient with glow; track behind = #1F2937.", - "track": "#1F2937", - "neutral": ["#64748B", "#CBD5E1"], - "hero": ["#14B8A6", "#5EEAD4"], - "heroGlow": "#2DD4BF" + "text": { + "ink": "#151515", + "title": "#151515", + "body": "#3a3b3c", + "muted": "#646567", + "titleOnDark": "#f9faf5", + "bodyOnDark": "#a5a5a6" }, "card": { - "$comment": "Translucent panel (code block, log, terminal, comparison bars). A dark navy fill at ~0.74-0.8 opacity so the aurora shows faintly through; a hairline light border. Inner chips/boxes use #0B1220 @ ~0.7. Keep cards ≥48px off the canvas edge.", - "fill": "#0A1622", - "fillOpacity": 0.74, - "border": "rgba(255,255,255,0.10)", - "radius": 24, - "innerFill": "#0B1220" + "$comment": "Cards sit ON the light surface: white fill, hairline ink border, soft shadow, generous radius. Inner wash surface for chips/rows uses the card-wash tint. Keep cards ≥48px off the canvas edge.", + "fill": "#ffffff", + "border": "rgba(0,0,0,0.06)", + "borderStrong": "rgba(0,0,0,0.12)", + "radius": 20, + "shadow": "0 10px 30px rgba(21,21,21,0.08)", + "wash": "#eef4f3", + "washComment": "≈ color-mix(prism-cyan-50 18%, neutral #f5f5f4) — the site's card-wash", + "codeInk": { "$comment": "Code/terminal cards may invert to ink for contrast on the light canvas — the ONE sanctioned dark element per cover.", "fill": "#151515", "text": "#f9faf5", "muted": "#a5a5a6", "radius": 20 } }, - "text": { - "title": "#f7fafc", - "titleOnLight": "#111827", - "body": "#9CA3AF", - "muted": "#6b7280" + "kicker": { + "$comment": "The brand eyebrow = a small colored DOT + a sentence-case semibold label. NOT uppercase, NOT letter-spaced, NO dash — those are the retired style. Dot color = the cover's accent.", + "dotDiameter": 9, + "gap": 10, + "fontSize": 17, + "font": "Inter 600", + "labelColor": "rgba(21,21,21,0.70)" + }, + "prismMotif": { + "$comment": "Optional brand device: 45° diagonal bands in cyan/red/yellow (the logo's anatomy), used as a corner glyph, an edge bleed, or a divider. One motif max; keep it geometric and crisp, never a blurred rainbow.", + "angle": 45, + "order": ["cyan #01d7e4", "red #f34a60", "yellow #f3c306"] } }, "fonts": { - "$comment": "The Eclipse brand fonts (see prisma/web eclipse typography tokens). Headings/titles use Mona Sans VF (display); body uses Inter; data/code uses a mono. The skill bundles static instances in assets/fonts/ (Mona Sans 800, Inter 400, Geist Mono 500) so covers render on-brand without a prisma/web checkout. Do NOT use Barlow — that was the old docs OG face and reads off-brand. For an SVG that renders outside this repo, embed the faces with scripts/embed-fonts.py.", + "$comment": "The 2026 brand pairing: Sora (display, weight 500-600 — NOT 800), Inter (body 400, labels 600), Mona Sans Mono (code/data 500). All bundled as variable fonts in assets/fonts/. Mona Sans display and Geist Mono are RETIRED for covers; Barlow was never on-brand.", "display": { - "family": "Mona Sans", - "role": "Titles, headings, product wordmark, big numbers", - "weight": 800, - "note": "Mona Sans VF; Eclipse titles run weight 800-900 with extended width (110-125). The bundled static instance is wght 800.", - "file": "MonaSans.woff2" + "family": "Sora", + "role": "Titles, headlines, big numbers, the Prisma wordmark sign-off", + "weight": 500, + "weightEmphasis": 600, + "note": "Sora VF (bundled). Headlines are weight 500, sentence case, tight leading (~1.06-1.1). Weight 600 only for small emphasis (wordmark, stat callouts). Never 700+.", + "file": "Sora-VF.woff2", + "cssWeightRange": "100 800" }, "body": { "family": "Inter", - "role": "Subtitles, descriptions, UI/category labels", + "role": "Subtitles, descriptions, kicker labels (600), UI text", "weight": 400, - "file": "Inter-Regular.woff2" + "file": "Inter-VF.woff2", + "cssWeightRange": "100 900" }, "mono": { - "family": "Geist Mono", - "alt": "Mona Sans Mono / JetBrains Mono", - "role": "Data values, code snippets, technical labels", + "family": "Mona Sans Mono", + "role": "Code snippets, data values, file paths, terminal text", "weight": 500, - "file": "GeistMono.woff2" + "file": "MonaSansMono-VF.woff2", + "cssWeightRange": "200 900" } }, "fontsDir": "assets/fonts", "typeScale": { - "$comment": "px values used by the canonical 1200x630 OG layout; scale proportionally for other formats.", - "title": 80, - "titleLong": 56, + "$comment": "px values for the canonical 1200x630 canvas; scale proportionally for other formats.", + "title": 68, + "titleLong": 54, "titleLongThreshold": 30, - "titleLineHeight": 1.2, - "description": 32, - "descriptionLineHeight": 1.5, - "badge": 24, - "wordmark": 22 + "titleLineHeight": 1.08, + "description": 26, + "descriptionLineHeight": 1.45, + "kicker": 17, + "wordmark": 24 }, "layout": { "padding": 72, - "eyebrow": { - "$comment": "Brand eyebrow = a short teal hairline dash + uppercase letter-spaced label. Mona Sans 800, ~16px, letter-spacing ~2.4, teal #5EEAD4. The dash is a ~30px rounded line preceding the text.", - "dashLength": 30, - "gap": 14, - "fontSize": 16, - "letterSpacing": 2.4, - "uppercase": true - }, + "kicker": { "see": "cover.kicker" }, "wordmark": { - "$comment": "Brand sign-off = the word 'Prisma' in Mona Sans 800, white, ~22px, in whichever bottom corner is clear of content (bottom-left when the diagram is right-side; bottom-right or top-right when content fills the bottom). NEVER the URL prisma.io/blog, and never an icon paired with extra text.", + "$comment": "Brand sign-off. PREFERRED: the small full-color lockup (assets/logos/prisma-lockup-color.svg) inlined at ~112px wide — the mark carries at grid-thumbnail scale where small grey type disappears. Fallback: the word 'Prisma' in Sora 600 ink ~24px. In whichever bottom corner is clear of content, inside the 72px crop-safe margin (lockup right edge ≤1128 on a 1200 canvas). Never the URL prisma.io/blog; never an icon paired with extra 'Prisma' text.", + "lockup": "logos/prisma-lockup-color.svg", + "lockupWidth": 112, "text": "Prisma", - "font": "Mona Sans 800", - "fontSize": 22, - "color": "#FFFFFF", - "position": "a bottom corner clear of content" + "font": "Sora 600", + "fontSize": 24, + "color": "#151515", + "colorOnDark": "#f9faf5", + "position": "a bottom corner clear of content, ≥72px from edges" + }, + "safeZone": { + "$comment": "Blog cards crop covers to ~16:9 via object-cover and render them ~400px wide beside the post title, on light AND dark surfaces. Critical elements stay ≥72px from every edge and survive a centered 16:9 crop; kicker ≥20px or omitted; headline ≤6 words, never the post title restated; cover washes run stronger than page washes (~0.18–0.28 per stop) so the piece holds on dark.", + "margin": 72 } }, "products": { - "$comment": "Per-product accent palettes from Eclipse. Postgres (ppg) and ORM have official token sets. Compute and Next are 2026 platform products without dedicated color tokens yet; they inherit the neutral/platform treatment (white label + teal accent). Update when official tokens ship.", - "postgres": { - "label": "Prisma Postgres", - "badge": "PRISMA POSTGRES", - "foreground": "#0d9488", - "foregroundStrong": "#0f766e", - "foregroundWeak": "#14b8a6", - "background": "#f0fdfa", - "backgroundStrong": "#ccfbf1", - "backgroundReverse": "#14b8a6", - "backgroundReverseStrong": "#0d9488", - "stroke": "#0d9488", - "reverseWeak": "#99f6e4", - "coverAccent": "#71e8df", - "icon": "logos/prisma-postgres-icon.svg" - }, - "orm": { - "label": "Prisma ORM", - "badge": "PRISMA ORM", - "foreground": "#4f46e5", - "foregroundStrong": "#4338ca", - "foregroundWeak": "#6366f1", - "background": "#eef2ff", - "backgroundStrong": "#e0e7ff", - "backgroundReverse": "#6366f1", - "backgroundReverseStrong": "#4f46e5", - "stroke": "#4f46e5", - "coverAccent": "#818cf8" - }, - "compute": { - "label": "Prisma Compute", - "badge": "PRISMA COMPUTE", - "$comment": "No official Eclipse color-token set yet; uses the brand chip icon and platform teal accent.", - "coverAccent": "#71e8df", - "icon": "logos/prisma-compute-icon.svg" - }, - "next": { - "label": "Prisma 8", - "badge": "PRISMA 8", - "$comment": "No official Eclipse color-token set yet; lockup sets Prisma 8 in white per the announcement treatment.", - "coverAccent": "#71e8df", - "lockup": "logos/prisma-8-logo.svg" - } + "$comment": "Per-product accent from the redesigned site (PLATFORM_PRODUCT_ACCENTS). One accent per cover. The old teal-Postgres / indigo-ORM mapping is retired.", + "orm": { "label": "Prisma ORM", "kicker": "Prisma ORM", "accent": "#01d7e4", "accentName": "prism-cyan-400", "deep": "#007f8d", "tint": "#dcfdff" }, + "postgres": { "label": "Prisma Postgres", "kicker": "Prisma Postgres", "accent": "#eaa700", "accentName": "prism-yellow-400", "deep": "#965100", "tint": "#fcedc2", "note": "the kicker dot may use #f3c306 (yellow-300) for pop on white, as the site does" }, + "compute": { "label": "Prisma Compute", "kicker": "Prisma Compute", "accent": "#f34a60", "accentName": "prism-red-500", "deep": "#af0a33", "tint": "#ffdfdf" }, + "prisma8": { "label": "Prisma 8", "kicker": "Prisma 8", "accent": "#01d7e4", "accentName": "prism-cyan-400", "deep": "#007f8d", "tint": "#dcfdff", "note": "Prisma 8 (the ORM's next major, release candidate) rides the ORM cyan" }, + "platform": { "label": "Prisma", "kicker": "sentence-case topic label", "accent": "#01d7e4", "note": "topic posts with no single product owner default to cyan, or pick the accent that matches the post's subject" } }, "neutral": { - "foreground": "#111827", - "foregroundWeak": "#6b7280", - "foregroundWeaker": "#9ca3af", + "ink": "#151515", + "foreground": "#3a3b3c", + "foregroundWeak": "#646567", + "foregroundWeaker": "#a5a5a6", "backgroundDefault": "#ffffff", - "background": "#f3f4f6", - "backgroundReverse": "#1f2937", - "backgroundReverseStrong": "#111827", - "stroke": "#e5e7eb", - "strokeStrong": "#d1d5db" + "paper": "#f9faf5", + "backgroundNeutral": "#f5f5f4", + "stroke": "#e5e5e4", + "hairline": "rgba(0,0,0,0.06)", + "inkSurface": "#151515", + "inkSurfaceDeep": "#0f0f0f" }, "formats": { "$comment": "Dimensions verified against prisma/web. 'hero' is the in-post image (heroImagePath). 'social' is the OG/preview image (metaImagePath). Filenames follow the blog repo convention: hero.(svg|jpg) and meta.png under /imgs/.", diff --git a/.claude/skills/content-create-hero-image/references/design-system.md b/.claude/skills/content-create-hero-image/references/design-system.md index 2a764acea14..70287238c9b 100644 --- a/.claude/skills/content-create-hero-image/references/design-system.md +++ b/.claude/skills/content-create-hero-image/references/design-system.md @@ -1,161 +1,134 @@ -# Prisma cover design system +# Prisma cover design system — 2026 brand -The visual language for Prisma blog and social covers, distilled from the Eclipse -design system, the canonical OG generator, and `SOCIALS.fig`. Machine-readable -values live in [`../assets/tokens.json`](../assets/tokens.json) — that file is the -source of truth; this document explains intent. +The visual language for Prisma blog and social covers under the 2026 rebrand: light paper +surfaces, the three-color prism accent family, Sora display type. Machine-readable values live +in [`../assets/tokens.json`](../assets/tokens.json) — that file is the source of truth; this +document explains intent. -## Sources +> **The pre-2026 style is retired.** The dark teal "aurora" surface, Mona Sans 800 headlines, +> uppercase dash eyebrows, and Geist Mono labels are the OLD look. The worked examples in +> `assets/examples/` and `assets/hero1–4.svg` predate the rebrand — study them for *composition +> and module structure only*, never for palette, type, or surface. -| What | Where (in `prisma/web`) | -| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| Color tokens (hex) | `packages/eclipse/src/styles/globals.css` | -| Type tokens (font + scale) | `apps/eclipse/content/design-system/tokens/typography.mdx` | -| Layout composition recipe | `apps/docs/src/app/og/[...slug]/route.tsx` (layout only — it uses Barlow, which is **off-brand**; covers use Mona Sans) | -| Brand fonts | `packages/eclipse/src/static/fonts/` (Mona Sans VF, Mona Sans Mono VF); bundled static instances in [`../assets/fonts/`](../assets/fonts/) | -| Logos / marks | Official press kit [`prisma/presskit`](https://github.com/prisma/presskit); product icons in [`../assets/logos/`](../assets/logos/) (`README.md`) | -| Blog cover conventions | `apps/blog/content/blog//index.mdx` + `apps/blog/public//imgs/` | -| Hand-designed cover library | `SOCIALS.fig` (see [`figma-source.md`](./figma-source.md)) | +## Sources -The skill bundles its brand fonts in `assets/fonts/`, so it renders on-brand without extra setup. -This skill lives in the `prisma/web` repo, so the live Eclipse tokens in `packages/eclipse/` are -available to reconcile against. +The durable sources are the **eclipse package** and the **marketing site app**. The marketing +site currently lives at `apps/site-redesign` (a temporary app name — it replaces `apps/site` at +cutover); if that path is gone, look for the same files under `apps/site`. `tokens.json` bundles +every needed value, so a missing path never blocks a cover. + +| What | Where (in `prisma/web`) | +| -------------------------- | --------------------------------------------------------------------------------------------------------------- | +| Eclipse (docs/blog) tokens | `packages/eclipse/src/styles/globals.css` (ink/paper neutrals, Sora/Inter wiring) — durable | +| Brand fonts | `packages/eclipse/src/static/fonts/` — durable; bundled copies in [`../assets/fonts/`](../assets/fonts/) | +| Brand color tokens | the marketing site's `src/app/globals.css` `@theme` block (prism-cyan/red/yellow ramps, paper, card-wash) | +| Product accent map | the marketing site's `src/components/product/icons.ts` (`PLATFORM_PRODUCT_ACCENTS`) | +| Logos / marks | `apps/blog/public/logo/` (full-color lockup) and the prism mark; bundled in [`../assets/logos/`](../assets/logos/) | +| Live brand reference | the marketing site's heroes and cards (`src/components/sections/`, `/brand` route) | +| Blog cover conventions | `apps/blog/content/blog//index.mdx` + `apps/blog/public//imgs/` | ## The look in one paragraph -A premium **teal-green "aurora" surface** — a luminous teal glow at the top (strongest top-left) -fading through dark navy to near-black at the bottom — with a single mint-teal accent (`#5EEAD4`). -A **dash-prefixed eyebrow** (a short teal hairline + uppercase label) names the topic; a bold, -**large** Mona Sans headline with its key phrase in teal carries the message; and one **content -module** does the showing — a row of icon tiles, a comparison card of bars, a log/data panel, a -terminal, or a code card. The word **`Prisma`** signs off in a clear bottom corner. Nothing else: -no stock illustration, no random gradient, no decorative noise. Restraint is the brand, and the -diagram is minimal — favour a few clean boxes and one hero glyph over arrows, chips, and pills. -(See the worked examples in `assets/examples/`, which mirror the brand reference frames.) +A **light paper canvas** — white or `#f9faf5` — with barely-there grain and, usually, a soft +**spectral wash**: two or three radial pools of the prism colors (cyan, yellow, red at ~15–25%) +dissolving into the surface along one edge, exactly like the site's hero panels. **One prism +accent** (chosen by product) carries the cover: a small **kicker dot** beside a sentence-case +label names the topic, a **Sora 500** headline in ink carries the message, and one **content +module** — a white hairline-bordered card, an ink code card, a flow of rounded tiles — does the +showing. The **`Prisma`** wordmark (Sora 600 ink) or the small full-color lockup signs off in a +clear bottom corner. Nothing else: no dark aurora, no uppercase eyebrows, no glows, no stock +decoration. Restraint is still the brand; the surface just turned to daylight. ## Color -- **Cover surface (default, dark):** a **vertical** gradient — teal-green `#163535` (top) → `#0A1018` → near-black `#03060E` (bottom). The lighter top carries the eyebrow + headline; the bottom anchors the content module. This visible top-to-bottom shift is part of the look — do not flatten it. -- **Accent (signature):** mint teal **`#5EEAD4`** (Eclipse teal-300) for eyebrows, headline highlight, hero numbers, hairlines (`#71e8df` is an accepted near-equivalent). Use exactly one accent per cover. -- **Title text:** `#f7fafc`/white on dark, `#111827` on light. -- **Body / subtitle / muted:** `#9CA3AF` (`#a0aec0` ok). -- **Background texture:** a faint slate grid (`#94A3B8` @ ~4.5%, 48px cells) plus a soft teal radial glow (`rgba(45,212,191,0.16)`), positioned to complement the composition. Both barely-there — atmosphere, not decoration. -- **Bar / data fills:** neutral/reference bars = slate gradient `#64748B → #CBD5E1`; the hero/product bar = teal gradient `#14B8A6 → #5EEAD4` with a `#2DD4BF` glow. Track behind bars = `#1F2937`. -- **Card surface:** `#111827` at ~92% opacity, `1.5px` border `#FFFFFF` @ 8%, radius ~22. -- **Product palettes** (semantic, from Eclipse): Postgres = teal (`#0d9488` / cover accent `#5EEAD4`), ORM = indigo (`#4f46e5`). Compute and Next inherit the platform teal. See `tokens.json → products`. - -Light covers are allowed for editorial/educational pieces: white background, `#111827` -title, product-colored accent. Dark is the default and the launch/announcement standard. +- **Cover surface (default, light):** `#ffffff` or paper `#f9faf5`. Add the **grain** (SVG + `feTurbulence`, multiply, ~5% opacity) and usually a **spectral wash** — 2–3 soft radial + gradients (`cyan rgba(1,215,228,.20)`, `yellow rgba(243,195,6,.16)`, `red rgba(255,118,130,.17)`) + pooling along the bottom or a corner and fading to the surface. The wash is atmosphere; type and + modules must sit on calm areas. +- **Accent (one per cover, by product):** ORM / Prisma 8 → **cyan `#01d7e4`**; Postgres → + **yellow `#eaa700`** (dot may use `#f3c306`); Compute → **red `#f34a60`**. Deep variants for + small text on white: cyan `#007f8d`, yellow `#965100`, red `#af0a33`. The other two prisms may + appear only inside the wash or a deliberate prism-stripe motif. +- **Text:** ink `#151515` for titles, `#3a3b3c` body, `#646567` muted. On the rare dark cover: + paper `#f9faf5` titles, `#a5a5a6` muted. +- **Cards:** white fill, hairline border `rgba(0,0,0,0.06)` (strong: `0.12`), radius ~20, soft + shadow `0 10px 30px rgba(21,21,21,0.08)`. Inner chip/row surface: card-wash `#eef4f3`. +- **Code/terminal cards invert to ink** (`#151515` fill, paper text) — the one sanctioned dark + element on a light cover, and it reads as the site's code blocks do. +- **Prism motif (optional):** 45° diagonal bands cyan → red → yellow (the logo's anatomy) as a + corner glyph, edge bleed, or divider. Crisp and geometric — never a blurred rainbow. +- **Dark covers are the exception**, for genuinely nocturnal subjects: ink `#151515`/`#0f0f0f` + surface, paper text, same accents. Say why when you choose it. ## Typography -| Role | Family | Weight | Notes | -| ------------------ | ------------------------------------ | ------ | ------------------------------------------------------------- | -| Title / headline | **Mona Sans** | 800 | Eclipse titles run 800–900, extended width; line-height ~1.1 | -| Eyebrow (kicker) | **Geist Mono** | 600 | UPPERCASE, letter-spacing ~2.7, accent teal, leading `—` rule | -| Subtitle / body | **Inter** | 400 | line-height 1.5 | -| Data values / code | **Geist Mono** (alt: Mona Sans Mono) | 500 | benchmark numbers, req/s, snippets, API paths | -| Big numbers | **Mona Sans** | 800 | hero stats and percentages | +| Role | Family | Weight | Notes | +| ------------------ | ------------------ | ------ | ---------------------------------------------------------------- | +| Title / headline | **Sora** | 500 | sentence case, line-height ~1.08, tracking ~-0.5 to -1; never 700+ | +| Kicker label | **Inter** | 600 | sentence case beside the accent dot; `rgba(21,21,21,.7)` | +| Subtitle / body | **Inter** | 400 | line-height ~1.45 | +| Data values / code | **Mona Sans Mono** | 500 | snippets, paths, numbers inside modules | +| Big numbers | **Sora** | 600 | hero stats; 600 is the ceiling | +| Wordmark sign-off | **Sora** | 600 | the word `Prisma`, ~24px ink | -Never substitute a different display face. **Mona Sans + Inter** is the pairing — **not Barlow**. -Barlow is the legacy docs-OG face and reads off-brand; do not use it on covers. +**Sora + Inter is the pairing.** Mona Sans display (the old 800 headlines), Geist Mono, and +Barlow are all off-brand on covers now. Headlines are **sentence case** — never all-caps, never +letter-spaced. -### Fonts & rendering (important) +### Fonts & rendering (unchanged mechanics) -The brand faces are **Mona Sans** (headings/display, weight 800), **Inter** (body, 400), and -**Geist Mono** (data/code, 500). The skill bundles static instances in -[`../assets/fonts/`](../assets/fonts/) (Mona Sans is a variable font; the bundled instance is the -weight-800 display cut). Use those families/weights — an arbitrary weight or a different family -makes renderers fall back to a generic sans, the #1 cause of an off-brand cover. +The bundled faces are variable fonts: `Sora-VF.woff2`, `Inter-VF.woff2`, +`MonaSansMono-VF.woff2`. A cover that only *names* the families renders with fallbacks wherever +they aren't installed, and librsvg ignores `@font-face` entirely. So the pipeline is still: -**One source of truth: embed the fonts, then render.** A cover that only _names_ the families -renders with fallback fonts wherever they are not installed. Two renderers disagree about -fonts, which is the #1 cause of "the PNG and SVG look different": +1. **`scripts/embed-fonts.py `** — subsets and inlines the three faces as base64 + `@font-face` (self-contained SVG). +2. **`scripts/export-png.sh`** — renders the PNG with headless Chrome, which honors the embedded + faces, making the PNG pixel-identical to the SVG in a browser. -- A **browser/Figma** renders the SVG's embedded `@font-face` (correct brand fonts). -- **librsvg/`rsvg-convert`** _ignores_ `@font-face`, and since fontconfig does not index the - bundled `.woff2`, it falls back to a generic sans (e.g. Verdana) — wrong. - -So the pipeline is: **(1) `scripts/embed-fonts.py `** inlines the faces as base64 -`@font-face` (self-contained SVG), then **(2) `scripts/export-png.sh`** renders the PNG with -**headless Chrome/Chromium**, which honors the embedded faces — making the PNG pixel-identical -to the SVG-in-browser. Always embed before exporting or sharing. (rsvg/magick remain only as -fallbacks and warn that fonts may not match.) +Always embed before exporting or sharing. ## Layout (canonical 1200×630) -- Uniform **72px** padding on all edges; nothing touches the canvas edge. -- **Headline block:** top-left; eyebrow, then title (1–3 hand-wrapped lines), optional one-line - subtitle (~20px gap). Large type — title ~62–72px. -- **`Prisma` wordmark:** the brand sign-off — the word `Prisma` in Mona Sans 800, white, ~22px, - in whichever **bottom corner is clear of content** (bottom-left when the module is right-side; - bottom/top-right when content fills the bottom). Never the URL `prisma.io/blog`; never an icon - paired with extra text. -- Strong left alignment and generous negative space on the right. Do not center everything. - -### Spacing & breathing room (coherence) +- Uniform **72px** padding; nothing touches the canvas edge. +- **Kicker** top-left: accent dot (9px) + sentence-case Inter 600 label (~17px). No dash, no caps. +- **Headline** below: Sora 500, ~56–68px, 1–3 hand-wrapped lines, ink. Emphasis inside a headline + is the accent color (deep variant if the phrase is small), not a weight change. +- Optional **one-line subtitle**: Inter 400 ~26px, `#646567`. +- **Content module** lower/right; **wordmark** in a clear bottom corner. +- Left-anchored, generous negative space. Center only a single graphic-led composition. -Cramped elements read as "off". Hold these minimums and keep them consistent across a set: +### Spacing minimums (unchanged) -- **≥ 48px** between any card/diagram and the canvas edge. -- **≥ 40px** between sibling tiles/boxes in a row (equal gaps; symmetric about their center). -- **≥ 24px** padding inside a card before its content; **≥ 28px** between stacked rows of content. -- Eyebrow → headline → subtitle → module each get clear air; never let two text blocks crowd. -- Verify spacing on the **rendered PNG**, by measurement, not by eye (see `design-review.md`). +- ≥ 48px between any card and the canvas edge; ≥ 40px between sibling tiles; ≥ 24px padding + inside cards; ≥ 28px between stacked rows. Verify on the rendered PNG, by measurement. ### Shared anatomy (every cover) -The house style is one frame with a few fixed parts and a swappable **content module**: - -1. **Eyebrow** top-left — a short teal **hairline dash** (~30px) + uppercase label in **Mona Sans - 800** ~16px, letter-spacing ~2.4, accent teal (`— LABEL`). Names the topic (e.g. - `REQUEST-TIME IMAGE PIPELINE`, `THROUGHPUT VS RAW PG`). -2. **Headline** below it — **Mona Sans 800**, **~62–72px** (go large), tight tracking (about -1.8), - 1–3 lines, white with the **key phrase in accent teal** (e.g. "Image transforms / **as app - logic**"). -3. **Content module** in the lower/right area — the visual that carries the idea (see catalog). - Keep it **minimal**: a few clean tiles/rows and one hero element beat a busy diagram. -4. **`Prisma` wordmark** — Mona Sans 800, white, ~22px, in a clear bottom corner. Always present. -5. **Base** — the teal-green **aurora** surface (bright teal top, strongest top-left → near-black - bottom) + a barely-there slate grid. Always. Never a flat/near-solid dark fill. - -Left-anchored, generous space, one accent, no decoration beyond the base aurora. +1. **Surface** — white/paper + grain, usually a spectral wash on one edge. Never the old dark + aurora; never a flat grey. +2. **Kicker** — accent dot + sentence-case label naming product or topic. +3. **Headline** — Sora 500 ink; short and declarative. (No-copy covers stay first-class: the + module + wordmark carry it, kicker optional.) +4. **One content module** — the visual that carries the idea (catalog below). +5. **Sign-off** — `Prisma` in Sora 600 ink, or the small full-color lockup, in a clear corner. ### Content modules (pick one per cover) -Each example folder in [`../assets/examples/`](../assets/examples/) is a worked instance: - -| Module | When | Looks like | Example | -| -------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | -| **Pipeline / flow** | a sequence or transform (A → B → C) | a row of rounded **square tiles**, equal size and equal gaps, a mono label under each; the key tile gets a teal-glow border and holds the hero logo/glyph (e.g. the Bun mark). Keep it minimal — the tiles + labels read as a flow; skip arrows, param chips, and pills | `image-transformations-with-bun-on-prisma-compute` | -| **Comparison card** | "X vs Y", "% of", benchmarks | rounded `#111827`@92% card of **horizontal bars** — each row = prism icon + label, big right-aligned number + unit; reference row fills 100% (slate), hero row fills its true ratio (teal + glow). Bar width _is_ the comparison | `prisma-next-benchmark` | -| **Data / log panel** | streams, logs, events, real-time | a dark panel of monospace **rows** (timestamp + label + mini-bar), optionally a small flow beneath (`source → client`) | `building-open-chat` | -| **Terminal card** | CLI, scaffolding, getting-started | a terminal-style card with a `$ command` and a short ✓ checklist | `create-prisma-deploy-prisma-compute` | -| **Code card** | config, schema, API shape | a code-editor card (filename tab + syntax-tinted lines), optional target nodes beneath | `prisma-compute-config-file` | - -Tiles/cards: rounded ~22–24px, **translucent** fill `#0A1622` @ ~0.74 (so the aurora shows -faintly through), hairline border `#FFFFFF` @ ~10%; inner chips/boxes `#0B1220` @ ~0.7; the hero -element uses a teal border + `#2DD4BF` glow. Labels and code/data are **Geist Mono**; headings and -big numbers are **Mona Sans**; prose is **Inter**. - -**No-copy covers (common).** Most Prisma blog images carry **no headline at all** — the content -module plus the `Prisma` wordmark do the work. Default to no-copy unless the post has a short, -punchy thesis worth setting as a headline. A no-copy cover centres/enlarges the module and keeps -the eyebrow optional. - -**Isometric skew (optional hero treatment).** For card/table/grid modules, a subtle isometric -skew (e.g. `transform="matrix(1,0.18,-0.18,1,…)"` or a ~15–25° rotate + scale) gives the hero a -premium 3-D plane. Use it for **cards and tables**; keep **flow/loop/pipeline and "→ bill" -diagrams flat** (skew muddies a left-to-right read). One skewed plane per cover, never the whole -canvas. +The module *structures* survive the rebrand; their *skin* is new. Reskin rules: -**Multiple directions.** When asked for N directions (1–4), produce N independent -`cover-.svg`/`.png` pairs exploring distinct modules or framings (e.g. literal diagram vs -typographic thesis vs comparison), each fully on-brand, and present them together for selection. +| Module | When | New-brand skin | +| -------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Pipeline / flow** | a sequence or transform (A → B → C) | white rounded tiles with hairline borders on the light surface; equal gaps; the hero tile gets the accent border + accent tint fill; mono labels below | +| **Comparison card** | "X vs Y", "% of", benchmarks | one white card; bars in card-wash track; reference bar `#e5e5e4`→`#a5a5a6`; hero bar in the accent; ink numbers right-aligned | +| **Data / log panel** | streams, logs, events, real-time | white card of mono rows (`#3a3b3c`), accent-tinted highlight row; or an ink code-card variant | +| **Terminal card** | CLI, scaffolding, getting-started | **ink card** (`#151515`, paper text) with a `$ command` and short ✓ checklist (✓ in the accent) | +| **Code card** | config, schema, API shape | ink card with a filename tab; syntax tints drawn from the prism ramps (cyan for keywords, yellow strings, red flags) — subtle, 2–3 tints max | +| **Prism stripe** | brand/launch moments | the 45° three-band motif as the graphic itself, with the lockup or a single stat | -**Graphic-led variant.** When a single chart/diagram is the whole message, you can drop the -headline and **center the module**, with the standalone product logo (e.g. `prisma-8-logo.svg`) -centered on top as the only brand mark. +**Isometric skew** stays available for card/table modules (one skewed plane max; flows stay +flat). **Multiple directions** (1–4) and **graphic-led no-copy variants** work as before. ## Formats @@ -166,4 +139,4 @@ centered on top as the only brand mark. | YouTube thumbnail | 1280×720 | video | `youtube-thumbnail.png` | | Generic blog cover | 1200×630 | alias of social | `blog-cover.svg/.png` | -Scale font sizes proportionally when the frame changes (e.g. ×0.70 for the 844-wide hero). +Scale font sizes proportionally when the frame changes (×0.70 for the 844-wide hero). diff --git a/.claude/skills/content-create-hero-image/scripts/embed-fonts.py b/.claude/skills/content-create-hero-image/scripts/embed-fonts.py index 3a068eca25e..7b845911c1d 100644 --- a/.claude/skills/content-create-hero-image/scripts/embed-fonts.py +++ b/.claude/skills/content-create-hero-image/scripts/embed-fonts.py @@ -3,7 +3,7 @@ A cover SVG that only references the brand families by name renders with fallback fonts wherever they are not installed (browsers, Figma, GitHub preview). This subsets -Mona Sans (800), Inter (400) and Geist Mono (500) to just the glyphs the SVG uses, +Sora, Inter and Mona Sans Mono (variable fonts) to just the glyphs the SVG uses, then injects them as base64 @font-face rules. If fonttools/brotli are unavailable, it embeds the bundled WOFF2 files whole. The fallback is larger but keeps the SVG self-contained without a Python dependency install. The PNG export does not need @@ -24,10 +24,14 @@ import sys from pathlib import Path +# 2026 brand faces. All three are variable fonts, so the @font-face rule carries +# a weight RANGE and one embed serves every weight the SVG uses (Sora 500/600, +# Inter 400/600, Mona Sans Mono 500). The old static faces (Mona Sans 800, +# Geist Mono) are retired but their files remain for re-rendering legacy covers. FACES = [ - ("Mona Sans", 800, "MonaSans.woff2"), - ("Inter", 400, "Inter-Regular.woff2"), - ("Geist Mono", 500, "GeistMono.woff2"), + ("Sora", "100 800", "Sora-VF.woff2"), + ("Inter", "100 900", "Inter-VF.woff2"), + ("Mona Sans Mono", "200 900", "MonaSansMono-VF.woff2"), ] diff --git a/.github/workflows/lychee.yml b/.github/workflows/lychee.yml index 03c554e7933..3e77c41a805 100644 --- a/.github/workflows/lychee.yml +++ b/.github/workflows/lychee.yml @@ -52,6 +52,8 @@ jobs: --exclude '^https?://localhost' --exclude 'https://www.gnu.org' --exclude 'https://docs.solidjs.com' + --exclude 'https://pris.ly/vercel-app-demo-live' + --exclude 'https://app-deploy-demo.prisma.io' --accept 200,201,204,301,302,303,307,308,403,429 ${{ steps.changed-docs.outputs.all_changed_files }} output: lychee/out.md @@ -81,6 +83,8 @@ jobs: --exclude '^https?://localhost' --exclude 'https://www.gnu.org' --exclude 'https://docs.solidjs.com' + --exclude 'https://pris.ly/vercel-app-demo-live' + --exclude 'https://app-deploy-demo.prisma.io' --accept 200,201,204,301,302,303,307,308,403,429 ${{ steps.changed-docs.outputs.all_changed_files }} output: lychee/out-retry.md diff --git a/.github/workflows/sync-management-api-docs.yml b/.github/workflows/sync-management-api-docs.yml index f366c472889..4313f9d6b13 100644 --- a/.github/workflows/sync-management-api-docs.yml +++ b/.github/workflows/sync-management-api-docs.yml @@ -1,4 +1,4 @@ -name: Sync Management API Docs +name: Sync REST API Docs on: repository_dispatch: @@ -11,7 +11,7 @@ concurrency: jobs: sync: - name: Sync Management API Documentation + name: Sync REST API Documentation runs-on: ubuntu-latest steps: - name: Checkout repository @@ -33,18 +33,18 @@ jobs: - name: Generate docs and Postman collection working-directory: apps/docs - run: pnpm run generate:management-api-docs + run: pnpm run generate:rest-api-docs - name: Check for changes id: changes run: | - if [[ -z "$(git status --porcelain --untracked-files=all -- apps/docs/content/docs/management-api/ apps/docs/public/prisma-management-api.postman_collection.json apps/docs/vercel.json)" ]]; then + if [[ -z "$(git status --porcelain --untracked-files=all -- apps/docs/content/docs/rest-api/ apps/docs/public/prisma-rest-api.postman_collection.json apps/docs/vercel.json)" ]]; then echo "changed=false" >> $GITHUB_OUTPUT echo "No changes detected" else echo "changed=true" >> $GITHUB_OUTPUT echo "Changes detected:" - git status --short -- apps/docs/content/docs/management-api/ apps/docs/public/prisma-management-api.postman_collection.json apps/docs/vercel.json + git status --short -- apps/docs/content/docs/rest-api/ apps/docs/public/prisma-rest-api.postman_collection.json apps/docs/vercel.json fi - name: Commit and push @@ -52,8 +52,8 @@ jobs: run: | git config user.email "prismabots@gmail.com" git config user.name "Prismo" - git add apps/docs/content/docs/management-api/ apps/docs/public/prisma-management-api.postman_collection.json apps/docs/vercel.json - git commit -m "chore(docs): sync management API documentation" + git add apps/docs/content/docs/rest-api/ apps/docs/public/prisma-rest-api.postman_collection.json apps/docs/vercel.json + git commit -m "chore(docs): sync REST API documentation" git push "https://x-access-token:${{ secrets.BOT_TOKEN_DOCS_COMMIT }}@github.com/${{ github.repository }}.git" HEAD:${{ github.ref_name }} - name: Trigger Vercel deploy diff --git a/apps/blog/content/blog/agentic-engineering-at-prisma/index.mdx b/apps/blog/content/blog/agentic-engineering-at-prisma/index.mdx index ae9ca0e2be7..59810fbe2aa 100644 --- a/apps/blog/content/blog/agentic-engineering-at-prisma/index.mdx +++ b/apps/blog/content/blog/agentic-engineering-at-prisma/index.mdx @@ -6,7 +6,8 @@ authors: - "Tyler Hogarth" metaTitle: "Agentic Engineering at Prisma" metaDescription: "Part of Prisma's agentic software development series on how it ships software with AI agents, covering the process, roles, and documentation layer that make cross-repo agent work possible." -heroImagePath: "/agentic-engineering-at-prisma/imgs/hero.png" +heroImagePath: "/agentic-engineering-at-prisma/imgs/hero.svg" +heroImageAlt: "The five Drive lifecycle stages as a rail, Plan, Execute, Review, Ship, and Delivery review, with the agent-owned Execute stage highlighted" metaImagePath: "/agentic-engineering-at-prisma/imgs/meta.png" tags: ["ai"] series: agentic-engineering diff --git a/apps/blog/content/blog/agents-md-for-databases/index.mdx b/apps/blog/content/blog/agents-md-for-databases/index.mdx index 920acc65ae5..333d2334240 100644 --- a/apps/blog/content/blog/agents-md-for-databases/index.mdx +++ b/apps/blog/content/blog/agents-md-for-databases/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "AGENTS.md for Databases: Rules for Safe, Fast Coding Agents" metaDescription: "A copy-pasteable AGENTS.md section for database work: ephemeral Postgres via npx create-db, safe migrations, and JSON output for Claude Code, Cursor, and Codex." heroImagePath: "/agents-md-for-databases/imgs/hero.svg" -heroImageAlt: "An AGENTS.md file open in an editor, with database rules highlighted" +heroImageAlt: "An ink code card with an AGENTS.md filename tab holding the five database rules, with the npx create-db@latest --json line marked in yellow" metaImagePath: "/agents-md-for-databases/imgs/meta.png" tags: - "ai" diff --git a/apps/blog/content/blog/announcing-query-insights-for-prisma-postgres/index.mdx b/apps/blog/content/blog/announcing-query-insights-for-prisma-postgres/index.mdx index 6bd0e3bab63..0395618c60a 100644 --- a/apps/blog/content/blog/announcing-query-insights-for-prisma-postgres/index.mdx +++ b/apps/blog/content/blog/announcing-query-insights-for-prisma-postgres/index.mdx @@ -7,8 +7,9 @@ authors: - "Aidan McAlister" metaTitle: "Announcing Query Insights For Prisma Postgres" metaDescription: "Query Insights gives you built-in visibility into how your database queries behave in production. It is included in Prisma Postgres and works out of the box without any setup." -metaImagePath: "/announcing-query-insights-for-prisma-postgres/announcing-query-insights-for-prisma-postgres-og.png" -heroImagePath: "/announcing-query-insights-for-prisma-postgres/announcing-query-insights-for-prisma-postgres-og.png" +metaImagePath: "/announcing-query-insights-for-prisma-postgres/imgs/meta.png" +heroImagePath: "/announcing-query-insights-for-prisma-postgres/imgs/hero.svg" +heroImageAlt: "The Queries tab of a Prisma Postgres database: average latency, queries per second, a latency chart, and grouped query shapes with the slowest one highlighted" --- Query Insights gives you built-in visibility into how your database queries behave in production. It is included in Prisma Postgres and works out of the box without any setup. diff --git a/apps/blog/content/blog/app-hosting-compute-platforms-for-ai-agents-2026/index.mdx b/apps/blog/content/blog/app-hosting-compute-platforms-for-ai-agents-2026/index.mdx index a771e73b15c..55bf3c2cb0d 100644 --- a/apps/blog/content/blog/app-hosting-compute-platforms-for-ai-agents-2026/index.mdx +++ b/apps/blog/content/blog/app-hosting-compute-platforms-for-ai-agents-2026/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "App Hosting and Compute Platforms for AI Agents in 2026" metaDescription: "A field guide to the 2026 wave of app-hosting and compute platforms (Prisma Compute, Neon, Cloudflare Containers, Hosting.com, Unkey, and Insforge) and how close each gets to one coherent stack for agents." heroImagePath: "/app-hosting-compute-platforms-for-ai-agents-2026/imgs/hero.svg" -heroImageAlt: "Field guide, 2026: app hosting and compute for AI agents. Prisma Compute, Hosting.com, Cloudflare Containers, Unkey Deploy, Neon Compute, and Insforge." +heroImageAlt: "An evaluation matrix of six platforms, Prisma Compute, Neon Compute, Cloudflare Containers, Hosting.com, Unkey Deploy and Insforge, scored on when they shipped, whether a database is included, and whether the stack is integrated" metaImagePath: "/app-hosting-compute-platforms-for-ai-agents-2026/imgs/meta.png" tags: - "platform" diff --git a/apps/blog/content/blog/building-open-chat/index.mdx b/apps/blog/content/blog/building-open-chat/index.mdx index 9c9c1aa95d7..a0813b9628f 100644 --- a/apps/blog/content/blog/building-open-chat/index.mdx +++ b/apps/blog/content/blog/building-open-chat/index.mdx @@ -8,7 +8,7 @@ metaTitle: "How I Built a Chat App That Never Drops a Token" metaDescription: "A personal walkthrough of building Open Chat (oss.chat): durable, resumable AI chat on Durable Streams, Prisma Streams, TanStack DB, and Prisma Compute. How each piece works and what it enables." excerpt: "How I built Open Chat: durable, resumable AI chat where the answer is safe the instant it exists. It runs on Durable Streams, Prisma Streams, TanStack DB, and Prisma Compute." heroImagePath: "/building-open-chat/imgs/hero.svg" -heroImageAlt: "Open Chat: a durable log of message.created and message.delta events, with an SSE tail that resumes from offset 412. Chat that never drops a token, durable-log-backed streaming." +heroImageAlt: "An append-only event log for one chat: message.created, message.delta and message.completed rows on a durable stream, with the live delta highlighted" metaImagePath: "/building-open-chat/imgs/meta.png" tags: - "platform" @@ -183,4 +183,4 @@ Then read the code. The whole app is about 6,000 lines and built to be read. The I set out to fix one tiny annoyance: a chat that drops its tail when you look away. What I ended up with is a small demonstration that durable, resumable streaming doesn't have to be exotic infrastructure. It can be an append-only log, a typed database, a live query, and one deploy command. Never dropping a token turned out to be the easy path, as long as you let the log be the truth. -The reason it stayed simple is that the app, the streaming service, and the database all live in one place. That's what [Prisma Compute](/launching-prisma-compute-public-beta) and [Prisma Postgres](https://www.prisma.io/postgres) are for: your app runs next to your data, deploys in one command, and is free to try while Compute is in public beta. If you want the rest of the story, see how we [launched Compute](/launching-prisma-compute-public-beta), why it [runs on Bun's Rust rewrite](/bun-rust-rewrite-prisma-compute), and how it handles [image transformations](/image-transformations-with-bun-on-prisma-compute) and [custom domains](/prisma-compute-custom-domains). Come build with us in [#prisma-compute](https://pris.ly/discord-compute) on Discord. +The reason it stayed simple is that the app, the streaming service, and the database all live in one place. That's what [Prisma Compute](/launching-prisma-compute-public-beta) and [Prisma Postgres](https://www.prisma.io/postgres) are for: your app runs next to your data, deploys in one command, and is free to try on the Free plan. If you want the rest of the story, see how we [launched Compute](/launching-prisma-compute-public-beta), why it [runs on Bun's Rust rewrite](/bun-rust-rewrite-prisma-compute), and how it handles [image transformations](/image-transformations-with-bun-on-prisma-compute) and [custom domains](/prisma-compute-custom-domains). Come build with us in [#prisma-compute](https://pris.ly/discord-compute) on Discord. diff --git a/apps/blog/content/blog/bun-rust-rewrite-prisma-compute/index.mdx b/apps/blog/content/blog/bun-rust-rewrite-prisma-compute/index.mdx index 9676a95cee2..c849525b736 100644 --- a/apps/blog/content/blog/bun-rust-rewrite-prisma-compute/index.mdx +++ b/apps/blog/content/blog/bun-rust-rewrite-prisma-compute/index.mdx @@ -6,8 +6,8 @@ authors: - "Alexey Orlenko" metaTitle: "We put Bun's Rust rewrite in production on Prisma Compute" metaDescription: "Why Prisma Compute's public beta runs on Bun's Rust rewrite canary: the memory and connection-pool failures we hit on stable Bun, and what changed." -heroImagePath: "/bun-rust-rewrite-prisma-compute/imgs/hero.png" -heroImageAlt: "Bun, Rust, and Prisma Compute" +heroImagePath: "/bun-rust-rewrite-prisma-compute/imgs/hero.svg" +heroImageAlt: "Peak resident memory in the Bun.S3File.arrayBuffer() loop inside a 1 GiB container: stable 1.3.14 runs past 900 MiB and is OOM-killed at iteration 96, while the Rust rewrite canary stays flat at 118 MiB to 4096 iterations" metaImagePath: "/bun-rust-rewrite-prisma-compute/imgs/meta.png" tags: - "platform" diff --git a/apps/blog/content/blog/claude-generated-50-websites-overnight-prisma-compute/index.mdx b/apps/blog/content/blog/claude-generated-50-websites-overnight-prisma-compute/index.mdx index 8102ea7c2ff..46206c4c9b1 100644 --- a/apps/blog/content/blog/claude-generated-50-websites-overnight-prisma-compute/index.mdx +++ b/apps/blog/content/blog/claude-generated-50-websites-overnight-prisma-compute/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Claude Generated 50 Websites Overnight with Prisma Compute" metaDescription: "Ali Fatemi gave Claude the Prisma docs and CLI, then used Prisma Compute to turn AI-generated websites into working URLs." heroImagePath: "/claude-generated-50-websites-overnight-prisma-compute/imgs/hero.svg" -heroImageAlt: "A dark pipeline showing claude, Prisma Compute, and live URLs under the headline 50 websites overnight." +heroImageAlt: "Fifty small deployment tiles in a dense grid with one picked out in red, standing for the roughly 50 sites an agent generated overnight and deployed inside one Prisma app" metaImagePath: "/claude-generated-50-websites-overnight-prisma-compute/imgs/meta.png" excerpt: "Ali Fatemi gave Claude the Prisma docs and CLI, then used Prisma Compute to turn generated websites into working URLs." tags: diff --git a/apps/blog/content/blog/create-prisma-deploy-prisma-compute/index.mdx b/apps/blog/content/blog/create-prisma-deploy-prisma-compute/index.mdx index 557149471ed..7f5b92f55a4 100644 --- a/apps/blog/content/blog/create-prisma-deploy-prisma-compute/index.mdx +++ b/apps/blog/content/blog/create-prisma-deploy-prisma-compute/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Deploy Prisma Apps with create-prisma" metaDescription: "create-prisma now scaffolds Compute-ready Prisma apps with prisma.compute.ts, compute:deploy, Prisma Postgres, and Prisma Skills add-ons." heroImagePath: "/create-prisma-deploy-prisma-compute/imgs/hero.svg" -heroImageAlt: "Scaffold a deploy-ready app with create-prisma: bun create prisma@stable, then choose a template, generate a typed config, and add Postgres and Skills." +heroImageAlt: "An ink terminal card running bun create prisma@stable, with a checklist of what the scaffold writes: prisma.compute.ts, Prisma Postgres, Prisma Skills, and a compute:deploy script" metaImagePath: "/create-prisma-deploy-prisma-compute/imgs/meta.png" excerpt: "create-prisma now scaffolds Compute-ready Prisma apps with prisma.compute.ts, compute:deploy, Prisma Postgres, and Prisma Skills add-ons." series: prisma-compute @@ -88,4 +88,4 @@ bunx @prisma/cli@latest app deploy - Follow the [deploy quickstart](https://docs.prisma.io/docs/prisma-compute/deploy) to take the generated app to a live URL. - Browse the [Prisma Compute docs](https://docs.prisma.io/docs/compute) for branching, environment variables, and the full CLI reference. -Compute is in [public beta](https://docs.prisma.io/docs/compute) and free while the beta lasts. It runs your app on the same infrastructure as [Prisma Postgres](https://www.prisma.io/postgres), which has a generous free tier of its own, so the project you scaffold today already has somewhere to run. Tell us what you build in [#prisma-compute](https://pris.ly/discord-compute) on Discord. +[Compute](https://docs.prisma.io/docs/compute) includes 1M requests a month on the Free plan. It runs your app on the same infrastructure as [Prisma Postgres](https://www.prisma.io/postgres), which has a generous free tier of its own, so the project you scaffold today already has somewhere to run. Tell us what you build in [#prisma-compute](https://pris.ly/discord-compute) on Discord. diff --git a/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx b/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx index 968a0963a86..ce0985d1a67 100644 --- a/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx +++ b/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx @@ -8,7 +8,7 @@ authors: metaTitle: "Data migrations in Prisma 8" metaDescription: "Write data migrations in TypeScript with Prisma 8. Backfill columns and transform data alongside schema changes using a type-safe query builder." heroImagePath: "/data-migrations-in-prisma-next/imgs/hero.svg" -heroImageAlt: "Data migrations in Prisma 8" +heroImageAlt: "A migration flow: addColumn leaves displayName nullable, a highlighted dataTransform step backfills it to Anonymous, then setNotNull makes the column required" metaImagePath: "/data-migrations-in-prisma-next/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/drive-and-the-maker/index.mdx b/apps/blog/content/blog/drive-and-the-maker/index.mdx index c64da60e81f..252a284e8f9 100644 --- a/apps/blog/content/blog/drive-and-the-maker/index.mdx +++ b/apps/blog/content/blog/drive-and-the-maker/index.mdx @@ -6,7 +6,8 @@ authors: - "Tyler Hogarth" metaTitle: "Drive and the Maker" metaDescription: "Part of Prisma's agentic software development series on how it ships software with AI agents, going deep on Drive, the development process, and the Maker role." -heroImagePath: "/drive-and-the-maker/imgs/hero.png" +heroImagePath: "/drive-and-the-maker/imgs/hero.svg" +heroImageAlt: "A line pulled from the essay set in large type on paper with a soft prism wash: when routine implementation is cheap, coordination and ritual become the expensive things." metaImagePath: "/drive-and-the-maker/imgs/meta.png" tags: ["ai"] series: agentic-engineering diff --git a/apps/blog/content/blog/evaluating-object-storage-providers-for-prisma-compute/index.mdx b/apps/blog/content/blog/evaluating-object-storage-providers-for-prisma-compute/index.mdx index 731e0d598d6..c6c3df1919f 100644 --- a/apps/blog/content/blog/evaluating-object-storage-providers-for-prisma-compute/index.mdx +++ b/apps/blog/content/blog/evaluating-object-storage-providers-for-prisma-compute/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Evaluating Object Storage Providers for Prisma Compute" metaDescription: "We benchmarked Tigris and Cloudflare R2 from six Prisma Compute regions using a latency-sensitive virtual filesystem workload, with AWS S3 and S3 Express as a baseline." heroImagePath: "/evaluating-object-storage-providers-for-prisma-compute/imgs/hero.svg" -heroImageAlt: "Tigris finished about 3x faster than Cloudflare R2 on the mixed read/write phase across six Prisma Compute regions" +heroImageAlt: "An evaluation matrix of three object stores on the criteria that separated them: egress price, bucket model, and read median for 10 KiB reads from Frankfurt, with Tigris the highlighted row" metaImagePath: "/evaluating-object-storage-providers-for-prisma-compute/imgs/meta.png" tags: - "platform" diff --git a/apps/blog/content/blog/evolving-agentic-engineering-at-prisma/index.mdx b/apps/blog/content/blog/evolving-agentic-engineering-at-prisma/index.mdx index aa8f7919db8..d1c467211c6 100644 --- a/apps/blog/content/blog/evolving-agentic-engineering-at-prisma/index.mdx +++ b/apps/blog/content/blog/evolving-agentic-engineering-at-prisma/index.mdx @@ -7,6 +7,7 @@ authors: metaTitle: "Evolving Agentic Engineering at Prisma" metaDescription: "A follow-up on what we learned after putting Drive into practice: where an opinionated process helped, where it became too heavy, and why we are moving toward leaner skills, stronger plans, and cheaper execution as models and harnesses improve." heroImagePath: "/evolving-agentic-engineering-at-prisma/imgs/hero.svg" +heroImageAlt: "A before and after drawing: seven items an encoded process makes you own, beside three lean skill contracts, spec to plan, plan to milestone, and diff to review" metaImagePath: "/evolving-agentic-engineering-at-prisma/imgs/meta.png" tags: ["ai"] series: agentic-engineering diff --git a/apps/blog/content/blog/give-your-agent-a-database/index.mdx b/apps/blog/content/blog/give-your-agent-a-database/index.mdx index e9af22459ba..2518976d7ec 100644 --- a/apps/blog/content/blog/give-your-agent-a-database/index.mdx +++ b/apps/blog/content/blog/give-your-agent-a-database/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "npx create-db: Instant Postgres for Your Coding Agent" metaDescription: "npx create-db gives coding agents a temporary Postgres database in seconds, no sign-up. JSON output lets Cursor, Claude Code, and Codex test on real Postgres." heroImagePath: "/give-your-agent-a-database/imgs/hero.svg" -heroImageAlt: "A terminal running npx create-db --json and returning a Postgres connection string" +heroImageAlt: "A three step flow: a coding agent runs npx create-db@latest --json and gets a real Prisma Postgres database at db.prisma.io that deletes itself after 24 hours" metaImagePath: "/give-your-agent-a-database/imgs/meta.png" tags: - "ai" diff --git a/apps/blog/content/blog/gremlin-turning-open-tasks-into-pull-requests/index.mdx b/apps/blog/content/blog/gremlin-turning-open-tasks-into-pull-requests/index.mdx index d4b8596fa06..31c41dd8d2b 100644 --- a/apps/blog/content/blog/gremlin-turning-open-tasks-into-pull-requests/index.mdx +++ b/apps/blog/content/blog/gremlin-turning-open-tasks-into-pull-requests/index.mdx @@ -6,8 +6,9 @@ authors: - "Tyler Hogarth" metaTitle: "Gremlin: turning open tasks into pull requests" metaDescription: "Gremlin is an autonomous engineering agent for small, well-scoped tasks. It uses Mastra for orchestration and OpenCode in a sandbox to turn Sentry issues, Linear tasks, and Slack instructions into reviewable pull requests." -heroImagePath: "/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.png" -heroImageAlt: "Gremlin Cloud Agent illustration with infrastructure icons, terminal output, and deployment status panels" +heroImagePath: "/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.svg" +heroImageAlt: "A pipeline where Sentry issues, Linear tasks, and Slack threads fan into one chain, gather context, sandbox, validate, and end in an Open PR tile" +metaImagePath: "/gremlin-turning-open-tasks-into-pull-requests/imgs/meta.png" tags: ["ai"] --- diff --git a/apps/blog/content/blog/how-prisma-build-with-agentic-ai/index.mdx b/apps/blog/content/blog/how-prisma-build-with-agentic-ai/index.mdx index 38a293e13fc..b44587bc042 100644 --- a/apps/blog/content/blog/how-prisma-build-with-agentic-ai/index.mdx +++ b/apps/blog/content/blog/how-prisma-build-with-agentic-ai/index.mdx @@ -7,7 +7,8 @@ authors: metaTitle: "Agentic Engineering: How Prisma Builds with AI" metaDescription: "In three months, Prisma fundamentally changed how it builds software by rethinking the relationship between engineers and AI agents. Here's what we learned building Prisma 8 with agentic engineering." metaImagePath: "/how-prisma-build-with-agentic-ai/imgs/meta.png" -heroImagePath: "/how-prisma-build-with-agentic-ai/imgs/meta.png" +heroImagePath: "/how-prisma-build-with-agentic-ai/imgs/hero.svg" +heroImageAlt: "An ink prompt card holding the three questions engineers ask of an agent, with how can I set it up to succeed marked in cyan" tags: ["ai", "education"] series: agentic-engineering seriesIndex: 1 diff --git a/apps/blog/content/blog/how-to-use-ai-safely-and-responsibly/index.mdx b/apps/blog/content/blog/how-to-use-ai-safely-and-responsibly/index.mdx index 843ec473ae6..a8eeefee040 100644 --- a/apps/blog/content/blog/how-to-use-ai-safely-and-responsibly/index.mdx +++ b/apps/blog/content/blog/how-to-use-ai-safely-and-responsibly/index.mdx @@ -7,8 +7,9 @@ authors: - "Matthias Oertel" metaTitle: "How to use AI coding tools safely and responsibly" metaDescription: "Practical security guidelines for developers using AI coding assistants — token scopes, secrets management, sandboxing, prompt injection, and reviewing generated code." -metaImagePath: "/how-to-use-ai-safely-and-responsibly/imgs/hero.png" -heroImagePath: "/how-to-use-ai-safely-and-responsibly/imgs/hero.png" +metaImagePath: "/how-to-use-ai-safely-and-responsibly/imgs/meta.png" +heroImagePath: "/how-to-use-ai-safely-and-responsibly/imgs/hero.svg" +heroImageAlt: "A policy card pairing the scoped permissions the post allows, bash(npm test), repo:read, and /sandbox, against the broad grants it refuses" tags: - "ai" --- diff --git a/apps/blog/content/blog/how-xeito-builds-features-not-database-infrastructure-with-prisma/index.mdx b/apps/blog/content/blog/how-xeito-builds-features-not-database-infrastructure-with-prisma/index.mdx index ce7a29a6c93..1e6620c8f29 100644 --- a/apps/blog/content/blog/how-xeito-builds-features-not-database-infrastructure-with-prisma/index.mdx +++ b/apps/blog/content/blog/how-xeito-builds-features-not-database-infrastructure-with-prisma/index.mdx @@ -8,7 +8,7 @@ metaTitle: "How One Founder Builds a Live Sports Platform with Prisma" metaDescription: "How Xeito uses Prisma ORM and Prisma Postgres to ship live scoring, leagues, payments, and player workflows without a database team." excerpt: "Gabriel Gil Graña is building Xeito, a live sports platform, without turning database infrastructure into the work." heroImagePath: "/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/hero.svg" -heroImageAlt: "Build features, not database infrastructure." +heroImageAlt: "A quote card: Gabriel Gil Graña of Xeito on wanting to spend his time creating features instead of managing memory, pool connections, storage limits, replicas and backups" metaImagePath: "/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/meta.png" tags: - "case-study" diff --git a/apps/blog/content/blog/image-transformations-with-bun-on-prisma-compute/index.mdx b/apps/blog/content/blog/image-transformations-with-bun-on-prisma-compute/index.mdx index 845de8c8e2d..c442473b9de 100644 --- a/apps/blog/content/blog/image-transformations-with-bun-on-prisma-compute/index.mdx +++ b/apps/blog/content/blog/image-transformations-with-bun-on-prisma-compute/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Image Transformations with Bun on Prisma Compute" metaDescription: "Bun includes native image transformations, and Prisma Compute runs on Bun. Build image resize and format routes as ordinary app requests instead of paying for a separate image transformation service." heroImagePath: "/image-transformations-with-bun-on-prisma-compute/imgs/hero.svg" -heroImageAlt: "Request-time image pipeline on Prisma Compute: source to Bun.Image to webp. Image transforms as app logic." +heroImageAlt: "A three-tile request-time pipeline: chair.jpg requested with w=640 and q=75, transformed by Bun.Image, returned as chair.webp cached immutable for a year" metaImagePath: "/image-transformations-with-bun-on-prisma-compute/imgs/meta.png" excerpt: "Bun ships native image transformations, and Prisma Compute runs on Bun, so you build image resize and format routes as ordinary app requests, with no separate image service to pay for or manage." tags: @@ -384,7 +384,7 @@ The real difference is not the API. It is how you have to think about the work. With a standalone image service, transformations are metered as their own product. A cache miss might cost a transformation unit, a cache write, and a CDN read. Those are reasonable meters, and they are one more billing model to keep in your head. -On Prisma Compute, an image transform is regular application work. A request comes in, your app runs, Bun transforms the image, your app returns bytes. The same meters apply as for any other response: request count, active CPU, memory while the app is running, and outbound bandwidth. (Compute is in public beta and [free while the beta lasts](https://pris.ly/pricing-compute).) +On Prisma Compute, an image transform is regular application work. A request comes in, your app runs, Bun transforms the image, your app returns bytes. The same meters apply as for any other response: request count, active CPU, memory while the app is running, and outbound bandwidth. (Every plan [includes a monthly request allowance](https://pris.ly/pricing-compute), starting with 1M requests on the Free plan.) That helps most for small products, internal tools, agent-built apps, and media-light workloads. You no longer have to decide whether an image pipeline deserves its own vendor. Start with a route. If it ever takes real traffic, harden it like any other hot path: tighter presets, better cache keys, precomputed variants, a CDN in front, specialized processing exactly where you need it. @@ -398,7 +398,7 @@ That is the Compute model: app, data, and the operational loop in one place. Image transformations show why that matters, because they are not magic. They are code, CPU, memory, bytes, and a cache policy. Bun gives the runtime a native image pipeline, and Prisma Compute gives you somewhere to run it, as part of the app you were already going to deploy, right next to its data in [Prisma Postgres](https://www.prisma.io/postgres). -Prisma Compute is in public beta and free while the beta lasts. Sign in once, the one step that needs a human: +Prisma Compute's Free plan includes 1M requests a month, so trying this costs nothing. Sign in once, the one step that needs a human: ```bash bunx @prisma/cli@latest auth login diff --git a/apps/blog/content/blog/introducing-create-prisma/index.mdx b/apps/blog/content/blog/introducing-create-prisma/index.mdx index 7d024002fe4..256f6644479 100644 --- a/apps/blog/content/blog/introducing-create-prisma/index.mdx +++ b/apps/blog/content/blog/introducing-create-prisma/index.mdx @@ -7,8 +7,8 @@ authors: metaTitle: "Introducing Create-Prisma: Start a Prisma App With One Command" metaDescription: "create-prisma is a new CLI that creates an app with Prisma set up, a starter schema, seed data, database scripts, and optional Prisma Postgres setup." excerpt: "create-prisma is a new CLI that creates an app with Prisma set up, including a starter schema, seed data, database scripts, and optional Prisma Postgres setup." -heroImagePath: "/introducing-create-prisma/imgs/hero.png" -heroImageAlt: "Introducing create-prisma — a new CLI for starting Prisma apps" +heroImagePath: "/introducing-create-prisma/imgs/hero.svg" +heroImageAlt: "An ink terminal card running npm create prisma@latest, with a checklist of what the CLI generates: prisma/schema.prisma, prisma/seed.ts, prisma.config.ts, a .env file with DATABASE_URL, and the db:generate, db:migrate and db:seed scripts." metaImagePath: "/introducing-create-prisma/imgs/meta.png" tags: - "announcement" diff --git a/apps/blog/content/blog/launching-prisma-compute-public-beta/index.mdx b/apps/blog/content/blog/launching-prisma-compute-public-beta/index.mdx index 408f6ddc179..3d6b4655346 100644 --- a/apps/blog/content/blog/launching-prisma-compute-public-beta/index.mdx +++ b/apps/blog/content/blog/launching-prisma-compute-public-beta/index.mdx @@ -6,7 +6,7 @@ authors: - "Shane Neubauer" metaTitle: "Launching Prisma Compute in Public Beta" metaDescription: "Prisma Compute is now in public beta: TypeScript app hosting that runs on the same infrastructure as your database. Point your agent at your project and tell it to deploy." -heroImagePath: "/launching-prisma-compute-public-beta/imgs/hero.png" +heroImagePath: "/launching-prisma-compute-public-beta/imgs/hero.svg" heroImageAlt: "Prisma Compute, now in public beta" metaImagePath: "/launching-prisma-compute-public-beta/imgs/meta.png" pinned: true diff --git a/apps/blog/content/blog/make-your-docs-agent-ready/index.mdx b/apps/blog/content/blog/make-your-docs-agent-ready/index.mdx index 2751f2a81cd..7726f9fd7c6 100644 --- a/apps/blog/content/blog/make-your-docs-agent-ready/index.mdx +++ b/apps/blog/content/blog/make-your-docs-agent-ready/index.mdx @@ -8,7 +8,7 @@ metaTitle: "How to Make Your Docs Agent-Ready: llms.txt, Parity, MCP" metaDescription: "Coding agents fail silently on truncated indexes, broken links, and missing metadata. What we fixed in the Prisma docs, and how to audit yours." heroImagePath: "/make-your-docs-agent-ready/imgs/hero.svg" metaImagePath: "/make-your-docs-agent-ready/imgs/meta.png" -heroImageAlt: "A documentation site restructured so a coding agent can discover, fetch, and parse it" +heroImageAlt: "An ink panel listing the docs endpoints an agent fetches: llms.txt at 7 KB, the per-area indexes, llms-full.txt at 4.5 MB, skill.md, and the MCP discovery document" tags: - "ai" - "education" diff --git a/apps/blog/content/blog/mongodb-without-compromise/index.mdx b/apps/blog/content/blog/mongodb-without-compromise/index.mdx index f7d4757da37..07511dbb060 100644 --- a/apps/blog/content/blog/mongodb-without-compromise/index.mdx +++ b/apps/blog/content/blog/mongodb-without-compromise/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "MongoDB Without Compromise" metaDescription: "Prisma 8 brings a MongoDB-native experience to TypeScript with type-safe queries, real migrations, polymorphic models, embedded collections, and typed aggregation pipelines." heroImagePath: "/mongodb-without-compromise/imgs/hero.svg" -heroImageAlt: "Prisma 8 and MongoDB" +heroImageAlt: "An untyped MongoDB document beside the Prisma 8 contract that types it, including the embedded Address type." metaImagePath: "/mongodb-without-compromise/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/postgres-bloom-index-the-overlooked-postgres-feature/index.mdx b/apps/blog/content/blog/postgres-bloom-index-the-overlooked-postgres-feature/index.mdx index 95b4e729618..68cf9232474 100644 --- a/apps/blog/content/blog/postgres-bloom-index-the-overlooked-postgres-feature/index.mdx +++ b/apps/blog/content/blog/postgres-bloom-index-the-overlooked-postgres-feature/index.mdx @@ -6,9 +6,9 @@ authors: - "Ankur Datta" metaTitle: "Bloom Filters in Postgres: The Index Type Most Developers Overlook" metaDescription: "One bloom index can replace a stack of B-trees on wide tables with many filter combinations. A tour of the concept, the Postgres extension, and a benchmark you can run yourself." -heroImagePath: "/postgres-bloom-index-the-overlooked-postgres-feature/imgs/bloom-filters-in-postgres.png" -metaImagePath: "/postgres-bloom-index-the-overlooked-postgres-feature/imgs/bloom-filters-in-postgres.png" -heroImageAlt: "Bloom Filters in Postgres" +heroImagePath: "/postgres-bloom-index-the-overlooked-postgres-feature/imgs/hero.svg" +metaImagePath: "/postgres-bloom-index-the-overlooked-postgres-feature/imgs/meta.png" +heroImageAlt: "The item alice hashed by fnv1a, djb2 and murmur3, setting bits 2, 7 and 11 of a sixteen bit array, captioned one bloom signature per row." tags: - "prisma-postgres" - "education" diff --git a/apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx b/apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx index 14d0b71b04a..572e65320b6 100644 --- a/apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx +++ b/apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx @@ -6,9 +6,9 @@ authors: - "Luan van der Westhuizen" metaTitle: "Price the Work, Not the Workflow" metaDescription: "Agents can ship, preview, test, and retry in loops. Infrastructure pricing should charge for the work an app performs, not the workflow around it." -heroImagePath: "/price-the-work-not-the-workflow/imgs/hero.png" -metaImagePath: "/price-the-work-not-the-workflow/imgs/hero.png" -heroImageAlt: "Agent-assisted development loop showing workflow activity around a small metered bill." +heroImagePath: "/price-the-work-not-the-workflow/imgs/hero.svg" +metaImagePath: "/price-the-work-not-the-workflow/imgs/meta.png" +heroImageAlt: "Four separately priced meters, requests, provisioned memory, active CPU and outbound bandwidth, with deploys, previews, retries, seats and idle time struck out as not billed" series: prisma-compute seriesIndex: 8 tags: @@ -154,17 +154,16 @@ Work has cost. Shipping should feel safe. ## What this means for Prisma Compute -Prisma Compute is in public beta, and Compute is free during beta. But pricing is -part of the product model, so we are publishing how we expect it to work. +Pricing is part of the product model, and Prisma Compute's pricing is live. -If this thesis is real, it has to show up in the pricing table. Our current -approach is a concrete expression of the principles above: +If this thesis is real, it has to show up in the pricing table. Our approach is +a concrete expression of the principles above: - + @@ -174,7 +173,7 @@ approach is a concrete expression of the principles above: Requests @@ -230,12 +229,12 @@ actually consumed while work runs. There is one line worth watching before you ship: outbound bandwidth. For streaming, media, exports, file-heavy apps, and high-transfer APIs, transfer can become the largest part of the bill. We expose it as its own meter rather than -burying it inside a blended unit, and we expect to learn from it during beta. +burying it inside a blended unit. -This is still a beta model. Rates, limits, included usage, and policy details may -change before production billing turns on. But the direction is deliberate: -familiar meters, no tax on shipping, no hidden Prisma unit, and usage data humans -and agents can both reason about. +Every plan also includes a monthly request allowance — 1M requests on the Free +plan, up to 100M on Business — before the request meter starts. The direction is +deliberate: familiar meters, no tax on shipping, no hidden Prisma unit, and +usage data humans and agents can both reason about. ## The future we are building for @@ -244,8 +243,9 @@ the Prisma ORM. The principle in this post is not only about Compute, it is how we think the platform should treat builders. To get that right, we need to learn from real workloads. How long apps stay -alive, how much they compute versus wait, how much data they send out. Compute is -now in public beta and free during this time. [Share the shape of your +alive, how much they compute versus wait, how much data they send out. You can +start on the Free plan, which includes 1M requests a month. [Share the shape of +your workload](https://tally.so/r/NpEZXB?source=blog&post=price-the-work-not-the-workflow&campaign=compute-pricing-feedback&cta=blog_end_cta) so we can see where these meters match how you actually build, and where they do not. diff --git a/apps/blog/content/blog/prisma-7-ama-clearing-up-the-why-behind-the-changes/index.mdx b/apps/blog/content/blog/prisma-7-ama-clearing-up-the-why-behind-the-changes/index.mdx index 855331c319a..7bf355073fc 100644 --- a/apps/blog/content/blog/prisma-7-ama-clearing-up-the-why-behind-the-changes/index.mdx +++ b/apps/blog/content/blog/prisma-7-ama-clearing-up-the-why-behind-the-changes/index.mdx @@ -6,9 +6,9 @@ authors: - "Ankur Datta" metaTitle: "Prisma 7 Explained: Performance, Architecture, and AMA Answers" metaDescription: "Prisma 7 introduces major architectural changes. We answer community AMA questions on performance, database support, the new client generator, and what’s next." -metaImagePath: "/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta-64c44281ee8d3e0fe5e7e9bbd309603e5496945d-1266x711-26d35e93c9.png" -heroImagePath: "/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero-fed37f83921ceeba6d0395d774c48ae9d5b68dcc-844x474-7cca11ee09.png" -heroImageAlt: "Prisma 7 is a structural release focused on long-term architecture rather than surface-level features. Some things improved, others became stricter. This post answers questions from our recent AMA on X and explains where Prisma 7 stands today and where it’s headed." +metaImagePath: "/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta.png" +heroImagePath: "/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero.svg" +heroImageAlt: "A question and answer from the Prisma 7 AMA set in large type: Prisma 7 vs Prisma 6 performance, is it faster or slower, answered with the line that it depends heavily on how you measure performance, with that phrase in cyan." tags: - "orm" --- diff --git a/apps/blog/content/blog/prisma-compute-config-file/index.mdx b/apps/blog/content/blog/prisma-compute-config-file/index.mdx index 8cdcc2dd06d..52539f68420 100644 --- a/apps/blog/content/blog/prisma-compute-config-file/index.mdx +++ b/apps/blog/content/blog/prisma-compute-config-file/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Configure Prisma Compute deploys in TypeScript" metaDescription: "Prisma Compute now reads a typed TypeScript config file, so deploys are reproducible and monorepos work: declare one app or several, then ship the whole system with one command." heroImagePath: "/prisma-compute-config-file/imgs/hero.svg" -heroImageAlt: "One typed file for every app target: a prisma.compute.ts declaring an api app on Hono and a web app on Next.js" +heroImageAlt: "An ink prisma.compute.ts code card declaring a monorepo config: an api app rooted at apps/api on Hono and a web app rooted at apps/web on Next.js" metaImagePath: "/prisma-compute-config-file/imgs/meta.png" excerpt: "Prisma Compute now reads a typed prisma.compute.ts, so deploys are reproducible and monorepos work: declare one app or several, then ship the whole system with one command." series: prisma-compute @@ -153,4 +153,4 @@ Starting fresh? [`create-prisma`](/create-prisma-deploy-prisma-compute) scaffold For the full field reference, see the [configuration docs](https://docs.prisma.io/docs/compute/configuration). For everything else about deploying on Compute, start with the [quickstart](https://docs.prisma.io/docs/prisma-compute/deploy). -One config file is the point: the same repo describes your data with [Prisma Postgres](https://www.prisma.io/postgres), your app with [Prisma Compute](https://docs.prisma.io/docs/compute), and your deploys with `prisma.compute.ts`, so a person or an agent can reason about the whole system in one place. Compute is in public beta and free while the beta lasts. Tell us what you ship in [#prisma-compute](https://pris.ly/discord-compute) on Discord. +One config file is the point: the same repo describes your data with [Prisma Postgres](https://www.prisma.io/postgres), your app with [Prisma Compute](https://docs.prisma.io/docs/compute), and your deploys with `prisma.compute.ts`, so a person or an agent can reason about the whole system in one place. Every plan [includes Compute usage](https://pris.ly/pricing-compute), starting with 1M requests a month on the Free plan. Tell us what you ship in [#prisma-compute](https://pris.ly/discord-compute) on Discord. diff --git a/apps/blog/content/blog/prisma-compute-custom-domains/index.mdx b/apps/blog/content/blog/prisma-compute-custom-domains/index.mdx index fb486f57639..fcea9a9676a 100644 --- a/apps/blog/content/blog/prisma-compute-custom-domains/index.mdx +++ b/apps/blog/content/blog/prisma-compute-custom-domains/index.mdx @@ -6,8 +6,9 @@ authors: - "Tyler Benfield" metaTitle: "We Launched Prisma Compute with Custom Domains" metaDescription: "Prisma Compute launched with custom domain support. Here's how we made the setup one DNS record while handling TLS certificate provisioning, storage, and routing behind the scenes." -heroImagePath: "/prisma-compute-custom-domains/imgs/hero.png" -heroImageAlt: "Custom domain in browser address bar" +heroImagePath: "/prisma-compute-custom-domains/imgs/hero.svg" +heroImageAlt: "The one DNS record a custom domain needs: a CNAME for shop.acme.com pointing at switchboard.cdg.prisma.build with a TTL of 300, and a status row reading active" +metaImagePath: "/prisma-compute-custom-domains/imgs/meta.png" tags: - "platform" series: prisma-compute diff --git a/apps/blog/content/blog/prisma-compute-time-synchronization/index.mdx b/apps/blog/content/blog/prisma-compute-time-synchronization/index.mdx index af83ff717c1..14250bf53f8 100644 --- a/apps/blog/content/blog/prisma-compute-time-synchronization/index.mdx +++ b/apps/blog/content/blog/prisma-compute-time-synchronization/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "How Prisma Compute Keeps Time Accurate in Long-Running Applications" metaDescription: "How Prisma Compute keeps wall-clock time accurate in long-running Firecracker microVMs, using the host-paired KVM PTP clock instead of an in-guest NTP daemon." heroImagePath: "/prisma-compute-time-synchronization/imgs/hero.svg" -heroImageAlt: "Average clock skew on an awake VM, drifting about 13.75 ms/h (3.82 ppm): -13.8 ms at one hour, -27.5 ms at two, -55 ms at four, -82.5 ms at six" +heroImageAlt: "A drift drawing: the host paired clock read from /dev/ptp0 holds flat while an awake microVM's guest CLOCK_REALTIME falls away at 13.75 ms per hour (3.82 ppm), reaching about -82.5 ms after six hours" metaImagePath: "/prisma-compute-time-synchronization/imgs/meta.png" series: prisma-compute seriesIndex: 9 diff --git a/apps/blog/content/blog/prisma-compute-vs-vercel-pricing/index.mdx b/apps/blog/content/blog/prisma-compute-vs-vercel-pricing/index.mdx index 910bb8302eb..812d5cf6928 100644 --- a/apps/blog/content/blog/prisma-compute-vs-vercel-pricing/index.mdx +++ b/apps/blog/content/blog/prisma-compute-vs-vercel-pricing/index.mdx @@ -5,7 +5,7 @@ date: "2026-07-01" authors: - "Martin Janse van Rensburg" heroImagePath: "/prisma-compute-vs-vercel-pricing/imgs/hero.svg" -heroImageAlt: "The same 20M-request month costs about $98 on Prisma Compute at planned rates versus about $236 on Vercel (Pro), saving about $138 or 58% every month." +heroImageAlt: "A line by line table of the same 20M-request month: about $98 total on Prisma Compute at planned rates against about $236 on Vercel (Pro)" metaImagePath: "/prisma-compute-vs-vercel-pricing/imgs/meta.png" series: prisma-compute tags: @@ -17,14 +17,14 @@ metaDescription: "Prisma Compute vs Vercel, priced line by line: the same worklo You're weighing [Prisma Compute](https://www.prisma.io/compute) against Vercel to host a TypeScript app, and you want the hard numbers quick. Here they are, with some _musings_ about them after. :::note -Prisma Compute is in **public beta** and free right now. The rates cited here are the [_expected_ production prices](https://www.prisma.io/docs/compute/pricing); they might still change by the time actual billing starts. [Vercel's pricing](https://vercel.com/pricing) is live. +Prisma Compute pricing is **live**: the rates cited here are the [production prices](https://www.prisma.io/docs/compute/pricing). Every plan also includes a monthly request allowance — from 1M requests on the Free plan to 100M on Business — which this raw meter-by-meter comparison leaves out. [Vercel's pricing](https://vercel.com/pricing) is live too. ::: ## Comparing Prisma Compute and Vercel by usage meter Both are usage-based and scale to zero, so once an app goes idle, it costs nothing. -| Meter | Prisma Compute (Beta) | Vercel (Pro) | Cheaper | +| Meter | Prisma Compute | Vercel (Pro) | Cheaper | |---|---|---|---| | Requests / invocations | $1.00 / 1M | $0.60 / 1M | **Vercel** (~40% less) | | Provisioned memory | $0.006 / GB-hour | $0.0106 / GB-hour | **Prisma** (~43% less) | @@ -33,13 +33,13 @@ Both are usage-based and scale to zero, so once an app goes idle, it costs nothi | Edge requests _(workflow)_ | None | $2.00 / 1M | **Prisma** | | Seat fee _(workflow)_ | None | $20 / user / mo (incl. $20 credit) | **Prisma** | -**Note:** Vercel has a defined free tier and a more mature platform including a global edge network and a big ecosystem. Prisma Compute's production free allowance is work-in-progress, and it is a brand new product. +**Note:** Vercel has a more mature platform including a global edge network and a big ecosystem, and it is a brand new product on Prisma's side. On included usage, Prisma's Free plan comes with 1M Compute requests a month, and paid plans include 5M–100M requests before the request meter starts. ## Comparing a 20M-request app on Prisma Compute vs Vercel Here's a single growing app for a month. Let's assume 20M requests, 2 GB of memory held while running (call it always-on for a 730-hour month, so 1,460 GB-hours), 300 vCPU-hours of actual compute, and 2 TB of outbound traffic. One seat. -| Line | Prisma Compute (Beta) | Vercel (Pro, 1 seat) | +| Line | Prisma Compute | Vercel (Pro, 1 seat) | |---|---|---| | Requests / invocations (20M) | $20.00 | $12.00 | | Memory (1,460 GB-hrs) | $8.76 | $15.48 | @@ -86,14 +86,14 @@ Beyond the free tier, it doesn't always go that way. The bill can jump with no j In the [same thread](https://www.reddit.com/r/nextjs/comments/1qnld0e/is_anyone_else_frustrated_with_vercel_pricing/), another developer drew a sharp line between the two sides of Vercel: the frontend is "really nice and cheap/free," the backend "absolute highway robbery." Others pointed at workflow charges, like a $150 bill "for Deployment Protection Exceptions." The recurring frustration is not just that bills get high, it's that teams feel they discover the shape of the bill after the workflow has already run. -On the other hand, Prisma Compute is still in public beta, so developers haven't been able to use it in a way that would lead to meaningful feedback yet. I am sure there will be, and I will update this article when this feedback starts to arrive. +On the other hand, Prisma Compute has only just left beta, so developers haven't been able to use it long enough for meaningful pricing feedback yet. I am sure there will be, and I will update this article when this feedback starts to arrive. ## Summary -On planned rates, Prisma Compute is a lot cheaper than Vercel for the parts of a bill that usually dominate (CPU, memory, egress) and it doesn't bill the seat, deploys, or previews. Vercel is cheaper on raw request price and has a more mature platform, an established free tier, and an ecosystem Prisma needs to catch up with. +At today's rates, Prisma Compute is a lot cheaper than Vercel for the parts of a bill that usually dominate (CPU, memory, egress) and it doesn't bill the seat, deploys, or previews. Vercel is cheaper on raw request price and has a more mature platform and an ecosystem Prisma needs to catch up with. Finally, don't trust a blog article over your own math (or common sense). Figure things out for yourself before making a big commitment. :::ppg[Run the math on your own app] -[Prisma Compute](https://www.prisma.io/compute) is free while the beta lasts. [Deploy a TypeScript app](https://www.prisma.io/docs/compute/getting-started) next to your [Prisma Postgres](https://www.prisma.io/postgres) database and watch the usage meters before billing ever starts. +[Prisma Compute](https://www.prisma.io/compute) includes 1M requests a month on the Free plan. [Deploy a TypeScript app](https://www.prisma.io/docs/compute/getting-started) next to your [Prisma Postgres](https://www.prisma.io/postgres) database and watch the usage meters as it runs. ::: diff --git a/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx b/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx index f370de8c269..c8ce37ce13f 100644 --- a/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx +++ b/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx @@ -8,7 +8,7 @@ authors: metaTitle: "Prisma 8: A Call for Extension Authors" metaDescription: "Prisma 8 has a tiny core that knows nothing about specific databases. Postgres, vector search, and JSON-with-schema are extensions, on the same surface that's open to you. An invitation to build." heroImagePath: "/prisma-next-call-for-extension-authors/imgs/hero.svg" -heroImageAlt: "Prisma 8: A Call for Extension Authors" +heroImageAlt: "A dark manifest card for an extension package listing the four layers it can contribute: contract, query, runtime and migration, over the line that registers it" metaImagePath: "/prisma-next-call-for-extension-authors/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx b/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx index 66ce1d81501..1f4d228f3f1 100644 --- a/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx +++ b/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx @@ -7,8 +7,8 @@ authors: - "Will Madden" metaTitle: "Prisma 8 Early Access: Write Your Contract, Prompt Your Agent, Ship Your App" metaDescription: "Prisma 8 is open for Early Access. Define your data layer as a contract and the framework handles migrations, type-safe queries, and continuous upgrades, safe to delegate to your agent." -heroImagePath: "/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/meta.png" -heroImageAlt: "Prisma 8 Early Access" +heroImagePath: "/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/hero.svg" +heroImageAlt: "A three-step pipeline of cards: write your contract in contract.prisma, prompt your agent to run prisma-next migration plan, then ship your app with prisma-next migrate" metaImagePath: "/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/prisma-next-ltree-extension/index.mdx b/apps/blog/content/blog/prisma-next-ltree-extension/index.mdx index a36aa9faed8..28f5811c6a1 100644 --- a/apps/blog/content/blog/prisma-next-ltree-extension/index.mdx +++ b/apps/blog/content/blog/prisma-next-ltree-extension/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Extending Prisma 8 with Typed Postgres ltree" metaDescription: "Use PostgreSQL ltree in Prisma 8 with prisma-ltree: typed path columns plus ancestor and descendant queries." heroImagePath: "/prisma-next-ltree-extension/imgs/hero.svg" -heroImageAlt: "Typed ltree for Prisma 8: the prisma-ltree extension pack shown as a hierarchical path tree" +heroImageAlt: "A typed ltree path tree on a light card: essays branches into essays.drafts and essays.published, each with a chapter leaf, above the isDescendantOf operator" metaImagePath: "/prisma-next-ltree-extension/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/prisma-next-performance-benchmark/index.mdx b/apps/blog/content/blog/prisma-next-performance-benchmark/index.mdx index da25a35eaae..6151e5ae506 100644 --- a/apps/blog/content/blog/prisma-next-performance-benchmark/index.mdx +++ b/apps/blog/content/blog/prisma-next-performance-benchmark/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Prisma 8 Is ~90% As Fast as Raw PG" metaDescription: "Prisma 8 performance benchmarks achieves ~90% of the raw pg driver's peak throughput, holds latency low under load, and ships as a 148.5 KB gzipped bundle for serverless and edge workloads." heroImagePath: "/prisma-next-performance-benchmark/imgs/hero.svg" -heroImageAlt: "Bar chart showing Prisma 8 outperforming Prisma 7 in throughput benchmarks" +heroImageAlt: "Peak sustained throughput bars on the same Postgres workload: the raw pg driver at 14,350 requests per second, Prisma 8 at 12,500, Prisma 7 at 8,300" metaImagePath: "/prisma-next-performance-benchmark/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx b/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx index d6e7ea92742..d1249ad8951 100644 --- a/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx +++ b/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx @@ -7,6 +7,7 @@ authors: metaTitle: "Prisma 8: April milestone complete, the extension API is open" metaDescription: "April shipped the first four extensions on the new Prisma 8 extension API: pgvector, arktype-json, ParadeDB, and CipherStash. The extension API is open to outside authors. May shifts to Early Access." heroImagePath: "/prisma-next-roadmap-april-milestone/imgs/hero.svg" +heroImageAlt: "A milestone panel: pgvector, arktype-json, ParadeDB and CipherStash checked off as shipped in April, with streaming subscriptions in a dashed card carried into May" metaImagePath: "/prisma-next-roadmap-april-milestone/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/prisma-next-roadmap/index.mdx b/apps/blog/content/blog/prisma-next-roadmap/index.mdx index 89eec2b06a9..d48b080d436 100644 --- a/apps/blog/content/blog/prisma-next-roadmap/index.mdx +++ b/apps/blog/content/blog/prisma-next-roadmap/index.mdx @@ -6,7 +6,8 @@ authors: - "Will Madden" metaTitle: "Prisma 8 Roadmap" metaDescription: "Have you been wondering when you can start using Prisma 8 in your app? Take a look at our roadmap to find out." -heroImagePath: "/prisma-next-roadmap/imgs/hero.png" +heroImagePath: "/prisma-next-roadmap/imgs/hero.svg" +heroImageAlt: "A horizontal milestone track with three nodes: April for external contributions, May for early access, and June to July for Postgres general availability" metaImagePath: "/prisma-next-roadmap/imgs/meta.png" tags: - "orm" diff --git a/apps/blog/content/blog/prisma-orm-7-3-0/index.mdx b/apps/blog/content/blog/prisma-orm-7-3-0/index.mdx index 7e70cbdef0a..c683d6dba57 100644 --- a/apps/blog/content/blog/prisma-orm-7-3-0/index.mdx +++ b/apps/blog/content/blog/prisma-orm-7-3-0/index.mdx @@ -6,7 +6,9 @@ authors: - "Mike Hartington" metaTitle: "Prisma ORM 7.3.0: Faster Query Compilation, Safer BigInt JSON, Better Adapters" metaDescription: "Prisma ORM 7.3.0 adds a new compilerBuild option (fast or small), speeds up raw queries by bypassing compilation, improves MSSQL and better-sqlite3 stability, reverts mapped enum behavior, and preserves BigInt precision in relationJoins JSON aggregation." -heroImagePath: "/prisma-orm-7-3-0/imgs/hero-e84b7eb35dc73daddb55d22bb7a24b71f40d3d5d-844x474-552f491d83.svg" +metaImagePath: "/prisma-orm-7-3-0/imgs/meta.png" +heroImagePath: "/prisma-orm-7-3-0/imgs/hero.svg" +heroImageAlt: "A Prisma ORM 7.3.0 version badge beside four changelog items: the new compilerBuild generator option, raw queries skipping the compiler, the MSSQL adapter on version 12.2.0, and BigInt precision preserved in relationJoins JSON aggregation." tags: - "orm" --- diff --git a/apps/blog/content/blog/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/index.mdx b/apps/blog/content/blog/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/index.mdx index b0cbf869f07..6697909b9c3 100644 --- a/apps/blog/content/blog/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/index.mdx +++ b/apps/blog/content/blog/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/index.mdx @@ -6,8 +6,9 @@ authors: - "Mike Hartington" metaTitle: "Prisma ORM v7.4: Query Caching & Performance Boost" metaDescription: "Prisma ORM v7.4 introduces query caching, partial indexes, and BigInt precision fixes—delivering significant performance improvements under load." -metaImagePath: "/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta-e94d09878c3f2ac3e105a920dea3556ac0f9917a-1688x948-a991da7a72.png" -heroImagePath: "/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero-fef1bbb68459cebeece803f612fd0b95571d3d57-844x474-c0e399ac58.png" +metaImagePath: "/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta.png" +heroImagePath: "/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero.svg" +heroImageAlt: "A Prisma ORM 7.4 release card with three named rows: query caching highlighted in cyan, with per-query compilation cost falling from 0.1-1ms to 1-10 microseconds, partial indexes behind the partialIndexes preview feature, and a typical cache hit rate near 100 percent." tags: - "orm" --- diff --git a/apps/blog/content/blog/prisma-postgres-on-stripe-projects/index.mdx b/apps/blog/content/blog/prisma-postgres-on-stripe-projects/index.mdx index 82f2e81f4dc..c47e405f1f5 100644 --- a/apps/blog/content/blog/prisma-postgres-on-stripe-projects/index.mdx +++ b/apps/blog/content/blog/prisma-postgres-on-stripe-projects/index.mdx @@ -6,8 +6,8 @@ authors: - "Sampo Lahtinen" metaTitle: "Prisma Postgres on Stripe Projects" metaDescription: "Add a Prisma Postgres database to your Stripe project with one command: spending limits out of the box, plan changes from the CLI you already use." -heroImagePath: "/prisma-postgres-on-stripe-projects/imgs/hero.png" -heroImageAlt: "Prisma Postgres on Stripe Projects" +heroImagePath: "/prisma-postgres-on-stripe-projects/imgs/hero.svg" +heroImageAlt: "A Stripe Projects provider card for prisma/database, provisioned and ready on the free plan, beside the starter, pro and business plan prices" metaImagePath: "/prisma-postgres-on-stripe-projects/imgs/meta.png" tags: - "announcement" diff --git a/apps/blog/content/blog/prisma-postgres-vs-neon-pricing-2026/index.mdx b/apps/blog/content/blog/prisma-postgres-vs-neon-pricing-2026/index.mdx index 8b414a3a3fb..2d42d76b328 100644 --- a/apps/blog/content/blog/prisma-postgres-vs-neon-pricing-2026/index.mdx +++ b/apps/blog/content/blog/prisma-postgres-vs-neon-pricing-2026/index.mdx @@ -9,7 +9,7 @@ metaTitle: "Prisma Postgres vs Neon Pricing 2026: Tables + Worked Examples" metaDescription: "Prisma Postgres vs Neon pricing side by side: per-plan tables with exact unit prices, five worked cost examples with reproducible math, and a worksheet for your own workload." heroImagePath: "/prisma-postgres-vs-neon-pricing-2026/imgs/hero.svg" metaImagePath: "/prisma-postgres-vs-neon-pricing-2026/imgs/meta.png" -heroImageAlt: "Prisma Postgres vs Neon Pricing 2026" +heroImageAlt: "A table comparing Prisma Postgres and Neon on billing unit, free tier, paid entry and top plan, using the published plan prices from the post." tags: - "education" --- diff --git a/apps/blog/content/blog/prisma-schema-as-llm-context/index.mdx b/apps/blog/content/blog/prisma-schema-as-llm-context/index.mdx index 34d08e4d4fc..7f8d1fb2795 100644 --- a/apps/blog/content/blog/prisma-schema-as-llm-context/index.mdx +++ b/apps/blog/content/blog/prisma-schema-as-llm-context/index.mdx @@ -102,9 +102,9 @@ You can test the qualitative half on your own project in five minutes. Give your All three are answerable from the schema plus the ORM's documented defaults, including the trap in the first: `Invoice.organization` declares no `onDelete`, and Prisma's default for a required relation is `Restrict`, so an organization with invoices cannot be deleted at all. To be clear about what this test shows: a single-file Drizzle schema passes it too. It separates agents that have the data model in context from agents reconstructing it from application code; the sections above are about what that context costs. -## Prisma Next treats schema-as-context as a feature +## Prisma 8 treats schema-as-context as a feature -[Prisma Next](https://www.prisma.io/docs/orm/next), the next generation of the ORM currently in early access, makes this a design goal rather than a side effect: the schema stays small, dense, and machine-readable, treated as first-class LLM context rather than an implementation detail, and errors are structured for agent consumption, carrying documentation URLs that resolve to a stable reference for the exact error. +[Prisma 8](https://www.prisma.io/docs/orm/v8), the next generation of the ORM currently in release candidate, makes this a design goal rather than a side effect: the schema stays small, dense, and machine-readable, treated as first-class LLM context rather than an implementation detail, and errors are structured for agent consumption, carrying documentation URLs that resolve to a stable reference for the exact error. The schema answers "what is the data model." The other half, "how do we change it safely here," belongs in your agent rules file; we covered a copy-pasteable version in [What to Put in Your AGENTS.md](/agents-md-for-databases). diff --git a/apps/blog/content/blog/prisma-studio-migrations-view/index.mdx b/apps/blog/content/blog/prisma-studio-migrations-view/index.mdx index 370b9bf395f..ca09212e72d 100644 --- a/apps/blog/content/blog/prisma-studio-migrations-view/index.mdx +++ b/apps/blog/content/blog/prisma-studio-migrations-view/index.mdx @@ -9,7 +9,7 @@ metaTitle: "Prisma Studio Migrations View: See Your Migration History" metaDescription: "The Prisma Studio Migrations view shows every applied Prisma 8 migration as a timeline with a visual diff, the executed SQL, and a schema diff." heroImagePath: "/prisma-studio-migrations-view/imgs/hero.svg" metaImagePath: "/prisma-studio-migrations-view/imgs/meta.png" -heroImageAlt: "The Prisma Studio Migrations view: a timeline of applied migrations beside a visual diff canvas" +heroImageAlt: "The Prisma Studio Migrations panel listing six applied migrations newest first, with the destructive Drop Legacy Username entry selected" tags: - "announcement" - "orm" diff --git a/apps/blog/content/blog/rebuilding-the-prisma-docs/index.mdx b/apps/blog/content/blog/rebuilding-the-prisma-docs/index.mdx index 3b005cfcc70..ce81f70186a 100644 --- a/apps/blog/content/blog/rebuilding-the-prisma-docs/index.mdx +++ b/apps/blog/content/blog/rebuilding-the-prisma-docs/index.mdx @@ -8,8 +8,8 @@ authors: metaTitle: "Rebuilding the Prisma Docs: A New Framework, Design, and Structure" metaDescription: "Learn how the Prisma team rebuilt their docs from scratch using Fumadocs, improved search with Mixedbread, and launched without disrupting day-to-day work." metaImagePath: "/rebuilding-the-prisma-docs/imgs/meta.png" -heroImagePath: "/rebuilding-the-prisma-docs/imgs/hero.png" -heroImageAlt: "Image of the new Prisma documentation site showing the redesigned navigation and layout" +heroImagePath: "/rebuilding-the-prisma-docs/imgs/hero.svg" +heroImageAlt: "An information architecture drawing of the rebuilt Prisma docs: a versioned entry point serving /docs and /docs/v6, branching into the four top-level sections Getting Started, ORM, Prisma Postgres, and Guides." tags: - "education" - "announcement" diff --git a/apps/blog/content/blog/rethinking-database-migrations/index.mdx b/apps/blog/content/blog/rethinking-database-migrations/index.mdx index b4cc5dc62b2..848ebd728f6 100644 --- a/apps/blog/content/blog/rethinking-database-migrations/index.mdx +++ b/apps/blog/content/blog/rethinking-database-migrations/index.mdx @@ -9,7 +9,7 @@ metaTitle: "Rethinking Database Migrations" metaDescription: "Database migrations are brittle and they break when you're most vulnerable; when you're deploying to production. Prisma 8 migrations make them explicit, verifiable and safe to retry." metaImagePath: "/rethinking-database-migrations/imgs/meta.png" heroImagePath: "/rethinking-database-migrations/imgs/hero.svg" -heroImageAlt: "Rethinking Database Migrations" +heroImageAlt: "A migration history graph: an empty database leads to abc123 createTable(user), which branches to def456 addColumn(user.email) and on to the ghi789 target" tags: - "orm" series: prisma-next diff --git a/apps/blog/content/blog/search-prisma-docs-from-your-coding-agent/index.mdx b/apps/blog/content/blog/search-prisma-docs-from-your-coding-agent/index.mdx index 43cfbc9e1ac..27fca707e1e 100644 --- a/apps/blog/content/blog/search-prisma-docs-from-your-coding-agent/index.mdx +++ b/apps/blog/content/blog/search-prisma-docs-from-your-coding-agent/index.mdx @@ -6,8 +6,8 @@ authors: - "Ankur Datta" metaTitle: "Search the Prisma Docs Using Your Coding Agent" metaDescription: "The Prisma MCP server now answers documentation questions in your editor. Ask about ORM, Postgres, or Compute and get a cited answer, no tab-switching, no extra setup." -heroImagePath: "/search-prisma-docs-from-your-coding-agent/imgs/hero.png" -heroImageAlt: "Your coding agent can now search the Prisma docs" +heroImagePath: "/search-prisma-docs-from-your-coding-agent/imgs/hero.svg" +heroImageAlt: "A docs search panel for the search_prisma_documentation tool: one question about deploying to Prisma Compute, and the docs pages its cited answer comes from" metaImagePath: "/search-prisma-docs-from-your-coding-agent/imgs/meta.png" tags: - "ai" diff --git a/apps/blog/content/blog/serverless-postgres/index.mdx b/apps/blog/content/blog/serverless-postgres/index.mdx index 252e65558af..a01692736a6 100644 --- a/apps/blog/content/blog/serverless-postgres/index.mdx +++ b/apps/blog/content/blog/serverless-postgres/index.mdx @@ -11,7 +11,7 @@ metaTitle: "Serverless Postgres: How It Works and Who Offers It (2026)" metaDescription: "Serverless Postgres separates compute from storage and bills for usage instead of provisioned servers. How scale-to-zero, cold starts, and the three pricing models compare across Neon, Prisma Postgres, Supabase, Aurora, and PlanetScale." metaImagePath: "/serverless-postgres/imgs/meta.png" heroImagePath: "/serverless-postgres/imgs/hero.svg" -heroImageAlt: "Serverless Postgres providers compared: logos for Prisma Postgres, Neon, Aurora, Supabase, and PlanetScale grouped by the three pricing models — operations, compute-time, and instances. Prisma wordmark top-right." +heroImageAlt: "A compute usage curve that suspends after five minutes idle and wakes a few hundred milliseconds later, drawn under a flat always ready line." --- Serverless Postgres is PostgreSQL you never provision or manage: the platform allocates compute on demand and bills you for usage, not for a server size you picked up front. One label, though, covers very different products, and they differ on two things that decide your cost and your latency: **what they bill for**, and **whether compute sleeps when idle**. diff --git a/apps/blog/content/blog/ship-risky-schema-changes-without-a-shared-staging-database/index.mdx b/apps/blog/content/blog/ship-risky-schema-changes-without-a-shared-staging-database/index.mdx index 621d9b38ff4..03ada96366a 100644 --- a/apps/blog/content/blog/ship-risky-schema-changes-without-a-shared-staging-database/index.mdx +++ b/apps/blog/content/blog/ship-risky-schema-changes-without-a-shared-staging-database/index.mdx @@ -9,7 +9,7 @@ draft: true metaTitle: "Ship risky schema changes with per-branch databases" metaDescription: "Prisma Compute gives every branch its own Prisma Postgres database. Rehearse expand-and-contract migrations in isolation before they touch production." heroImagePath: "/ship-risky-schema-changes-without-a-shared-staging-database/imgs/hero.svg" -heroImageAlt: "Per-branch databases let each pull request run its own migrations in isolation" +heroImageAlt: "Two branches fork off main into separate branch databases, one adding the displayName column and one dropping the legacy name column" metaImagePath: "/ship-risky-schema-changes-without-a-shared-staging-database/imgs/meta.png" tags: - "platform" diff --git a/apps/blog/content/blog/sunsetting-prisma-optimize/index.mdx b/apps/blog/content/blog/sunsetting-prisma-optimize/index.mdx index ba39fec3c8c..d6ca4ed3a64 100644 --- a/apps/blog/content/blog/sunsetting-prisma-optimize/index.mdx +++ b/apps/blog/content/blog/sunsetting-prisma-optimize/index.mdx @@ -6,8 +6,9 @@ authors: - "Mike Hartington" metaTitle: "Sunsetting Prisma Optimize" metaDescription: "Prisma Optimize is being sunset as we move query observability directly into Prisma Postgres through Query Insights." -heroImagePath: "/sunsetting-prisma-optimize/imgs/optimize-sunset.svg" -metaImagePath: "/sunsetting-prisma-optimize/imgs/optimize-sunset@2x.png" +heroImagePath: "/sunsetting-prisma-optimize/imgs/hero.svg" +metaImagePath: "/sunsetting-prisma-optimize/imgs/meta.png" +heroImageAlt: "A dated wind-down notice: the Prisma Optimize client extension gives way to Query Insights in Prisma Postgres, with the command that removes the old package" tags: - "announcement" - "prisma-postgres" diff --git a/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx b/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx index 700c3809084..91b763c14f7 100644 --- a/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx +++ b/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx @@ -7,9 +7,9 @@ authors: - "Ankur Datta" metaTitle: "The Next Evolution of Prisma ORM" metaDescription: "A look at Prisma 8, a ground-up rethink of Prisma that improves queries, extensibility, migrations, and AI-friendly workflows while keeping Prisma’s schema-first approach." -metaImagePath: "/the-next-evolution-of-prisma-orm/imgs/meta-558fe7eccfd12d3b52c325d62e5fa463a1b5f619-1200x640-3212708663.png" -heroImagePath: "/the-next-evolution-of-prisma-orm/imgs/hero-61773d2cc286213d32b63e59605b0f5e0df4fe52-844x474-cb41e2fab7.svg" -heroImageAlt: "The Next Evolution of Prisma ORM" +metaImagePath: "/the-next-evolution-of-prisma-orm/imgs/meta.png" +heroImagePath: "/the-next-evolution-of-prisma-orm/imgs/hero.svg" +heroImageAlt: "A lineage of three Prisma ORM generations: Prisma 6 shipping Rust native binaries, Prisma 7 with the query system rewritten, and Prisma 8 stepped up and outlined in cyan, rebuilt in TypeScript and extensible by default." tags: - "orm" series: prisma-next diff --git a/apps/blog/content/blog/typescript-7-native-compiler-faster-type-checking/index.mdx b/apps/blog/content/blog/typescript-7-native-compiler-faster-type-checking/index.mdx index b114ddac35f..f2827b33bee 100644 --- a/apps/blog/content/blog/typescript-7-native-compiler-faster-type-checking/index.mdx +++ b/apps/blog/content/blog/typescript-7-native-compiler-faster-type-checking/index.mdx @@ -9,7 +9,7 @@ metaTitle: "TypeScript 7 Native Compiler: 3x Faster Type Checks in a Real Monore metaDescription: "TypeScript 7 ships the compiler as a native Go port. We migrated a large TypeScript monorepo to it: whole-repo type checking went from ~74s to ~24s with no memory tuning. Here are the numbers, the exact config diffs, the sharp edges, and who should migrate now." metaImagePath: "/typescript-7-native-compiler-faster-type-checking/imgs/meta.png" heroImagePath: "/typescript-7-native-compiler-faster-type-checking/imgs/hero.svg" -heroImageAlt: "Headline 'Type checking, 3x faster' beside a before/after bar chart: a tall slate bar labeled TS 5.x at 74 seconds and a short glowing blue bar labeled TS 7 at 24 seconds, with a '3x faster' callout. TypeScript logo top-left, Prisma wordmark top-right." +heroImageAlt: "Two proportional bars comparing a whole-repo type check: tsc 5.8.2, the classic compiler, at about 74 seconds in grey, and tsc 7.0.2, the native Go compiler, at about 24 seconds in cyan with a 3x faster pill, above a note that the Node heap flag went from 8 GB to none." tags: - "education" - "platform" diff --git a/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx b/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx index 84c9ee22ced..1b6e266ac75 100644 --- a/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx +++ b/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx @@ -7,9 +7,9 @@ authors: - "Ankur Datta" metaTitle: "TypeScript Migrations in Prisma 8" metaDescription: "In Prisma 8, migrations are TypeScript files you can read, edit, and re-run with confidence. Every step is verified before it runs and again after, and every failure points directly at the operation that caused it." -heroImagePath: "/typescript-migrations-in-prisma-next/imgs/typescript-migrations-in-prisma-next.png" -metaImagePath: "/typescript-migrations-in-prisma-next/imgs/typescript-migrations-in-prisma-next.png" -heroImageAlt: "TypeScript Migrations In Prisma 8" +heroImagePath: "/typescript-migrations-in-prisma-next/imgs/hero.svg" +metaImagePath: "/typescript-migrations-in-prisma-next/imgs/meta.png" +heroImageAlt: "A dark migration.ts code card showing the createTable, addUnique and createIndex operation factories that a Prisma 8 migration is built from" tags: - "orm" - "education" diff --git a/apps/blog/content/blog/you-dont-need-a-job-queue-postgres-already-has-skip-locked/index.mdx b/apps/blog/content/blog/you-dont-need-a-job-queue-postgres-already-has-skip-locked/index.mdx index 3c4b056460c..87c4b812e5f 100644 --- a/apps/blog/content/blog/you-dont-need-a-job-queue-postgres-already-has-skip-locked/index.mdx +++ b/apps/blog/content/blog/you-dont-need-a-job-queue-postgres-already-has-skip-locked/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Build a Postgres Job Queue with SKIP LOCKED, No Redis" metaDescription: "Postgres can run a reliable background job queue with FOR UPDATE SKIP LOCKED. Build a worker queue with retries using pg and Prisma Postgres, no broker required." heroImagePath: "/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/hero.svg" -heroImageAlt: "You Don't Need a Job Queue, Postgres Already Has SKIP LOCKED" +heroImageAlt: "A dark SQL card holding the post's claim query, with FOR UPDATE SKIP LOCKED highlighted in yellow, beside the line 'The job queue is a table'." metaImagePath: "/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/meta.png" tags: - "prisma-postgres" diff --git a/apps/blog/content/blog/you-dont-need-a-vector-database-postgres-already-has-pgvector/index.mdx b/apps/blog/content/blog/you-dont-need-a-vector-database-postgres-already-has-pgvector/index.mdx index 0b00a922c09..84c6d6ba44d 100644 --- a/apps/blog/content/blog/you-dont-need-a-vector-database-postgres-already-has-pgvector/index.mdx +++ b/apps/blog/content/blog/you-dont-need-a-vector-database-postgres-already-has-pgvector/index.mdx @@ -8,7 +8,7 @@ metaTitle: "You Don't Need a Vector Database, Postgres Already Has pgvector" metaDescription: "pgvector turns Postgres into a vector store; Prisma 8 makes it type-safe. Build working semantic search on a temporary Prisma Postgres database in minutes." heroImagePath: "/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/hero.svg" metaImagePath: "/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/meta.png" -heroImageAlt: "You Don't Need a Vector Database, Postgres Already Has pgvector" +heroImageAlt: "The post's movie vectors plotted on the action and scifi axes, with The Terminator highlighted and lines drawn to its nearest neighbours." tags: - "prisma-postgres" - "education" diff --git a/apps/blog/content/blog/you-dont-need-elasticsearch-postgres-already-has-full-text-search/index.mdx b/apps/blog/content/blog/you-dont-need-elasticsearch-postgres-already-has-full-text-search/index.mdx index 1f699a22504..b5347c091d2 100644 --- a/apps/blog/content/blog/you-dont-need-elasticsearch-postgres-already-has-full-text-search/index.mdx +++ b/apps/blog/content/blog/you-dont-need-elasticsearch-postgres-already-has-full-text-search/index.mdx @@ -7,7 +7,7 @@ authors: metaTitle: "Postgres Full-Text Search Instead of Elasticsearch" metaDescription: "Build full-text search with tsvector, GIN indexes, and pg_trgm typo tolerance on Prisma Postgres. For most apps, no Elasticsearch cluster required." heroImagePath: "/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/hero.svg" -heroImageAlt: "You Don't Need Elasticsearch, Postgres Already Has Full-Text Search" +heroImageAlt: "A struck-out Elasticsearch tile above a highlighted Postgres tile labelled tsvector plus GIN index, beside the line 'The search index is a column'." metaImagePath: "/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/meta.png" tags: - "prisma-postgres" diff --git a/apps/blog/content/blog/you-dont-need-redis-postgres-already-has-pub-sub/index.mdx b/apps/blog/content/blog/you-dont-need-redis-postgres-already-has-pub-sub/index.mdx index 6bae207c84b..4798534bb62 100644 --- a/apps/blog/content/blog/you-dont-need-redis-postgres-already-has-pub-sub/index.mdx +++ b/apps/blog/content/blog/you-dont-need-redis-postgres-already-has-pub-sub/index.mdx @@ -6,9 +6,9 @@ authors: - "Ankur Datta" metaTitle: "You Don't Need Redis, Postgres Already Has Pub/Sub" metaDescription: "Postgres includes a lightweight Pub/Sub mechanism through LISTEN and NOTIFY. In this post, you'll build a small real-time Pub/Sub app with Bun, pg, and Prisma Postgres." -heroImagePath: "/you-dont-need-redis-postgres-already-has-pub-sub/imgs/you-dont-need-redis-postgres-already-has-pub-sub.png" -metaImagePath: "/you-dont-need-redis-postgres-already-has-pub-sub/imgs/you-dont-need-redis-postgres-already-has-pub-sub.png" -heroImageAlt: "You Don't Need Redis, Postgres Already Has Pub/Sub" +heroImagePath: "/you-dont-need-redis-postgres-already-has-pub-sub/imgs/hero.svg" +metaImagePath: "/you-dont-need-redis-postgres-already-has-pub-sub/imgs/meta.png" +heroImageAlt: "A publisher running NOTIFY app_events, fanning out through the app_events channel to two subscribers running LISTEN app_events." tags: - "education" series: postgres-features diff --git a/apps/blog/content/blog/your-database-might-not-be-the-bottleneck/index.mdx b/apps/blog/content/blog/your-database-might-not-be-the-bottleneck/index.mdx index 9deaf797262..89d09efdac7 100644 --- a/apps/blog/content/blog/your-database-might-not-be-the-bottleneck/index.mdx +++ b/apps/blog/content/blog/your-database-might-not-be-the-bottleneck/index.mdx @@ -7,7 +7,8 @@ authors: metaTitle: "Your Database Might Not Be the Bottleneck" metaDescription: "Slow APIs are not always a database problem. Here’s how request parsing, middleware, and repeated object work can become the real bottleneck before Postgres is even involved." metaImagePath: "/your-database-might-not-be-the-bottleneck/imgs/meta.png" -heroImagePath: "/your-database-might-not-be-the-bottleneck/imgs/hero.jpg" +heroImagePath: "/your-database-might-not-be-the-bottleneck/imgs/hero.svg" +heroImageAlt: "Request composition bars for the post's slow and fast apps: the query segment is the same size in both, while the slow bar fills with middleware, URL parsing and serialization." --- When an API feels slow, the database is usually the first thing people blame. That makes sense because databases often do the most expensive work in the stack: filtering, joins, sorting, counts, pagination, and serialization. If a route suddenly takes 400ms, most people immediately start looking for missing indexes. diff --git a/apps/blog/next.config.mjs b/apps/blog/next.config.mjs index 87446f7dc1c..a6a338b1783 100644 --- a/apps/blog/next.config.mjs +++ b/apps/blog/next.config.mjs @@ -201,9 +201,7 @@ const securityHeaders = [ }, ]; -const allowedDevOrigins = ( - process.env.ALLOWED_DEV_ORIGINS ?? "localhost,127.0.0.1,192.168.1.48" -) +const allowedDevOrigins = (process.env.ALLOWED_DEV_ORIGINS ?? "localhost,127.0.0.1,192.168.1.48") .split(",") .map((origin) => origin.trim()) .filter(Boolean); diff --git a/apps/blog/public/agentic-engineering-at-prisma/imgs/hero.png b/apps/blog/public/agentic-engineering-at-prisma/imgs/hero.png deleted file mode 100644 index 621f47d8fb9..00000000000 Binary files a/apps/blog/public/agentic-engineering-at-prisma/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/agentic-engineering-at-prisma/imgs/hero.svg b/apps/blog/public/agentic-engineering-at-prisma/imgs/hero.svg new file mode 100644 index 00000000000..2a4e87919af --- /dev/null +++ b/apps/blog/public/agentic-engineering-at-prisma/imgs/hero.svg @@ -0,0 +1,79 @@ + + Agentic Engineering at Prisma + The five Drive hand-off stages as a rail: Plan, Execute, Review, Ship and Delivery review, with the agent-owned Execute stage marked in prism cyan. Prisma blog cover, 2026 brand. + + + + + + + + + + + + + + + + + + + + + + + + + + + Drive, the project lifecycle + + + + + Not the code, + everything around it + + + + + + + Plan + + Execute + + Review + + Ship + + Delivery review + + + + + + + + Engineers direct, agents execute, engineers validate. + + + + + + + + + + + + + + diff --git a/apps/blog/public/agentic-engineering-at-prisma/imgs/meta.png b/apps/blog/public/agentic-engineering-at-prisma/imgs/meta.png index 4350e3dff96..f1b054d89ee 100644 Binary files a/apps/blog/public/agentic-engineering-at-prisma/imgs/meta.png and b/apps/blog/public/agentic-engineering-at-prisma/imgs/meta.png differ diff --git a/apps/blog/public/agents-md-for-databases/imgs/hero.svg b/apps/blog/public/agents-md-for-databases/imgs/hero.svg index ecc56918bc6..4be82439e62 100644 --- a/apps/blog/public/agents-md-for-databases/imgs/hero.svg +++ b/apps/blog/public/agents-md-for-databases/imgs/hero.svg @@ -1,69 +1,63 @@ - - - - What to Put in Your AGENTS.md So Your Agent Handles the Database Right - An AGENTS.md file card listing five database rules, feeding Claude Code, Cursor, and Codex. + + What to Put in Your AGENTS.md So Your Agent Handles the Database Right + An ink code card with an AGENTS.md filename tab holding the post's five database rules, with the npx create-db@latest --json line marked in prism yellow. Prisma blog cover, 2026 brand. - - - - - - - + + + + + + + + + + + + - - - - - - - - AGENTS.MD - - Database rules - for your - coding agent - + + + + - - - AGENTS.md - - ## Database rules - - scratch work: npx create-db --json - - never migrate reset without asking - - rehearse migrations on a throwaway db - - prefer --json output, parse the fields - - DATABASE_URL from env, never committed - + + + Agent rules for database work - - - - - - - - Claude Code - via @AGENTS.md - Cursor - native - Codex - native + + + + AGENTS.md + ## Database rules + - Scratch work gets a throwaway database: + npx create-db@latest --json + - Never reset or drop without my confirmation. + - Rehearse migrations on a throwaway first. + - Prefer --json output when a CLI offers it. + - Keep connection strings in the environment. - - Prisma + + + + + + + + + + diff --git a/apps/blog/public/agents-md-for-databases/imgs/meta.png b/apps/blog/public/agents-md-for-databases/imgs/meta.png index da9388df59c..c774d2996f4 100644 Binary files a/apps/blog/public/agents-md-for-databases/imgs/meta.png and b/apps/blog/public/agents-md-for-databases/imgs/meta.png differ diff --git a/apps/blog/public/announcing-query-insights-for-prisma-postgres/announcing-query-insights-for-prisma-postgres-og.png b/apps/blog/public/announcing-query-insights-for-prisma-postgres/announcing-query-insights-for-prisma-postgres-og.png deleted file mode 100644 index fc0adc707e3..00000000000 Binary files a/apps/blog/public/announcing-query-insights-for-prisma-postgres/announcing-query-insights-for-prisma-postgres-og.png and /dev/null differ diff --git a/apps/blog/public/announcing-query-insights-for-prisma-postgres/imgs/hero.svg b/apps/blog/public/announcing-query-insights-for-prisma-postgres/imgs/hero.svg new file mode 100644 index 00000000000..b9db22be609 --- /dev/null +++ b/apps/blog/public/announcing-query-insights-for-prisma-postgres/imgs/hero.svg @@ -0,0 +1,149 @@ + + Announcing Query Insights For Prisma Postgres + The Queries tab of a Prisma Postgres database as a full width panel: average latency and queries per second, a latency chart, and four grouped query shapes with their execution and read counts, the expensive aggregate highlighted. Prisma blog cover, 2026 brand, prism yellow accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Average latency + 391 + ms + + Queries per second + 43.3 + + + Queries + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Latency + Executions + Reads + + + + + + + + + 0ms + SELECT name, species, age FROM pets ORDER BY age DESC LIMIT $1 + 156 + 156 + + + slow + SELECT COUNT(*)::int AS rows_scanned, AVG(p.age + n)::numeric(10,2)… + 156 + 156 + + + 0ms + INSERT INTO pets (name, species, age) VALUES ($1, $2, $3), ($4, $5… + 1 + 55 + + + 0ms + SELECT name, species, age FROM pets WHERE age > (SELECT AVG(age)… + 13 + 26 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/announcing-query-insights-for-prisma-postgres/imgs/meta.png b/apps/blog/public/announcing-query-insights-for-prisma-postgres/imgs/meta.png new file mode 100644 index 00000000000..b732c16149d Binary files /dev/null and b/apps/blog/public/announcing-query-insights-for-prisma-postgres/imgs/meta.png differ diff --git a/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/hero.svg b/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/hero.svg index bd01b366521..086570dc33d 100644 --- a/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/hero.svg +++ b/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/hero.svg @@ -1,498 +1,119 @@ - -
Field Guide · 2026

App hosting &
compute for
AI agents

Prisma Compute
TypeScript hosting next to Postgres
Public beta · Jun 2026
H
Hosting.com
One-click AI app hosting
Mar 2026
C
Cloudflare Containers
Docker on the global edge
GA · Apr 2026
U
Unkey Deploy
Dockerfile → production API
Apr 2026
N
Neon Compute
Instant, branchable backend
Jun 2026
I
Insforge
Agent-native open-source backend
Early-stage
Prisma
\ No newline at end of file + + App Hosting and Compute Platforms for AI Agents in 2026 + An evaluation matrix of the six platforms in the field guide, set as printed index rows: when each shipped, whether a database comes with it, and whether the stack is integrated. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Field guide, 2026 + + + + + + Platform + Shipped + Database + Integrated stack + + + + + + + + + + + + + + + Prisma Compute + Neon Compute + Cloudflare Containers + Hosting.com + Unkey Deploy + Insforge + + + + June 2026 + June 2026 + 13 April 2026 + March 2026 + April 2026 + 2026, early stage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/meta.png b/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/meta.png index 296ebc2573c..320779ece92 100644 Binary files a/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/meta.png and b/apps/blog/public/app-hosting-compute-platforms-for-ai-agents-2026/imgs/meta.png differ diff --git a/apps/blog/public/building-open-chat/imgs/hero.svg b/apps/blog/public/building-open-chat/imgs/hero.svg index 589b83a741a..bd3033d1020 100644 --- a/apps/blog/public/building-open-chat/imgs/hero.svg +++ b/apps/blog/public/building-open-chat/imgs/hero.svg @@ -1,471 +1,84 @@ - -
Open Chat /
Durable Streaming

Chat that
never
drops a
token

Durable log backed
streaming
DURABLE LOGhead · offset 412
409message.created
410message.delta
411message.delta
412message.delta
SSE tailresumes at 412
client
Prisma
\ No newline at end of file + + How I Built a Chat App That Never Drops a Token + An append-only event log for one chat: message.created, message.delta and message.completed rows on a durable stream, with the live delta highlighted in prism red. Prisma blog cover, 2026 brand, prism red Compute accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Durable, resumable chat + + + + Nothing on screen that isn’t durable + + + + + + POST /v1/stream/u_3f9c…_messages + stream-key: chat:chat_38eb… + + + + + + message.createdrole: user"Tell me about cows!" + message.createdrole: assistant"" + message.deltarole: assistant"Cows are" + message.deltarole: assistant" fascinating" + message.completedoutputTokens: 312costMicroUsd: 9 + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/building-open-chat/imgs/meta.png b/apps/blog/public/building-open-chat/imgs/meta.png index 5cfe94ff0fa..93485db87de 100644 Binary files a/apps/blog/public/building-open-chat/imgs/meta.png and b/apps/blog/public/building-open-chat/imgs/meta.png differ diff --git a/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/hero.png b/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/hero.png deleted file mode 100644 index 57e6f427c2d..00000000000 Binary files a/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/hero.svg b/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/hero.svg new file mode 100644 index 00000000000..8855f5265c3 --- /dev/null +++ b/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/hero.svg @@ -0,0 +1,90 @@ + + We put Bun's Rust rewrite in production on Prisma Compute + Peak resident memory in the Bun.S3File.arrayBuffer() loop inside a 1 GiB container: stable 1.3.14 runs past the 900 MiB threshold and is OOM-killed, while the Rust rewrite canary stays flat at 118 MiB to 4096 iterations. Prisma blog cover, 2026 brand, prism red Compute accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bun canary in production + + + + The build that passed our tests + + + + + + Peak RSS · Bun.S3File.arrayBuffer() loop in a 1 GiB container + + + 1.3.14+0d9b296af + stable · OOM-killed at iteration 96 + over 900 MiB + + + + 1.3.14-canary.1+172afa532 + Rust rewrite · flat to 4096 iterations + 118 MiB + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/meta.png b/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/meta.png index f4acd8333c6..0975182e97a 100644 Binary files a/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/meta.png and b/apps/blog/public/bun-rust-rewrite-prisma-compute/imgs/meta.png differ diff --git a/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/hero.svg b/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/hero.svg index 14e7c8cae3a..77ccfa0e94c 100644 --- a/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/hero.svg +++ b/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/hero.svg @@ -1,55 +1,184 @@ - - - - Claude Generated 50 Websites Overnight. Prisma Compute Helped Ship Them. - A three-step pipeline: claude, then Prisma Compute, ending in live URLs, under the headline 50 websites overnight. + + Claude Generated 50 Websites Overnight. Prisma Compute Helped Ship Them. + Fifty small deployment tiles in a dense grid, one picked out in prism red, standing for the roughly 50 sites an agent generated overnight and deployed inside one Prisma app. Prisma blog cover, 2026 brand, prism red Compute accent. - - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + Deployed by an agent - - PRISMA COMPUTE CUSTOMER STORY - - 50 websites - overnight + + From generated code + to live URLs - Claude generated them. Prisma Compute helped ship them. + spas in Vancouver, overnight - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + ~50 sites · one Prisma app - claude - Prisma Compute - live URLs + + + + + + + + + + + + + + + + + - - Prisma diff --git a/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/meta.png b/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/meta.png index b027d5519cb..c714a518465 100644 Binary files a/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/meta.png and b/apps/blog/public/claude-generated-50-websites-overnight-prisma-compute/imgs/meta.png differ diff --git a/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/hero.svg b/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/hero.svg index 849731531ee..2a3b9246e64 100644 --- a/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/hero.svg +++ b/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/hero.svg @@ -1,498 +1,86 @@ - -
create-prisma

Scaffold a
deploy-ready
app

$ bun create prisma@stable
Choose template
Generate typed config
Add Postgres + Skills
Prisma
\ No newline at end of file + + Deploy Prisma Apps with create-prisma + An ink terminal card running bun create prisma@stable with a checklist of what the scaffold writes: prisma.compute.ts, Prisma Postgres, Prisma Skills, and a compute:deploy script. Prisma blog cover, 2026 brand, prism red Compute accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scaffolding with create-prisma + + + + + From nothing to + a live URL + + + One command scaffolds the app, + the database, and the deploy config. + + + + + + + $bun create prisma@stable + + + ✓prisma.compute.ts + ✓Prisma Postgres + ✓Prisma Skills + ✓compute:deploy script + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/meta.png b/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/meta.png index 76de40e8fa4..f04472f8b74 100644 Binary files a/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/meta.png and b/apps/blog/public/create-prisma-deploy-prisma-compute/imgs/meta.png differ diff --git a/apps/blog/public/data-migrations-in-prisma-next/imgs/hero.svg b/apps/blog/public/data-migrations-in-prisma-next/imgs/hero.svg index 6b37e31639d..533abdf4b6a 100644 --- a/apps/blog/public/data-migrations-in-prisma-next/imgs/hero.svg +++ b/apps/blog/public/data-migrations-in-prisma-next/imgs/hero.svg @@ -1 +1,84 @@ -PRISMA 8DataMigrations inPrisma 8 \ No newline at end of file + + Data Migrations in Prisma 8 + A migration flow with a dataTransform step between two schema states: addColumn leaves displayName nullable, the transform backfills it, then setNotNull makes it required. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma 8 data migrations + + + + + Backfill inside + the migration + + + + + + + addColumn + displayName nullable + + + + + dataTransform + check: displayName is null + run: set "Anonymous" + + + + + setNotNull + displayName NOT NULL + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/data-migrations-in-prisma-next/imgs/meta.png b/apps/blog/public/data-migrations-in-prisma-next/imgs/meta.png index a8b69538410..0a62fbf2353 100644 Binary files a/apps/blog/public/data-migrations-in-prisma-next/imgs/meta.png and b/apps/blog/public/data-migrations-in-prisma-next/imgs/meta.png differ diff --git a/apps/blog/public/drive-and-the-maker/imgs/hero.png b/apps/blog/public/drive-and-the-maker/imgs/hero.png deleted file mode 100644 index 059a2ed904d..00000000000 Binary files a/apps/blog/public/drive-and-the-maker/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/drive-and-the-maker/imgs/hero.svg b/apps/blog/public/drive-and-the-maker/imgs/hero.svg new file mode 100644 index 00000000000..11e6c2f3804 --- /dev/null +++ b/apps/blog/public/drive-and-the-maker/imgs/hero.svg @@ -0,0 +1,70 @@ + + Drive and the Maker + An editorial cover: a pulled line from the essay, that when routine implementation is cheap, coordination and ritual become the expensive things, set in large type on paper with a soft three color prism wash. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Agentic engineering + + + + + + When routine implementation is cheap, + coordination and ritual become + the expensive things. + + Drive, a development process where AI agents execute alongside people. + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/drive-and-the-maker/imgs/meta.png b/apps/blog/public/drive-and-the-maker/imgs/meta.png index f29e20b6ed1..f2243e78296 100644 Binary files a/apps/blog/public/drive-and-the-maker/imgs/meta.png and b/apps/blog/public/drive-and-the-maker/imgs/meta.png differ diff --git a/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/hero.svg b/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/hero.svg index 4809ddd038e..b9154e25a6b 100644 --- a/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/hero.svg +++ b/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/hero.svg @@ -1,59 +1,85 @@ - - - - Tigris finished about 3x faster than Cloudflare R2 on the accelerated-fs workload - Mixed read/write phase, 5 GiB dataset, averaged across six Prisma Compute regions. Cloudflare R2 finished in 861 seconds; Tigris finished in 266 seconds, about 3x faster. Lower is faster. + + Evaluating Object Storage Providers for Prisma Compute + An evaluation matrix of three object stores on the criteria that separated them: egress price, bucket model, and read median for 10 KiB reads from Frankfurt. Tigris is the highlighted row. Prisma blog cover, 2026 brand, prism red Compute accent, no headline. - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + - - OBJECT STORAGE ON PRISMA COMPUTE - - Tigris finished - ~3x faster - than Cloudflare R2 - - 5 GiB mixed read/write, averaged across six Prisma Compute regions + + + Object storage benchmark - - - - - - Cloudflare R2 - 861s - - - - - - Tigris - 266s - - + + + + + + Provider + Egress + Bucket model + Read median + + + + + + + Tigrisnoneone global bucket14-18 ms + Cloudflare R2noneone per region85 ms + AWS S3$0.09/GBone per region32 ms + + + 1,000 · 10 KiB reads from Frankfurt - Prisma + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/meta.png b/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/meta.png index 70ca9fdf2d6..2621fae91ec 100644 Binary files a/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/meta.png and b/apps/blog/public/evaluating-object-storage-providers-for-prisma-compute/imgs/meta.png differ diff --git a/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/hero.svg b/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/hero.svg index 8884508dbe7..abf8e054f4c 100644 --- a/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/hero.svg +++ b/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/hero.svg @@ -1,3 +1,96 @@ - - + + Evolving Agentic Engineering at Prisma + A before and after drawing: seven anonymous rows standing for the verbose skill layer a team ends up owning, beside three named contracts, spec, plan and execute, in prism cyan. Prisma blog cover, 2026 brand. + + + + + + + + + + + + + + + + + + + + + + + + + + + Agentic engineering, revisited + + + + + Not more process, more precise + + + + + A skill should define a contract, not narrate a process. + + + + + Opinionated skills + + process design + + skill wording + + model assumptions + + harness assumptions + + evaluation surface + + ongoing maintenance + + obsolescence risk + + Skills as interfaces + + spec + + + plan + + plan + + + milestone + + diff + + + review + + + + + + + + + + + + + diff --git a/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/meta.png b/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/meta.png index 762fb57976a..57bdfc34a10 100644 Binary files a/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/meta.png and b/apps/blog/public/evolving-agentic-engineering-at-prisma/imgs/meta.png differ diff --git a/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/hero.svg b/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/hero.svg index dfb1c4d8bc5..0b037c07623 100644 --- a/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/hero.svg +++ b/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/hero.svg @@ -1,74 +1,71 @@ - - - - From Local Development to Production with Prisma Postgres - A .env file swaps a local Postgres connection string for a hosted Prisma Postgres one; the app moves from local to production. + + From Local Development to Production with Prisma Postgres + One env swap takes a Prisma app from local Postgres to hosted Prisma Postgres. Prisma blog cover, 2026 brand, prism yellow accent. - - - - - - - - - - + + + + + + + + + + + - - - + + + + + + + + + Prisma Postgres - - PRISMA POSTGRES - - Local to - production, - one env swap + + Local to production, + one env swap - - - .env - - - # local - DATABASE_URL="postgres://…@localhost:51214" - # production - DATABASE_URL="postgres://…@pooled.db.prisma.io" - DIRECT_URL="postgres://…@db.prisma.io" - + + + + .env + # local + DATABASE_URL="postgres://…@localhost:51214" + # production + DATABASE_URL="postgres://…@db.prisma.io:5432" - - - - - - - - $_ - local - prisma dev · Docker - - - - - production - Prisma Postgres + + + + + + + + + + + + + + + + + - - Prisma - diff --git a/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/meta.png b/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/meta.png index e465c56a186..4652b4cc19e 100644 Binary files a/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/meta.png and b/apps/blog/public/from-local-to-production-with-prisma-postgres/imgs/meta.png differ diff --git a/apps/blog/public/give-your-agent-a-database/imgs/hero.svg b/apps/blog/public/give-your-agent-a-database/imgs/hero.svg index 347535f50db..b35a1ede33f 100644 --- a/apps/blog/public/give-your-agent-a-database/imgs/hero.svg +++ b/apps/blog/public/give-your-agent-a-database/imgs/hero.svg @@ -1,60 +1,75 @@ - - - - Your AI Agent Needs a Database. Give It One in Five Seconds - A terminal runs npx create-db --json and returns a Postgres connection string an agent can use immediately. + + Your AI Agent Needs a Database. Give It One in Five Seconds + A flat three step provisioning flow: a coding agent runs npx create-db@latest --json and gets a real Prisma Postgres database at db.prisma.io that deletes itself after 24 hours. Prisma blog cover, 2026 brand, prism yellow accent, no headline. - - - - - - - + + + + + + + + + + + + + + + + - - - + + + + + - - - NPX CREATE-DB - - Give your agent - a database - + + + Ephemeral Prisma Postgres - - - - - - - $ npx create-db --json - - - { - "success": true, - "connectionString": - "postgres://…@db.prisma.io:5432", - "deletionDate": "2026-07-10T08:22Z", - "region": "us-east-1" - } - - - - ready in 5 seconds, deletes itself in 24 hours + + + + coding agent + Cursor, Codex, Claude Code + wants a clean database + + npx create-db@latest --json + real PostgreSQL, no account + no Docker, no sign-up + + db.prisma.io:5432 + deletes itself after 24 hours + claim it to keep it, free + + + + - Prisma + + + + + + + + + + + diff --git a/apps/blog/public/give-your-agent-a-database/imgs/meta.png b/apps/blog/public/give-your-agent-a-database/imgs/meta.png index 4c4d63be57b..123f7584743 100644 Binary files a/apps/blog/public/give-your-agent-a-database/imgs/meta.png and b/apps/blog/public/give-your-agent-a-database/imgs/meta.png differ diff --git a/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.png b/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.png deleted file mode 100644 index 482d8201906..00000000000 Binary files a/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.svg b/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.svg new file mode 100644 index 00000000000..23736eebece --- /dev/null +++ b/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/hero.svg @@ -0,0 +1,86 @@ + + Gremlin: turning open tasks into pull requests + A pipeline: Sentry issues, Linear tasks and Slack threads fan into one chain, gather context, sandbox, validate, and end in an Open PR tile marked in prism cyan. Prisma blog cover, 2026 brand. + + + + + + + + + + + + + + + + + + + + + + + + + + + Gremlin, an autonomous agent + + + + + The pull request is the interface + + + + + + + Sentry issue + + Linear task + + Slack thread + + + + + + + + Gather context + + Sandbox + + Validate + + Open PR + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/meta.png b/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/meta.png new file mode 100644 index 00000000000..9f27f60b7f3 Binary files /dev/null and b/apps/blog/public/gremlin-turning-open-tasks-into-pull-requests/imgs/meta.png differ diff --git a/apps/blog/public/how-prisma-build-with-agentic-ai/imgs/hero.svg b/apps/blog/public/how-prisma-build-with-agentic-ai/imgs/hero.svg new file mode 100644 index 00000000000..e3e9ac61a22 --- /dev/null +++ b/apps/blog/public/how-prisma-build-with-agentic-ai/imgs/hero.svg @@ -0,0 +1,68 @@ + + Agentic Engineering: How Prisma Builds with AI + An ink prompt card holding the three questions the post says engineers ask of an agent, with the operative line, how can I set it up to succeed, marked in prism cyan. Prisma blog cover, 2026 brand. + + + + + + + + + + + + + + + + + + + + + + + + + + + Agentic engineering + + + + + + > + what can this do + > + where does it fail + > + how can I set it up to succeed + + + + + A failure is signal, + not proof + + + + + + + + + + + + + + + diff --git a/apps/blog/public/how-prisma-build-with-agentic-ai/imgs/meta.png b/apps/blog/public/how-prisma-build-with-agentic-ai/imgs/meta.png index 59b88b9ad00..08894dd5d40 100644 Binary files a/apps/blog/public/how-prisma-build-with-agentic-ai/imgs/meta.png and b/apps/blog/public/how-prisma-build-with-agentic-ai/imgs/meta.png differ diff --git a/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/hero.png b/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/hero.png deleted file mode 100644 index 18e14b770a7..00000000000 Binary files a/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/hero.svg b/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/hero.svg new file mode 100644 index 00000000000..782135bb27a --- /dev/null +++ b/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/hero.svg @@ -0,0 +1,80 @@ + + How to Use AI Safely and Responsibly + A guardrail policy card pairing scoped permissions the post allows, bash(npm test), repo:read and /sandbox, against the broad grants it refuses, bash(*), admin:org and skipping permissions. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Security baseline + + + + + Your agent runs with + your permissions + + + + + + + + allowed + refused + + bash(npm test) + + bash(*) + + repo:read + + admin:org + + /sandbox + + --dangerously-skip-permissions + + + + + + + + + + + + + + diff --git a/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/meta.png b/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/meta.png new file mode 100644 index 00000000000..45b4f9bd8fc Binary files /dev/null and b/apps/blog/public/how-to-use-ai-safely-and-responsibly/imgs/meta.png differ diff --git a/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/hero.svg b/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/hero.svg index b4db9e4638c..1f6561346d1 100644 --- a/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/hero.svg +++ b/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/hero.svg @@ -1,74 +1,74 @@ How One Founder Builds a Live Sports Platform Without a Database Team - A Prisma customer story cover for Xeito, showing one founder building a live sports platform while Prisma handles database defaults. + A typographic quote card: Gabriel Gil Graña of Xeito on wanting to spend his time creating features instead of managing memory, pool connections, storage limits, replicas and backups. Prisma blog cover, 2026 brand, prism yellow accent. - - - - - - - - - - + + + - - - - - - - - - - - + + + + + + + + + + - - - - - - - CUSTOMER STORY - One founder. - Live sports - platform. - Xeito keeps shipping product work. - Prisma handles database defaults. + + + + + - - - Xeito product work + + + Xeito, live sports platform + - - - - Features - leagues.live - payments - standings - ai.coach - + + + - - - Prisma defaults - schema → migrations → types - + “ + I really wanted to spend time creating features + + and not having to deal with memory, pool connections, + storage limits, replicas, backups.” + - - + + Gabriel Gil Graña + Founder, Xeito - Prisma + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/meta.png b/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/meta.png index 02d50a113fd..89ed0fa553c 100644 Binary files a/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/meta.png and b/apps/blog/public/how-xeito-builds-features-not-database-infrastructure-with-prisma/imgs/meta.png differ diff --git a/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/hero.svg b/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/hero.svg index 38a03648c1c..0df3214ab4c 100644 --- a/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/hero.svg +++ b/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/hero.svg @@ -1 +1,94 @@ -Image Transformations with Bun on Prisma ComputeRequest-time image pipeline from source to Bun.Image to WebP on Prisma Compute.PRISMA COMPUTEImage transformsas app logicRequest-time image pipelineinputsourcenativeBun.ImageoutputwebpPrisma \ No newline at end of file + + Image Transformations with Bun on Prisma Compute + A request-time pipeline of three tiles: chair.jpg requested with w=640 and q=75, transformed by Bun.Image into webp, and returned as chair.webp cached immutable for a year. Prisma blog cover, 2026 brand, prism red Compute accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Image transforms on Bun + + + + + + + + + + + + + + + + + + + chair.jpg + Bun.Image + chair.webp + ?w=640&q=75 + resize · webp + immutable, 1 year + + + + + + Image transforms are + just app logic + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/meta.png b/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/meta.png index 11528e06988..aae98af52a6 100644 Binary files a/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/meta.png and b/apps/blog/public/image-transformations-with-bun-on-prisma-compute/imgs/meta.png differ diff --git a/apps/blog/public/infraslopture-and-other-paradoxes/imgs/hero.svg b/apps/blog/public/infraslopture-and-other-paradoxes/imgs/hero.svg index aa6fd74cb33..6ab7611df00 100644 --- a/apps/blog/public/infraslopture-and-other-paradoxes/imgs/hero.svg +++ b/apps/blog/public/infraslopture-and-other-paradoxes/imgs/hero.svg @@ -1,59 +1,74 @@ - - - Infraslopture and Other Paradoxes - A terminal where a prompt asking for reproducible server configurations resolves into a checklist of NixOS, colmena, sops-nix, Incus, and Tailscale. + + Infraslopture and Other Paradoxes + Untrustable agents meeting production infrastructure: a reproducible-config checklist. Prisma blog cover, 2026 brand, prism red accent. - - - - - - - + + + + + + + + + + + - - - + + + + + + + + + Agentic engineering - - AGENTIC ENGINEERING - - Infraslopture - and other paradoxes + + Infraslopture, + and other paradoxes + Untrustable agents, production infrastructure, no burned-down servers. - - - - - - > i need reproducible server configs - - - - - NixOS + flakes - - - - colmena + sops-nix - - - - Incus + Tailscale - + + + + > i need reproducible server configs + ✓ + NixOS + flakes + ✓ + colmena + sops-nix + ✓ + Incus + Tailscale - Prisma - + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/infraslopture-and-other-paradoxes/imgs/meta.png b/apps/blog/public/infraslopture-and-other-paradoxes/imgs/meta.png index 07f25dc6da8..b0ae05df68b 100644 Binary files a/apps/blog/public/infraslopture-and-other-paradoxes/imgs/meta.png and b/apps/blog/public/infraslopture-and-other-paradoxes/imgs/meta.png differ diff --git a/apps/blog/public/introducing-create-prisma/imgs/hero.png b/apps/blog/public/introducing-create-prisma/imgs/hero.png deleted file mode 100644 index 2e48d607061..00000000000 Binary files a/apps/blog/public/introducing-create-prisma/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/introducing-create-prisma/imgs/hero.svg b/apps/blog/public/introducing-create-prisma/imgs/hero.svg new file mode 100644 index 00000000000..275ffa9fd73 --- /dev/null +++ b/apps/blog/public/introducing-create-prisma/imgs/hero.svg @@ -0,0 +1,83 @@ + + Introducing Create-Prisma: Start a Prisma App With One Command + An ink terminal card running npm create prisma at latest, with a checklist of what the CLI generates: a Prisma schema, a seed file, prisma.config.ts, a dotenv file with DATABASE_URL, and the database scripts. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + create-prisma + + + + + Every framework, + the same setup + + Templates for Next.js, Nuxt, Hono, and more. + + + + + + $ npm create prisma@latest + + + + ✓ + prisma/schema.prisma + ✓ + prisma/seed.ts + ✓ + prisma.config.ts + ✓ + .env with DATABASE_URL + ✓ + db:generate, db:migrate, db:seed + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/introducing-create-prisma/imgs/meta.png b/apps/blog/public/introducing-create-prisma/imgs/meta.png index 457abfe666c..90bfdc0d2b1 100644 Binary files a/apps/blog/public/introducing-create-prisma/imgs/meta.png and b/apps/blog/public/introducing-create-prisma/imgs/meta.png differ diff --git a/apps/blog/public/launching-prisma-compute-public-beta/imgs/hero.png b/apps/blog/public/launching-prisma-compute-public-beta/imgs/hero.png index 33d382d51cd..fdc68fa8dbe 100644 Binary files a/apps/blog/public/launching-prisma-compute-public-beta/imgs/hero.png and b/apps/blog/public/launching-prisma-compute-public-beta/imgs/hero.png differ diff --git a/apps/blog/public/launching-prisma-compute-public-beta/imgs/hero.svg b/apps/blog/public/launching-prisma-compute-public-beta/imgs/hero.svg new file mode 100644 index 00000000000..dc1211171f5 --- /dev/null +++ b/apps/blog/public/launching-prisma-compute-public-beta/imgs/hero.svg @@ -0,0 +1,80 @@ + + Launching Prisma Compute in Public Beta + Prisma Compute public beta: TypeScript app hosting on the same infrastructure as your database. Prisma blog cover, 2026 brand, prism red accent with the prism-stripe launch motif. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma Compute · Public beta + + + + + Your app, hosted + next to its database + + TypeScript app hosting on the same infrastructure as your data. + + + + + + $ prisma app deploy + ✓ build · 12s + ✓ database connected + → live + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/launching-prisma-compute-public-beta/imgs/meta.png b/apps/blog/public/launching-prisma-compute-public-beta/imgs/meta.png index bb2b5ccbb87..fdc68fa8dbe 100644 Binary files a/apps/blog/public/launching-prisma-compute-public-beta/imgs/meta.png and b/apps/blog/public/launching-prisma-compute-public-beta/imgs/meta.png differ diff --git a/apps/blog/public/logo/full-color-white.svg b/apps/blog/public/logo/full-color-white.svg new file mode 100644 index 00000000000..19e803de053 --- /dev/null +++ b/apps/blog/public/logo/full-color-white.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/logo/full-color.svg b/apps/blog/public/logo/full-color.svg new file mode 100644 index 00000000000..19c4f1c037a --- /dev/null +++ b/apps/blog/public/logo/full-color.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/logo/prisma-footer-black.svg b/apps/blog/public/logo/prisma-footer-black.svg new file mode 100644 index 00000000000..56293264a0f --- /dev/null +++ b/apps/blog/public/logo/prisma-footer-black.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/logo/prisma-footer-color.svg b/apps/blog/public/logo/prisma-footer-color.svg new file mode 100644 index 00000000000..b54c20465dc --- /dev/null +++ b/apps/blog/public/logo/prisma-footer-color.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/make-your-docs-agent-ready/imgs/hero.svg b/apps/blog/public/make-your-docs-agent-ready/imgs/hero.svg index 10abab986ce..29fc3c90c18 100644 --- a/apps/blog/public/make-your-docs-agent-ready/imgs/hero.svg +++ b/apps/blog/public/make-your-docs-agent-ready/imgs/hero.svg @@ -1,100 +1,80 @@ - - - - How to Make Your Docs Agent-Ready - Prisma blog cover. A row of four document tiles, llms.txt highlighted in teal, then a markdown page, skill.md, and the .well-known MCP discovery document, under the headline "Make your docs agent-ready". - + + How to Make Your Docs Agent-Ready + An ink panel listing the Prisma docs endpoints an agent fetches: the split llms.txt index at 7 KB, per-area indexes, llms-full.txt at 4.5 MB, skill.md and the MCP discovery document. Prisma blog cover, 2026 brand, prism cyan accent. - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + + - - - DOCS FOR CODING AGENTS + + + Agent-ready docs - - Make your docs - agent-ready + + Small enough to + survive one fetch - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - { } - - - - llms.txt - postgres.md - skill.md - .well-known/mcp - + + 116,000 characters down to 7,000. + + + + + + agent endpoints + + + + /docs/llms.txt + 7 KB + /docs/llms/orm.txt + /docs/llms/orm-v6.txt + 37 KB + /docs/llms/postgres.txt + /docs/llms-full.txt + 4.5 MB + /skill.md + /.well-known/mcp - - + + + + + + + + + + diff --git a/apps/blog/public/make-your-docs-agent-ready/imgs/meta.png b/apps/blog/public/make-your-docs-agent-ready/imgs/meta.png index e0261cbe1d3..6f168c84742 100644 Binary files a/apps/blog/public/make-your-docs-agent-ready/imgs/meta.png and b/apps/blog/public/make-your-docs-agent-ready/imgs/meta.png differ diff --git a/apps/blog/public/mongodb-without-compromise/imgs/hero.svg b/apps/blog/public/mongodb-without-compromise/imgs/hero.svg index fc72dc94148..18e113685bf 100644 --- a/apps/blog/public/mongodb-without-compromise/imgs/hero.svg +++ b/apps/blog/public/mongodb-without-compromise/imgs/hero.svg @@ -1 +1,91 @@ -PRISMA 8Prisma 8andMongoDB \ No newline at end of file + + MongoDB Without Compromise + Data shape drawing: an untyped MongoDB document beside the Prisma 8 contract that types it, including the embedded Address type. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma 8 and MongoDB + + + + Typed all the way down + + + + + MongoDB document + + + { + _id: ObjectId + name: "Alice Chen" + email: "alice@example.com" + address: { street, city } + } + + + + + + + + Prisma 8 contract + + + model User { + id ObjectId @id @map("_id") + name String + email String + address Address? + } + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/mongodb-without-compromise/imgs/meta.png b/apps/blog/public/mongodb-without-compromise/imgs/meta.png index 1c28d3b17d3..56c204bcc35 100644 Binary files a/apps/blog/public/mongodb-without-compromise/imgs/meta.png and b/apps/blog/public/mongodb-without-compromise/imgs/meta.png differ diff --git a/apps/blog/public/object-store-buckets/imgs/hero.svg b/apps/blog/public/object-store-buckets/imgs/hero.svg index f17aa8e9c6a..c126761931d 100644 --- a/apps/blog/public/object-store-buckets/imgs/hero.svg +++ b/apps/blog/public/object-store-buckets/imgs/hero.svg @@ -1,85 +1,81 @@ - - - - Your AI Agent Needs File Storage. Now It Can Get Its Own - An agent chip issues two Management API calls that create a bucket and mint a key, then writes hello/first-upload.txt, 44 bytes, into the bucket. + + Your AI Agent Needs File Storage. Now It Can Get Its Own + Object Store buckets: two Management API calls take an agent from nothing to reading and writing files. Prisma blog cover, 2026 brand, prism yellow accent. - - - - - - - - + + + - - - - - - - - + + + + + + + - - - - - - + + + + - - - OBJECT STORE BUCKETS + + + Object Store - Your agent can provision - file storage now + + Your agent gets + its own file storage + + S3-compatible buckets on every Prisma project, two API calls away. - - - - agent - - - - - uploads - bkt_ic7y0a24 - + + + + agent + needs files - - - POST /v1/buckets - ready + → - - POST /v1/buckets/:id/keys - read_write + + Management API + 2 calls - - - - hello/first-upload.txt - 44 bytes + → - - S3-compatible · any client · keys scoped read / read_write + + bucket + read · write - - Prisma + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/object-store-buckets/imgs/meta.png b/apps/blog/public/object-store-buckets/imgs/meta.png index 27d6d9caced..067e95b92b7 100644 Binary files a/apps/blog/public/object-store-buckets/imgs/meta.png and b/apps/blog/public/object-store-buckets/imgs/meta.png differ diff --git a/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/bloom-filters-in-postgres.png b/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/bloom-filters-in-postgres.png deleted file mode 100644 index cb1c5c9d035..00000000000 Binary files a/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/bloom-filters-in-postgres.png and /dev/null differ diff --git a/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/hero.svg b/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/hero.svg new file mode 100644 index 00000000000..42fd7553e61 --- /dev/null +++ b/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/hero.svg @@ -0,0 +1,130 @@ + + Bloom Filters in Postgres: The Index Type Most Developers Overlook + Probabilistic set drawing: the item alice hashed by fnv1a, djb2 and murmur3, setting bits 2, 7 and 11 of a sixteen bit array. Prisma blog cover, 2026 brand, prism yellow accent, no headline. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + item + + "alice" + + + + + + + + + + + fnv1a + + djb2 + + murmur3 + + + + + + + + + + + + + 16 bits + + + 0 + + 0 + + 1 + + 0 + + 0 + + 0 + + 0 + + 1 + + 0 + + 0 + + 0 + + 1 + + 0 + + 0 + + 0 + + 0 + + + 2 + 7 + 11 + + + + one bloom signature per row + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/meta.png b/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/meta.png new file mode 100644 index 00000000000..a59a00fb101 Binary files /dev/null and b/apps/blog/public/postgres-bloom-index-the-overlooked-postgres-feature/imgs/meta.png differ diff --git a/apps/blog/public/price-the-work-not-the-workflow/imgs/hero.png b/apps/blog/public/price-the-work-not-the-workflow/imgs/hero.png deleted file mode 100644 index dcb14afad27..00000000000 Binary files a/apps/blog/public/price-the-work-not-the-workflow/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/price-the-work-not-the-workflow/imgs/hero.svg b/apps/blog/public/price-the-work-not-the-workflow/imgs/hero.svg new file mode 100644 index 00000000000..e73d4b59018 --- /dev/null +++ b/apps/blog/public/price-the-work-not-the-workflow/imgs/hero.svg @@ -0,0 +1,96 @@ + + Price the Work, Not the Workflow + Four meters priced separately, one per kind of consumption: requests, provisioned memory, active CPU and outbound bandwidth, with deploys, previews, retries, seats and idle time struck out as not billed. Prisma blog cover, 2026 brand, prism red accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma Compute pricing + + + + One meter per kind of work + + + + + + + + + + + + + Requests + $1.00 + per 1M + + Provisioned memory + $0.006 + per GB-hour + + Active CPU + $0.064 + per vCPU-hour + + Outbound bandwidth + $0.025 + per GB + + + + deploys, previews, retries, seats, idle time + + not billed + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/price-the-work-not-the-workflow/imgs/meta.png b/apps/blog/public/price-the-work-not-the-workflow/imgs/meta.png new file mode 100644 index 00000000000..072db6b2514 Binary files /dev/null and b/apps/blog/public/price-the-work-not-the-workflow/imgs/meta.png differ diff --git a/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero-fed37f83921ceeba6d0395d774c48ae9d5b68dcc-844x474-7cca11ee09.png b/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero-fed37f83921ceeba6d0395d774c48ae9d5b68dcc-844x474-7cca11ee09.png deleted file mode 100644 index 6150d034038..00000000000 Binary files a/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero-fed37f83921ceeba6d0395d774c48ae9d5b68dcc-844x474-7cca11ee09.png and /dev/null differ diff --git a/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero.svg b/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero.svg new file mode 100644 index 00000000000..09a80404479 --- /dev/null +++ b/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/hero.svg @@ -0,0 +1,76 @@ + + Prisma 7 AMA: Clearing Up the Why Behind the Changes + A typographic question and answer from the Prisma 7 AMA: is Prisma 7 faster or slower than Prisma 6, answered with the line that it depends heavily on how you measure performance, with the operative phrase set in prism cyan. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma 7 AMA + + + + + + Q. + + Prisma 7 vs Prisma 6 performance: + is it faster or slower? + + + + + + + A. + + This depends heavily on + how you measure performance. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta-64c44281ee8d3e0fe5e7e9bbd309603e5496945d-1266x711-26d35e93c9.png b/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta-64c44281ee8d3e0fe5e7e9bbd309603e5496945d-1266x711-26d35e93c9.png deleted file mode 100644 index 735886ab0c8..00000000000 Binary files a/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta-64c44281ee8d3e0fe5e7e9bbd309603e5496945d-1266x711-26d35e93c9.png and /dev/null differ diff --git a/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta.png b/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta.png new file mode 100644 index 00000000000..99bca91ad8a Binary files /dev/null and b/apps/blog/public/prisma-7-ama-clearing-up-the-why-behind-the-changes/imgs/meta.png differ diff --git a/apps/blog/public/prisma-compute-config-file/imgs/hero.svg b/apps/blog/public/prisma-compute-config-file/imgs/hero.svg index 521918cefa1..74786283529 100644 --- a/apps/blog/public/prisma-compute-config-file/imgs/hero.svg +++ b/apps/blog/public/prisma-compute-config-file/imgs/hero.svg @@ -1,504 +1,79 @@ - -
Prisma Compute Config

One typed file
for every app
target

prisma.compute.ts
export default defineComputeConfig(({
apps: {
api: app("apps/api", "hono"),
web: app("apps/web", "nextjs")
}
})
api
Hono
web
Next.js
Prisma
\ No newline at end of file + + Configure Prisma Compute deploys in TypeScript + An ink code card with a prisma.compute.ts filename tab showing a monorepo config that declares an api app on Hono and a web app on Next.js. Prisma blog cover, 2026 brand, prism red Compute accent, no headline. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma Compute config + + + + + + + + prisma.compute.ts + + + + export defaultdefineComputeConfig({ + apps: { + api: {root:"apps/api",framework:"hono"}, + web: {root:"apps/web",framework:"nextjs"}, + }, + }); + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-compute-config-file/imgs/meta.png b/apps/blog/public/prisma-compute-config-file/imgs/meta.png index f7eddeee5b9..c8dc9b57b79 100644 Binary files a/apps/blog/public/prisma-compute-config-file/imgs/meta.png and b/apps/blog/public/prisma-compute-config-file/imgs/meta.png differ diff --git a/apps/blog/public/prisma-compute-custom-domains/imgs/hero.png b/apps/blog/public/prisma-compute-custom-domains/imgs/hero.png deleted file mode 100644 index aefc32dd8c8..00000000000 Binary files a/apps/blog/public/prisma-compute-custom-domains/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/prisma-compute-custom-domains/imgs/hero.svg b/apps/blog/public/prisma-compute-custom-domains/imgs/hero.svg new file mode 100644 index 00000000000..5980b6f9c93 --- /dev/null +++ b/apps/blog/public/prisma-compute-custom-domains/imgs/hero.svg @@ -0,0 +1,88 @@ + + We Launched Prisma Compute with Custom Domains + The one DNS record a custom domain needs: a CNAME for shop.acme.com pointing at switchboard.cdg.prisma.build with a TTL of 300, and a status row reading active once TLS is provisioned. Prisma blog cover, 2026 brand, prism red Compute accent, no headline. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Custom domains on Prisma Compute + + + + + + + + Type + Name + Value + TTL + + + + + + CNAME + shop.acme.com + switchboard.cdg.prisma.build + 300 + + + + status + + active + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-compute-custom-domains/imgs/meta.png b/apps/blog/public/prisma-compute-custom-domains/imgs/meta.png new file mode 100644 index 00000000000..c690be133a5 Binary files /dev/null and b/apps/blog/public/prisma-compute-custom-domains/imgs/meta.png differ diff --git a/apps/blog/public/prisma-compute-time-synchronization/imgs/hero.svg b/apps/blog/public/prisma-compute-time-synchronization/imgs/hero.svg index 7f07b367628..909fec5eb9f 100644 --- a/apps/blog/public/prisma-compute-time-synchronization/imgs/hero.svg +++ b/apps/blog/public/prisma-compute-time-synchronization/imgs/hero.svg @@ -1,53 +1,102 @@ - - - - Every clock drifts — measured on a Prisma Compute VM - An awake Compute VM in Frankfurt drifted about 13.75 ms per hour (3.82 ppm) over six hours: -13.8 ms at one hour, -27.5 ms at two, -55 ms at four, -82.5 ms at six. + + How Prisma Compute Keeps Time Accurate in Long-Running Applications + A drift drawing: the host paired clock read from /dev/ptp0 runs flat while the guest CLOCK_REALTIME of an awake microVM falls away from it, reaching about minus 82.5 ms after six hours at the measured average of 13.75 ms per hour. Prisma blog cover, 2026 brand, prism red Compute accent. - - - - - + + + + + + + + + + + + + + + + - - - + + + + + - - - PRISMA COMPUTE - Every clock drifts - Even a server-grade crystal oscillator wanders from true time. - Prisma + + + Clock drift on Prisma Compute - - - average clock skew, sampled every 5 min - 13.75 ms/h - 3.82 ppm - - - - t+1h-13.8 ms - - t+2h-27.5 ms - - t+4h-55.0 ms - - t+6h-82.5 ms - + + + The host clock, + one hypercall away + + + 13.75 ms/h · 3.82 ppm + 73 h to drift one second + + + + + + + + + + + + + + + + + + + + + + host /dev/ptp0 + guest CLOCK_REALTIME + + + 2 h + 4 h + 6 h + -27.5 ms + -55 ms + -82.5 ms + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-compute-time-synchronization/imgs/meta.png b/apps/blog/public/prisma-compute-time-synchronization/imgs/meta.png index 31da37ade5c..7d3628b9f11 100644 Binary files a/apps/blog/public/prisma-compute-time-synchronization/imgs/meta.png and b/apps/blog/public/prisma-compute-time-synchronization/imgs/meta.png differ diff --git a/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/hero.svg b/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/hero.svg index 6c4d76bb664..9d1dfe693f0 100644 --- a/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/hero.svg +++ b/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/hero.svg @@ -1,62 +1,111 @@ - - - - Prisma Compute vs Vercel Pricing - The same 20M-request month: about $236 on Vercel (Pro), crossed out, becomes about $98 on Prisma Compute at planned rates, saving about $138 or 58% every month. + + Prisma Compute vs Vercel Pricing + A line by line pricing table for one 20M request month: Prisma Compute totals about 98 dollars against about 236 dollars on Vercel Pro, with the seat fee the only line Prisma does not charge. Prisma blog cover, 2026 brand, prism red accent. - - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + - - PRISMA COMPUTE VS VERCEL - - The same workload, - ~58% less on Prisma - - One month, priced line by line: 20M requests, 300 vCPU-hours, 2 TB egress, one seat. + + + Priced line by line - - + + + The whole gap + is the workflow + + 20M requests · 1,460 GB-hours · 300 vCPU-hours · 2 TB out · 1 seat + - - - Vercel (Pro) - ~$236/ month - + + + + - - - + + Requests + Memory + Active CPU + Egress + Seat + Total + + - - - Prisma Compute - ~$98 - / month at planned rates + + Prisma Compute + + $20.00 + $8.76 + $19.20 + $50.00 + $0.00 + + ~$98 + - - - save ~$138 / month + + Vercel (Pro) + + $12.00 + $15.48 + $38.40 + $150.00 + $20.00 + + ~$236 + - Prisma + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/meta.png b/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/meta.png index d93e253a202..6477a247689 100644 Binary files a/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/meta.png and b/apps/blog/public/prisma-compute-vs-vercel-pricing/imgs/meta.png differ diff --git a/apps/blog/public/prisma-next-call-for-extension-authors/imgs/hero.svg b/apps/blog/public/prisma-next-call-for-extension-authors/imgs/hero.svg index 20bd981fe98..83cc7713118 100644 --- a/apps/blog/public/prisma-next-call-for-extension-authors/imgs/hero.svg +++ b/apps/blog/public/prisma-next-call-for-extension-authors/imgs/hero.svg @@ -1 +1,81 @@ -PRISMA 8 \ No newline at end of file + + Prisma 8: A Call for Extension Authors + An ink manifest card for a Prisma 8 extension package, showing the four layers an extension can contribute: contract, query, runtime and migration. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @yourname/prisma-next-extension-foo + + + + contract + column types, index types + + + query + typed builder methods + + + runtime + codecs, middleware + + + migration + DDL and data operations + + + extensionPacks: [pgvector] + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-next-call-for-extension-authors/imgs/meta.png b/apps/blog/public/prisma-next-call-for-extension-authors/imgs/meta.png index 59ba7267c52..e2ab4e130f9 100644 Binary files a/apps/blog/public/prisma-next-call-for-extension-authors/imgs/meta.png and b/apps/blog/public/prisma-next-call-for-extension-authors/imgs/meta.png differ diff --git a/apps/blog/public/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/hero.svg b/apps/blog/public/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/hero.svg new file mode 100644 index 00000000000..360348bbae2 --- /dev/null +++ b/apps/blog/public/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/hero.svg @@ -0,0 +1,83 @@ + + Prisma 8 Early Access: Write Your Contract, Prompt Your Agent, Ship Your App + Three-tile pipeline: write the contract, prompt the agent, ship the app, with the framework planning the migration in between. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma 8 early access + + + + + Safe enough + to delegate + + + + + + + Write your contract + contract.prisma + + + + + Prompt your agent + prisma-next migration plan + + + + + Ship your app + prisma-next migrate + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/meta.png b/apps/blog/public/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/meta.png index 032ec60124a..5483c418e31 100644 Binary files a/apps/blog/public/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/meta.png and b/apps/blog/public/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/imgs/meta.png differ diff --git a/apps/blog/public/prisma-next-ltree-extension/imgs/hero.svg b/apps/blog/public/prisma-next-ltree-extension/imgs/hero.svg index 618e56e8696..a066055dea8 100644 --- a/apps/blog/public/prisma-next-ltree-extension/imgs/hero.svg +++ b/apps/blog/public/prisma-next-ltree-extension/imgs/hero.svg @@ -1,96 +1,95 @@ - - - - Typed ltree for Prisma 8: prisma-ltree extension pack - prisma-ltree extends Prisma 8 with typed Postgres ltree columns and operators for hierarchical paths. - + + Extending Prisma 8 with Typed Postgres ltree + A typed ltree path tree, essays to essays.drafts to essays.drafts.chapter_1, with the isDescendantOf operator highlighted. Prisma blog cover, 2026 brand, prism cyan accent. - - - - - - - - - - + + + - - - - - - - - + + + + + + + - - - + + + + + + + + + Community extension pack - - TYPED POSTGRES LTREE - - Typed ltree - for Prisma 8 + + One column, + the whole subtree + Typed ltree columns via prisma-ltree. - - - + + + + Path = ltree.Ltree() + - - - Prisma 8 - - - - - - prisma-ltree + + + + + + - - - - - - - + + essays - - essays + + essays.drafts - - drafts + + essays.drafts.chapter_1 - - chapter_1 + + essays.published - - notes + + essays.published.chapter_3 - - published - - - - path essays.drafts.chapter_1 + + isDescendantOf("essays") - Prisma + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-next-ltree-extension/imgs/meta.png b/apps/blog/public/prisma-next-ltree-extension/imgs/meta.png index 0ed9d484fe0..85db852acdb 100644 Binary files a/apps/blog/public/prisma-next-ltree-extension/imgs/meta.png and b/apps/blog/public/prisma-next-ltree-extension/imgs/meta.png differ diff --git a/apps/blog/public/prisma-next-performance-benchmark/imgs/hero.svg b/apps/blog/public/prisma-next-performance-benchmark/imgs/hero.svg index a691380e420..b1c7ac958c3 100644 --- a/apps/blog/public/prisma-next-performance-benchmark/imgs/hero.svg +++ b/apps/blog/public/prisma-next-performance-benchmark/imgs/hero.svg @@ -1 +1,76 @@ -Prisma 8 performance benchmarkPrisma 8 reaches about 90 percent of raw pg throughput.THROUGHPUT VS RAW PGPrisma 8 Is~90% As Fastas Raw PGpg (raw driver)14,350req/secPrisma 812,534req/secPrisma \ No newline at end of file + + Prisma 8 Is ~90% As Fast as Raw PG + Peak sustained throughput bars for the raw pg driver, Prisma 8 and Prisma 7, measured on the same Postgres workload. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + Peak throughput, same workload + + + + + + + pg (raw driver) + 14,350 req/s + + + + Prisma 8 + 12,500 req/s + + + + Prisma 7 + 8,300 req/s + + + + 87% of pg peak, 52% above Prisma 7 + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-next-performance-benchmark/imgs/meta.png b/apps/blog/public/prisma-next-performance-benchmark/imgs/meta.png index 21bd18e36cd..609c3d94e18 100644 Binary files a/apps/blog/public/prisma-next-performance-benchmark/imgs/meta.png and b/apps/blog/public/prisma-next-performance-benchmark/imgs/meta.png differ diff --git a/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/hero.svg b/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/hero.svg index f2e05761fe1..6c7cc674c24 100644 --- a/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/hero.svg +++ b/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/hero.svg @@ -1 +1,93 @@ -PRISMA 8 \ No newline at end of file + + Prisma 8: April Milestone Complete, the Extension API Is Open + A milestone panel listing the four extensions that shipped on the Prisma 8 extension API in April, with streaming subscriptions carried into May. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma 8 milestone update + + + + + What shipped, + what did not + + + + + + + + Shipped in April + + + ✓ + pgvector + + + ✓ + arktype-json + + + ✓ + ParadeDB + + + ✓ + CipherStash + + + + Carried into May + + + Streaming + subscriptions + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/meta.png b/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/meta.png index fe791140ae7..9a935b79979 100644 Binary files a/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/meta.png and b/apps/blog/public/prisma-next-roadmap-april-milestone/imgs/meta.png differ diff --git a/apps/blog/public/prisma-next-roadmap/imgs/hero.png b/apps/blog/public/prisma-next-roadmap/imgs/hero.png deleted file mode 100644 index d976f92d866..00000000000 Binary files a/apps/blog/public/prisma-next-roadmap/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/prisma-next-roadmap/imgs/hero.svg b/apps/blog/public/prisma-next-roadmap/imgs/hero.svg new file mode 100644 index 00000000000..8cda933916f --- /dev/null +++ b/apps/blog/public/prisma-next-roadmap/imgs/hero.svg @@ -0,0 +1,79 @@ + + Prisma 8 Roadmap + A horizontal milestone track for the phased Prisma 8 delivery plan: April external contributions, May early access, June to July Postgres general availability. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + April + + + + External contributions + extensions, targets, middleware + + + May + + + + Early access + initial release, then feedback + + + June to July + + + + + Postgres general availability + production ready + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-next-roadmap/imgs/meta.png b/apps/blog/public/prisma-next-roadmap/imgs/meta.png index 475041a65d5..b499714051a 100644 Binary files a/apps/blog/public/prisma-next-roadmap/imgs/meta.png and b/apps/blog/public/prisma-next-roadmap/imgs/meta.png differ diff --git a/apps/blog/public/prisma-orm-7-3-0/imgs/hero-e84b7eb35dc73daddb55d22bb7a24b71f40d3d5d-844x474-552f491d83.svg b/apps/blog/public/prisma-orm-7-3-0/imgs/hero-e84b7eb35dc73daddb55d22bb7a24b71f40d3d5d-844x474-552f491d83.svg deleted file mode 100644 index af136d88465..00000000000 --- a/apps/blog/public/prisma-orm-7-3-0/imgs/hero-e84b7eb35dc73daddb55d22bb7a24b71f40d3d5d-844x474-552f491d83.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/blog/public/prisma-orm-7-3-0/imgs/hero.svg b/apps/blog/public/prisma-orm-7-3-0/imgs/hero.svg new file mode 100644 index 00000000000..7c038d5c141 --- /dev/null +++ b/apps/blog/public/prisma-orm-7-3-0/imgs/hero.svg @@ -0,0 +1,81 @@ + + Prisma ORM 7.3.0: Faster queries, safer data, smoother upgrades + A version badge reading Prisma ORM 7.3.0 beside four changelog items from the release: the new compilerBuild generator option, raw queries skipping the compiler, the MSSQL adapter on version 12.2.0, and BigInt precision preserved in relationJoins JSON aggregation. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma ORM + 7.3.0 + + npm i prisma@7.3.0 + + + + + + New query compiler option + compilerBuild = "fast" | "small" + + + + Raw queries skip the compiler + $queryRaw, $executeRaw + + + + MSSQL adapter updated + @prisma/adapter-mssql, MSSQL v12.2.0 + + + + BigInt precision preserved + relationJoins JSON aggregation + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-orm-7-3-0/imgs/meta.png b/apps/blog/public/prisma-orm-7-3-0/imgs/meta.png new file mode 100644 index 00000000000..0661d0ef6e6 Binary files /dev/null and b/apps/blog/public/prisma-orm-7-3-0/imgs/meta.png differ diff --git a/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero-fef1bbb68459cebeece803f612fd0b95571d3d57-844x474-c0e399ac58.png b/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero-fef1bbb68459cebeece803f612fd0b95571d3d57-844x474-c0e399ac58.png deleted file mode 100644 index 963650e684f..00000000000 Binary files a/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero-fef1bbb68459cebeece803f612fd0b95571d3d57-844x474-c0e399ac58.png and /dev/null differ diff --git a/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero.svg b/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero.svg new file mode 100644 index 00000000000..cd13a05748b --- /dev/null +++ b/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/hero.svg @@ -0,0 +1,82 @@ + + Prisma ORM v7.4: Query Caching, Partial Indexes, and Major Performance Improvements + A release-notes card for Prisma ORM 7.4 listing three named features: query caching with per-query compilation cost falling from 0.1-1ms to 1-10 microseconds, partial indexes behind a preview feature flag, and a typical cache hit rate near 100 percent. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma ORM 7.4 + + + + + + Query caching + Per-query compilation cost + 0.1-1ms → 1-10μs + + + + Partial indexes + New preview feature + previewFeatures = ["partialIndexes"] + + + + + Performance + Typical cache hit rate + ~100% + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta-e94d09878c3f2ac3e105a920dea3556ac0f9917a-1688x948-a991da7a72.png b/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta-e94d09878c3f2ac3e105a920dea3556ac0f9917a-1688x948-a991da7a72.png deleted file mode 100644 index 0e9bc09be82..00000000000 Binary files a/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta-e94d09878c3f2ac3e105a920dea3556ac0f9917a-1688x948-a991da7a72.png and /dev/null differ diff --git a/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta.png b/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta.png new file mode 100644 index 00000000000..605bc57fcee Binary files /dev/null and b/apps/blog/public/prisma-orm-v7-4-query-caching-partial-indexes-and-major-performance-improvements/imgs/meta.png differ diff --git a/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/hero.png b/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/hero.png deleted file mode 100644 index f37e1d6ca4d..00000000000 Binary files a/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/hero.svg b/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/hero.svg new file mode 100644 index 00000000000..c1b10980a06 --- /dev/null +++ b/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/hero.svg @@ -0,0 +1,98 @@ + + Your agent can now provision Prisma Postgres through Stripe + A provider card for prisma/database on Stripe Projects: provisioned and ready on the free plan, with the published starter, pro and business plan prices and the four injected environment variables. Prisma blog cover, 2026 brand, prism yellow accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Stripe Projects + + + + + No signup, + no card, + no browser. + + $ stripe projects add prisma/database + + + + + + + + + prisma/database + + ready + + + + + + free + Free + + starter + $10/mo + + pro + $49/mo + + business + $129/mo + + + + ✓ Injected 4 environment variables + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/meta.png b/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/meta.png index f37e1d6ca4d..b651ad8d76f 100644 Binary files a/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/meta.png and b/apps/blog/public/prisma-postgres-on-stripe-projects/imgs/meta.png differ diff --git a/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/hero.svg b/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/hero.svg index aa7f70fceb5..92ae57dc075 100644 --- a/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/hero.svg +++ b/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/hero.svg @@ -1,89 +1,104 @@ - - Prisma Postgres vs Neon Pricing 2026 - Prisma blog cover. Prisma Postgres bills per operation; Neon bills per compute-hour. - + + Prisma Postgres vs Neon Pricing 2026: Per-Plan Tables and Worked Examples + Pricing comparison table: billing unit, free tier, paid entry and top plan for Prisma Postgres and Neon, using the published figures from the post. Prisma blog cover, 2026 brand, prism yellow accent, no headline. - - - - - - - - - + + + + + + + - - - - - - - - - - - - - + + + + + + + - - - + + + + - - - DATABASE PRICING - + + + + + + - - - Prisma Postgres vs Neon - Pricing 2026 - - They don't bill for the same thing. - + + Prisma Postgres + Neon + + - - - - - + + + + - - - - - - + + + Bills for + Free + Paid entry + Top plan - Prisma Postgres - - PAY PER OPERATION - Billed by queries, not uptime - - vs + + Operations + 100k ops · 500 MB + $10 / mo + $129 / mo + Compute-hours + 100 CU-hours · 0.5 GB + $0.106 / CU-hour + $0.222 / CU-hour + - - - - Prisma + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/meta.png b/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/meta.png index 533f26c6267..0014f64fa24 100644 Binary files a/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/meta.png and b/apps/blog/public/prisma-postgres-vs-neon-pricing-2026/imgs/meta.png differ diff --git a/apps/blog/public/prisma-schema-as-llm-context/imgs/hero.svg b/apps/blog/public/prisma-schema-as-llm-context/imgs/hero.svg index 3f7fd0bc141..afe9a94a5d0 100644 --- a/apps/blog/public/prisma-schema-as-llm-context/imgs/hero.svg +++ b/apps/blog/public/prisma-schema-as-llm-context/imgs/hero.svg @@ -1,78 +1,76 @@ - - - - Why Your Agent Reads a Prisma Schema Better Than Your Codebase - A compact schema.prisma file beside a token-count comparison: the schema carries the whole data model in half the tokens of code-based definitions. + + Why Your Agent Reads a Prisma Schema Better Than Your Codebase + Token-cost comparison: one declarative schema file versus a code-based model. Prisma blog cover, 2026 brand, prism cyan accent. - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - + + + + + + + + + Schema as LLM context - - SCHEMA AS LLM CONTEXT - - Your agent reads - the schema, - not the codebase + + Your agent reads + the schema, + not the codebase - - - schema.prisma - - model Membership { - role Role @default(MEMBER) - user User @relation(onDelete: Cascade) - org Org @relation(onDelete: Cascade) - @@unique([userId, orgId]) - @@index([orgId]) - } - - + + + + schema.prisma + 968 tokens + + - - schema.prisma - 968 tokens - - - code-based model - 1,543 tokens - - + code-based model + 1,543 tokens + + - Prisma - + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/prisma-schema-as-llm-context/imgs/meta.png b/apps/blog/public/prisma-schema-as-llm-context/imgs/meta.png index 8f74b264df9..585aa466558 100644 Binary files a/apps/blog/public/prisma-schema-as-llm-context/imgs/meta.png and b/apps/blog/public/prisma-schema-as-llm-context/imgs/meta.png differ diff --git a/apps/blog/public/prisma-studio-migrations-view/imgs/hero.svg b/apps/blog/public/prisma-studio-migrations-view/imgs/hero.svg index 7e01c6af981..d4fcebd686d 100644 --- a/apps/blog/public/prisma-studio-migrations-view/imgs/hero.svg +++ b/apps/blog/public/prisma-studio-migrations-view/imgs/hero.svg @@ -1,45 +1,132 @@ - - See what every migration changed — Prisma Studio Migrations view - The Prisma Studio Migrations view: a newest-first timeline of applied Prisma 8 migrations beside a visual diff canvas showing an added Role enum and two updated models. + + See Your Migration History in Prisma Studio + The Prisma Studio Migrations view as a white panel: six applied migrations newest first, each with its apply time, operation count and change chips, with the destructive Drop Legacy Username entry selected. Prisma blog cover, 2026 brand, prism cyan accent. - - - - - - - - + + + - - - - + + + + + + + + + + + + - - - - - - - PRISMA STUDIO - - - - - - See what every migration changed + + + + - - - + + + + + + + Migrations + + 6 + prisma_contract.ledger + - + + + + + + + + #6 + Add Category Description + Jul 16, 14:16:02 · 1 op + + ~1 model + + +1 field + + + #5 + Add Avatar + Jul 16, 14:15:46 · 1 op + + ~1 model + + +1 field + + + + #4 + Drop Legacy Username + + + + + + Jul 16, 13:57:55 · 1 op · 6d10e14 → d218a70 + + ~1 model + + -1 field + + + #3 + Add Categories + Jul 16, 13:57:30 · 7 ops + + +1 model + + +1 field + + + #2 + Add Roles And Publishing + Jul 16, 13:57:13 · 4 ops + + ~2 models + + +1 enum + + + #1 + Init Users Posts + Jul 16, 13:55:40 · 6 ops + + +2 models + + +1 index + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/apps/blog/public/prisma-studio-migrations-view/imgs/meta.png b/apps/blog/public/prisma-studio-migrations-view/imgs/meta.png index d493508da53..03f4eae0b46 100644 Binary files a/apps/blog/public/prisma-studio-migrations-view/imgs/meta.png and b/apps/blog/public/prisma-studio-migrations-view/imgs/meta.png differ diff --git a/apps/blog/public/rebuilding-the-prisma-docs/imgs/hero.png b/apps/blog/public/rebuilding-the-prisma-docs/imgs/hero.png deleted file mode 100644 index 3507429aaec..00000000000 Binary files a/apps/blog/public/rebuilding-the-prisma-docs/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/rebuilding-the-prisma-docs/imgs/hero.svg b/apps/blog/public/rebuilding-the-prisma-docs/imgs/hero.svg new file mode 100644 index 00000000000..4b3ea80ca48 --- /dev/null +++ b/apps/blog/public/rebuilding-the-prisma-docs/imgs/hero.svg @@ -0,0 +1,96 @@ + + How We Rebuilt the Prisma Docs from the Ground Up + An information architecture drawing of the rebuilt Prisma docs: a versioned entry point serving the latest docs and the v6 docs, branching into the four top level sections Getting Started, ORM, Prisma Postgres, and Guides. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /docs + + /docs/v6 + + + + + + + + + + + + + + + + + + + + Getting Started + + + + ORM + + + + Prisma Postgres + + + + Guides + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/rebuilding-the-prisma-docs/imgs/meta.png b/apps/blog/public/rebuilding-the-prisma-docs/imgs/meta.png index e8fecc8afda..a9fb4ee4b76 100644 Binary files a/apps/blog/public/rebuilding-the-prisma-docs/imgs/meta.png and b/apps/blog/public/rebuilding-the-prisma-docs/imgs/meta.png differ diff --git a/apps/blog/public/rethinking-database-migrations/imgs/hero.png b/apps/blog/public/rethinking-database-migrations/imgs/hero.png deleted file mode 100644 index 3087bb2963f..00000000000 Binary files a/apps/blog/public/rethinking-database-migrations/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/rethinking-database-migrations/imgs/hero.svg b/apps/blog/public/rethinking-database-migrations/imgs/hero.svg index 2d357f2d22b..fe7028362e2 100644 --- a/apps/blog/public/rethinking-database-migrations/imgs/hero.svg +++ b/apps/blog/public/rethinking-database-migrations/imgs/hero.svg @@ -1 +1,90 @@ - \ No newline at end of file + + Rethinking Database Migrations + A migration history graph: nodes linked by from and to schema hashes branch and rejoin, so the graph decides the apply order instead of filename timestamps. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + empty database + + + + abc123 + createTable(user) + + + + target + + + ghi789 + addColumn(user.name) + + + + def456 + addColumn(user.email) + + + + Migrations are a graph + Hashes, not timestamps, set the order. + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/rethinking-database-migrations/imgs/meta.png b/apps/blog/public/rethinking-database-migrations/imgs/meta.png index 3087bb2963f..ed766d72e6a 100644 Binary files a/apps/blog/public/rethinking-database-migrations/imgs/meta.png and b/apps/blog/public/rethinking-database-migrations/imgs/meta.png differ diff --git a/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/hero.svg b/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/hero.svg index 3ae23b05745..b4e6e4e1088 100644 --- a/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/hero.svg +++ b/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/hero.svg @@ -1,77 +1,73 @@ - - - - Search encrypted data with Prisma 8 and CipherStash - Cover showing a column of ciphertext rows in Postgres, one matched by an encrypted query, and an explicit decrypt step returning the plaintext to the application. + + Search encrypted data with Prisma 8 and CipherStash + Searchable field-level encryption: a query matching a row whose contents stay ciphertext. Prisma blog cover, 2026 brand, prism cyan accent. - - - - - - - - - - - - - - + + + + + + + + + + + - - - + + + + + + + + + Prisma 8 × CipherStash - - CIPHERSTASH FOR PRISMA 8 - - Search data - that stays - encrypted + + Search data + that stays encrypted - - - ENCRYPTED COLUMN - users.email - - - - 9c02 7d3e a41f 8b55 - - - 4fa1 b6e7 0d52 c318 - - - 71b4 05df c38e 2a90 - match - - - 2c88 e15a 7b39 f047 - - - decrypt() - - - - - - dan@example.com - + + + + where: { email: "ada@lovelace.dev" } + + mBjc…9GhQ== kX02…jw1A== + + aQ7r…Pw2g== tY55…c0Vw== ← match + + zL19…xTe8== qN37…v5Kd== - Prisma - + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/meta.png b/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/meta.png index 9e84ca29688..4fd178f91ab 100644 Binary files a/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/meta.png and b/apps/blog/public/search-encrypted-data-with-prisma-next-and-cipherstash/imgs/meta.png differ diff --git a/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/hero.png b/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/hero.png deleted file mode 100644 index f9e259892e2..00000000000 Binary files a/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/hero.png and /dev/null differ diff --git a/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/hero.svg b/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/hero.svg new file mode 100644 index 00000000000..69fe841a461 --- /dev/null +++ b/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/hero.svg @@ -0,0 +1,70 @@ + + Search the Prisma Docs Using Your Coding Agent + A search result panel for the read-only search_prisma_documentation tool on mcp.prisma.io/mcp: one question about deploying to Prisma Compute and the docs pages the cited answer comes from. Prisma blog cover, 2026 brand, prism cyan accent, no headline. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma MCP server + + + + + + + search_prisma_documentation + mcp.prisma.io/mcp + > + How do I deploy my project to Prisma Compute + + cited sources + read-only tool + + prisma.io/docs/compute/getting-started + prisma.io/docs/compute/cli-reference + prisma.io/docs/ai/tools/mcp-server + + + + + + + + + + + + + + diff --git a/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/meta.png b/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/meta.png index b166ee204ba..f300dd03b15 100644 Binary files a/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/meta.png and b/apps/blog/public/search-prisma-docs-from-your-coding-agent/imgs/meta.png differ diff --git a/apps/blog/public/serverless-postgres/imgs/hero.svg b/apps/blog/public/serverless-postgres/imgs/hero.svg index b0206a51177..60239fba4da 100644 --- a/apps/blog/public/serverless-postgres/imgs/hero.svg +++ b/apps/blog/public/serverless-postgres/imgs/hero.svg @@ -1,64 +1,82 @@ - - - - Serverless Postgres providers, compared - Prisma blog cover. Logos for Prisma Postgres, Neon, Aurora, Supabase, and PlanetScale, the five serverless Postgres providers compared in this guide. - + + Serverless Postgres: How It Works and How to Choose a Provider + Scale to zero timeline: a compute curve that suspends after five minutes idle and wakes again, against a flat always ready line. Figures from the post. Prisma blog cover, 2026 brand, prism yellow accent. - - - - + + + + + + + + + + + + - - - + + + + - - PROVIDER COMPARISON · JULY 2026 - - Serverless Postgres - providers, compared - + + + Serverless Postgres - Prisma - - - - - - Prisma Postgres - - - - - Neon + + The nap costs + a cold start + - - - - Aurora + + + + Prisma Postgres: always ready + + - - - - Supabase + + + + + + + + + Neon, default settings + 5 min idle + compute suspended + wake: a few hundred ms + + + - - - - PlanetScale + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/serverless-postgres/imgs/meta.png b/apps/blog/public/serverless-postgres/imgs/meta.png index 228051b7cc6..5f977e23603 100644 Binary files a/apps/blog/public/serverless-postgres/imgs/meta.png and b/apps/blog/public/serverless-postgres/imgs/meta.png differ diff --git a/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/hero.svg b/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/hero.svg index 7a67c467a49..fb1bc3a2c8f 100644 --- a/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/hero.svg +++ b/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/hero.svg @@ -1,105 +1,88 @@ - - - Ship risky schema changes with per-branch databases - Per-branch databases on Prisma Compute give every pull request its own database and migration history. - + + Ship risky schema changes with per-branch databases + Two branches fork off main, each into its own isolated Prisma Postgres database: one adds the displayName column, one drops the legacy name column. Prisma blog cover, 2026 brand, prism yellow accent. - - - - - - - - - + + + - - - - - + + + + + + + - - - - - - - - + + + + - - - - PRISMA COMPUTE + + + Prisma Postgres per branch - - - Ship risky schema changes - with per-branch databases + + One database + per timeline + Every branch gets its own database. - - - - - main - - - - - - - - - - - - - + + + + + - add-displayName - - - - - DB: alice - - - + + + main - remove-name - - - - DB: bob + + + Add column "displayName" + branch database + - - - expand - → - migrate - → - contract + + + Drop column "name" + branch database + - - - Prisma + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/meta.png b/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/meta.png index c28e16b9913..c4501ddf723 100644 Binary files a/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/meta.png and b/apps/blog/public/ship-risky-schema-changes-without-a-shared-staging-database/imgs/meta.png differ diff --git a/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/hero.svg b/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/hero.svg index 3c949690b8e..1b60ce3c5b7 100644 --- a/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/hero.svg +++ b/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/hero.svg @@ -1,71 +1,71 @@ - - - - Don't Let Your AI Agent Delete Your Production Database - Claude and Codex agent tiles feed into a production database whose rows are dissolving away. + + Don't Let Your AI Agent Delete Your Production Database + Prisma 8 removes the destructive failure modes structurally: no reset command, migrations that verify every step. Prisma blog cover, 2026 brand, prism cyan accent. - - - - - - - + + + + + + + + + + + - - - - - - - - + + + + + + + + + Prisma 8 - - PRISMA 8 AGENT SAFETY - - Don't let your agent - delete your database + + Your agent can't drop + what it can't reach + No reset command. No shadow database. Migrations verify every step. - - - - - - - - - - - - - - - - - - - claude - codex - production db + + + + $ prisma migrate reset --force + command does not exist in Prisma 8 + $ prisma db update + ✓ plan verified · 0 destructive steps - Prisma - + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/meta.png b/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/meta.png index 68cb49f2e34..9d33ab3aac6 100644 Binary files a/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/meta.png and b/apps/blog/public/stop-your-ai-agent-dropping-your-database/imgs/meta.png differ diff --git a/apps/blog/public/sunsetting-prisma-optimize/imgs/hero.svg b/apps/blog/public/sunsetting-prisma-optimize/imgs/hero.svg new file mode 100644 index 00000000000..770fe0beb5d --- /dev/null +++ b/apps/blog/public/sunsetting-prisma-optimize/imgs/hero.svg @@ -0,0 +1,86 @@ + + Sunsetting Prisma Optimize + A dated wind-down notice: the Prisma Optimize client extension gives way to Query Insights inside Prisma Postgres, with the one command that removes the old package. Prisma blog cover, 2026 brand, prism yellow accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Product update + + + + + + + Announced 23 March 2026 + Query observability, now built in + + + + @prisma/extension-optimize + + + + + + + + Query Insights in Prisma Postgres + + + $ npm uninstall @prisma/extension-optimize + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/sunsetting-prisma-optimize/imgs/meta.png b/apps/blog/public/sunsetting-prisma-optimize/imgs/meta.png new file mode 100644 index 00000000000..7ecbcc8f5d0 Binary files /dev/null and b/apps/blog/public/sunsetting-prisma-optimize/imgs/meta.png differ diff --git a/apps/blog/public/sunsetting-prisma-optimize/imgs/optimize-sunset.svg b/apps/blog/public/sunsetting-prisma-optimize/imgs/optimize-sunset.svg deleted file mode 100644 index c6330960e51..00000000000 --- a/apps/blog/public/sunsetting-prisma-optimize/imgs/optimize-sunset.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/blog/public/sunsetting-prisma-optimize/imgs/optimize-sunset@2x.png b/apps/blog/public/sunsetting-prisma-optimize/imgs/optimize-sunset@2x.png deleted file mode 100644 index b4d3a32caee..00000000000 Binary files a/apps/blog/public/sunsetting-prisma-optimize/imgs/optimize-sunset@2x.png and /dev/null differ diff --git a/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/hero-61773d2cc286213d32b63e59605b0f5e0df4fe52-844x474-cb41e2fab7.svg b/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/hero-61773d2cc286213d32b63e59605b0f5e0df4fe52-844x474-cb41e2fab7.svg deleted file mode 100644 index 93b96d44970..00000000000 --- a/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/hero-61773d2cc286213d32b63e59605b0f5e0df4fe52-844x474-cb41e2fab7.svg +++ /dev/null @@ -1 +0,0 @@ -Prisma 8 \ No newline at end of file diff --git a/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/hero.svg b/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/hero.svg new file mode 100644 index 00000000000..c9dd47f0cbd --- /dev/null +++ b/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/hero.svg @@ -0,0 +1,102 @@ + + The Next Evolution of Prisma ORM + A lineage of three Prisma ORM generations drawn as plates, the newest stepped up and outlined in prism cyan: Prisma 6 shipped Rust native binaries, Prisma 7 rewrote the query system, Prisma 8 is rebuilt in TypeScript and extensible by default. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma 8 + + + + + The schema stays, + the foundation changes + + + + + + + + + + + + + Prisma 6 + + + Rust native binaries + shipped in your app + + + + + + Prisma 7 + + + Query system rewritten, + recommended today + + + + + + Prisma 8 + + Early access + + + Rebuilt in TypeScript, + extensible by default + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/meta-558fe7eccfd12d3b52c325d62e5fa463a1b5f619-1200x640-3212708663.png b/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/meta-558fe7eccfd12d3b52c325d62e5fa463a1b5f619-1200x640-3212708663.png deleted file mode 100644 index 70ef1ab9fec..00000000000 Binary files a/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/meta-558fe7eccfd12d3b52c325d62e5fa463a1b5f619-1200x640-3212708663.png and /dev/null differ diff --git a/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/meta.png b/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/meta.png new file mode 100644 index 00000000000..d4b305710cd Binary files /dev/null and b/apps/blog/public/the-next-evolution-of-prisma-orm/imgs/meta.png differ diff --git a/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/hero.svg b/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/hero.svg index 30fa32d46e0..a55157e0174 100644 --- a/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/hero.svg +++ b/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/hero.svg @@ -1,79 +1,85 @@ - - - - TypeScript 7: type checking 3x faster - Whole-repo type check dropped from about 74 seconds on TypeScript 5.x to about 24 seconds on the TypeScript 7 native compiler, roughly 3x faster. + + TypeScript 7 in a Real Monorepo: 3x Faster Type Checks, Mostly Config Changes + Two proportional bars comparing a whole-repo type check on the classic compiler, TypeScript 5.8.2 at about 74 seconds, with the native compiler, TypeScript 7.0.2 at about 24 seconds, roughly 3x faster, and the Node heap flag dropping from 8 GB to none. Prisma blog cover, 2026 brand, prism cyan accent. - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + - - - - - TS - - TYPESCRIPT 7 · NATIVE COMPILER + + + One real monorepo, measured in CI - - Prisma - - - Type checking, - 3× faster + + Same TypeScript, native Go engine - The native compiler, on a real monorepo. - - - + + + + tsc 5.8.2, classic compiler + + 74s + - - - 74s - TS 5.x + + tsc 7.0.2, native Go compiler + + + 24s + + 3x faster + - - - 24s - TS 7 + node heap flag: 8 GB → none + - - - - - 3× faster - + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/meta.png b/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/meta.png index af61d742024..fc8c2038a1f 100644 Binary files a/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/meta.png and b/apps/blog/public/typescript-7-native-compiler-faster-type-checking/imgs/meta.png differ diff --git a/apps/blog/public/typescript-migrations-in-prisma-next/imgs/hero.svg b/apps/blog/public/typescript-migrations-in-prisma-next/imgs/hero.svg new file mode 100644 index 00000000000..d3bb5b196bb --- /dev/null +++ b/apps/blog/public/typescript-migrations-in-prisma-next/imgs/hero.svg @@ -0,0 +1,82 @@ + + TypeScript Migrations in Prisma 8 + An ink code card for a Prisma 8 migration.ts file, with the createTable, addUnique, createIndex and addForeignKey operations and the precheck, execute, postcheck triad. Prisma blog cover, 2026 brand, prism cyan accent. + + + + + + + + + + + + + + + + + + + + + + + + + + Prisma 8 migrations + + + + + Every step + checked twice + + Re-running a failed migration is safe. + + + + + + + + migration.ts + + override get operations() { + return [ + createTable("public", "user", [ + { name: "email", typeSql: "text" }, + ], { columns: ["id"] }), + addUnique("public", "user", + "user_email_key", ["email"]), + createIndex("public", "post", + "post_authorId_idx", ["authorId"]), + ] + } + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/typescript-migrations-in-prisma-next/imgs/meta.png b/apps/blog/public/typescript-migrations-in-prisma-next/imgs/meta.png new file mode 100644 index 00000000000..0138f6ae3cf Binary files /dev/null and b/apps/blog/public/typescript-migrations-in-prisma-next/imgs/meta.png differ diff --git a/apps/blog/public/typescript-migrations-in-prisma-next/imgs/typescript-migrations-in-prisma-next.png b/apps/blog/public/typescript-migrations-in-prisma-next/imgs/typescript-migrations-in-prisma-next.png deleted file mode 100644 index 37b917d788e..00000000000 Binary files a/apps/blog/public/typescript-migrations-in-prisma-next/imgs/typescript-migrations-in-prisma-next.png and /dev/null differ diff --git a/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/hero.svg b/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/hero.svg index 3b52226d3a0..2c30a643248 100644 --- a/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/hero.svg +++ b/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/hero.svg @@ -1,106 +1,72 @@ - - - - You Don't Need a Job Queue, Postgres Already Has SKIP LOCKED - Two workers claim different rows from a Postgres jobs table. Worker 1 holds a locked row; worker 2 skips it and claims the next one. + + You Don't Need a Job Queue, Postgres Already Has SKIP LOCKED + Ink SQL card holding the claim query from the post, with FOR UPDATE SKIP LOCKED highlighted in prism yellow. Prisma blog cover, 2026 brand, prism yellow accent. - - - - - - - - + + + - - - - - - - - + + + + + + + - - - - - - + + + + - - - POSTGRES FEATURES + + + Postgres job queues - You don't need a job queue, - Postgres has SKIP LOCKED + The job queue + is a table + Ten workers claim ten different rows. - - - - jobs - - - - - 1 - send-email - - - - - running - - - - - 2 - deliver-webhook - running - - - 3 - generate-export - pending - - - 4 - sync-crm - pending - - - - worker-1 - - - worker-2 - - - - - - - - - + + + + + SELECT * FROM jobs + WHERE status = 'pending' + ORDER BY id + FOR UPDATE SKIP LOCKED + LIMIT 1; - - - Prisma + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/meta.png b/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/meta.png index 2a571a757a1..a6fa82c0b80 100644 Binary files a/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/meta.png and b/apps/blog/public/you-dont-need-a-job-queue-postgres-already-has-skip-locked/imgs/meta.png differ diff --git a/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/hero.svg b/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/hero.svg index ba8dc3507d8..8e8b50526d0 100644 --- a/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/hero.svg +++ b/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/hero.svg @@ -1,86 +1,99 @@ - - - - You Don't Need a Vector Database, Postgres Already Has pgvector - A vector plane with movie embeddings as rays from an origin. The teal query ray sits closest to The Terminator (cosine similarity 0.999), then Alien (0.975) and Mad Max (0.972); the romance cluster points away. Header reads ORDER BY embedding <=> $1 LIMIT 3. + + You Don't Need a Vector Database, Postgres Already Has pgvector + Embedding field: the post's movie vectors plotted on the action and scifi axes, with The Terminator as the query point linked to its nearest neighbours. Prisma blog cover, 2026 brand, prism yellow accent. - - - - + + + + + + + + + + + + + + + - - - + + + + - - - POSTGRES FEATURES · PART 3 - - Vector search, - already in Postgres - - pgvector + Prisma 8, typed from schema to query + + + Postgres and pgvector - - - ORDER BY embedding <=> $1 LIMIT 3 - - - - - + + Similarity search + is a SELECT + cosine distance, closest rows first + 4 axes here, 1,536 in production + - - - - - Notting Hill - - - Her + + + + + + - - - - - - Alien - 0.975 - - - - Mad Max - 0.972 - - - - Terminator - 0.999 + + - - - - - - query + + + + + + + + + + + + + + + The Terminator + Alien + Mad Max + Notting Hill + Her + Hot Fuzz + action + scifi - - - Prisma + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/meta.png b/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/meta.png index 46afa532411..9caa34f80ed 100644 Binary files a/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/meta.png and b/apps/blog/public/you-dont-need-a-vector-database-postgres-already-has-pgvector/imgs/meta.png differ diff --git a/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/hero.svg b/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/hero.svg index 6336e337bd0..85a7dc862cb 100644 --- a/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/hero.svg +++ b/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/hero.svg @@ -1,103 +1,79 @@ - - - - You Don't Need Elasticsearch, Postgres Already Has Full-Text Search - A search query typed into an input, with three results ranked by ts_rank score bars, fed by a tsvector column and GIN index. + + You Don't Need Elasticsearch, Postgres Already Has Full-Text Search + Replacement diagram: a struck-out Elasticsearch tile above an accent-filled Postgres tile carrying tsvector and a GIN index. Prisma blog cover, 2026 brand, prism yellow accent. - - - - - - - - + + + - - - - - - - - + + + + + + + - - - - - - - - - - - - - - + + + + - - - POSTGRES FEATURES + + + Postgres full-text search - You don't need Elasticsearch, - Postgres has full-text search + The search index + is a column + websearch_to_tsquery · ts_rank · pg_trgm - - - - - - - - - + + + + + Elasticsearch + + a second system to keep in sync + + + + + + + + Postgres + tsvector + GIN index - speed up postgres queries - - - ORDER BY ts_rank DESC - - - - - 0.91 - Speeding up Postgres queries - - - - - 0.55 - Query plans explained - - - - - 0.18 - Intro to SQL basics - - - - - - tsvector + GIN - - - Prisma + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/meta.png b/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/meta.png index 9639a64e132..66c19204a00 100644 Binary files a/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/meta.png and b/apps/blog/public/you-dont-need-elasticsearch-postgres-already-has-full-text-search/imgs/meta.png differ diff --git a/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/hero.svg b/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/hero.svg new file mode 100644 index 00000000000..ce81919bf95 --- /dev/null +++ b/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/hero.svg @@ -0,0 +1,94 @@ + + You Don't Need Redis, Postgres Already Has Pub/Sub + Pub/Sub flow: a publisher running NOTIFY into the app_events channel, fanning out to two connections holding LISTEN app_events. Prisma blog cover, 2026 brand, prism yellow accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Postgres Pub/Sub + + + + Real time + is two commands + + + + + + + publisher + NOTIFY app_events + + + + + + + + channel + app_events + + + + + + + + + + subscriber + LISTEN app_events + + subscriber + LISTEN app_events + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/meta.png b/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/meta.png new file mode 100644 index 00000000000..20dc86e0e70 Binary files /dev/null and b/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/meta.png differ diff --git a/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/you-dont-need-redis-postgres-already-has-pub-sub.png b/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/you-dont-need-redis-postgres-already-has-pub-sub.png deleted file mode 100644 index c1567469395..00000000000 Binary files a/apps/blog/public/you-dont-need-redis-postgres-already-has-pub-sub/imgs/you-dont-need-redis-postgres-already-has-pub-sub.png and /dev/null differ diff --git a/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/hero.jpg b/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/hero.jpg deleted file mode 100644 index 851ef9e108c..00000000000 Binary files a/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/hero.jpg and /dev/null differ diff --git a/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/hero.svg b/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/hero.svg new file mode 100644 index 00000000000..3ba9069f5cf --- /dev/null +++ b/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/hero.svg @@ -0,0 +1,103 @@ + + Your Database Might Not Be the Bottleneck + Request composition bars for the post's two apps: the query segment is identical in both, while the slow version spends its time on middleware, URL parsing and serialization. Schematic, no timings. Prisma blog cover, 2026 brand, prism yellow accent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + slow version + + + + + + + + + middleware + new URL() + JSON.stringify() + query + + + fast version + + + + + + + handler + query + + + + + app work + + query + same routes, same ORM, same queries + + + + + + API performance + + + + Slow before + the query runs + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/meta.png b/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/meta.png index 2961d5e5b19..235fd66093b 100644 Binary files a/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/meta.png and b/apps/blog/public/your-database-might-not-be-the-bottleneck/imgs/meta.png differ diff --git a/apps/blog/scripts/update-posthog-blog-tiles.mjs b/apps/blog/scripts/update-posthog-blog-tiles.mjs index 22925c71c33..3f0254cfd89 100644 --- a/apps/blog/scripts/update-posthog-blog-tiles.mjs +++ b/apps/blog/scripts/update-posthog-blog-tiles.mjs @@ -146,7 +146,11 @@ function recentPostsQuery(slugs) { `coalesce(pv.visitors, 0) AS visitors, row_number() OVER (ORDER BY coalesce(pv.pageviews, 0) DESC) AS rank, ` + `count() OVER () AS total FROM recent LEFT JOIN pv ON pv.path = concat('/blog/', recent.slug)) ` + `ORDER BY rank LIMIT 100`; - return { kind: "DataVisualizationNode", display: "ActionsTable", source: { kind: "HogQLQuery", query } }; + return { + kind: "DataVisualizationNode", + display: "ActionsTable", + source: { kind: "HogQLQuery", query }, + }; } async function patchInsight(id, query) { @@ -182,7 +186,9 @@ if (process.argv.includes("--dry-run")) { } if (!process.env.POSTHOG_API_KEY) { - console.error("Error: POSTHOG_API_KEY is not set. Set the repo secret, or pass --dry-run to preview."); + console.error( + "Error: POSTHOG_API_KEY is not set. Set the repo secret, or pass --dry-run to preview.", + ); process.exit(1); } diff --git a/apps/blog/src/app/(blog)/[slug]/page.tsx b/apps/blog/src/app/(blog)/[slug]/page.tsx index 0effbcee200..6a55c05e6ce 100644 --- a/apps/blog/src/app/(blog)/[slug]/page.tsx +++ b/apps/blog/src/app/(blog)/[slug]/page.tsx @@ -4,7 +4,7 @@ import { notFound } from "next/navigation"; import { getMDXComponents } from "@/mdx-components"; import { createRelativeLink } from "fumadocs-ui/mdx"; import { blog } from "@/lib/source"; -import { Badge, InlineTOC, Separator } from "@prisma/eclipse"; +import { InlineTOC, Separator } from "@prisma/eclipse"; import { JsonLd } from "@prisma-docs/ui/components/json-ld"; import { BlogShare } from "@/components/BlogShare"; @@ -17,12 +17,12 @@ import { SeriesBanner } from "@/components/SeriesBanner"; import { SeriesMarker } from "@/components/SeriesMarker"; import { SeriesNavigation } from "@/components/SeriesNavigation"; import { KeepReading } from "@/components/KeepReading"; +import { BackToBlogLink } from "@/components/BackToBlogLink"; import { getSeriesContext } from "@/lib/series"; import { getRelatedPosts } from "@/lib/related-posts"; import { getBaseUrl, withBlogBasePath, withBlogBasePathForImageSrc } from "@/lib/url"; import Link from "next/link"; import type { Metadata } from "next"; -import { cn } from "@prisma-docs/ui/lib/cn"; interface TOCItem { title: string; @@ -182,20 +182,24 @@ export default async function Page(props: { params: Promise<{ slug: string }> }) const relatedPosts = seriesContext ? [] : getRelatedPosts(page, 2); return ( -
+
{blogPostingJsonLd ? ( ) : null}
- {/* Title + meta */} -
- - ← Back to Blog - -

+ {/* Title + meta — CF's post header: back link, display title, muted + dek, then the byline row. */} +
+ +

{page.data.title}

-
+ {page.data.excerpt ? ( +

+ {page.data.excerpt} +

+ ) : null} +
{page.data.date ? ( <> @@ -215,22 +219,18 @@ export default async function Page(props: { params: Promise<{ slug: string }> }) ) : null}
{page.data.tags && page.data.tags.length > 0 && ( -
+ // Same ghost pill as the home page's category chips, so a tag reads + // identically wherever it appears. Hover is the docs shell's accent + // wash (`fd-accent` = cyan-100 light / cyan-950 dark) rather than a + // grey tint, so pointing at a pill answers in the brand hue. +
{page.data?.tags?.map((tag) => ( - - + + {formatTag(tag)} ))}
@@ -239,12 +239,8 @@ export default async function Page(props: { params: Promise<{ slug: string }> })
{/* Body */} -
+
- {page.data.excerpt ? ( -

{page.data.excerpt}

- ) : null} - }) {/* Share Container */}
-
-
- +
+ {/* InlineTOC ships the docs shell's own treatment — cyan `fd-primary` + rail segment and `fd-accent-foreground` text on the active item, + cyan hover on the rest — via the same variables this app remaps in + global.css. No overrides, so the blog TOC reads exactly like the + docs TOC in both modes. */} +
+ On this page diff --git a/apps/blog/src/app/(blog)/author/[slug]/page.tsx b/apps/blog/src/app/(blog)/author/[slug]/page.tsx index 1dcbd6a33dc..7039b2e958a 100644 --- a/apps/blog/src/app/(blog)/author/[slug]/page.tsx +++ b/apps/blog/src/app/(blog)/author/[slug]/page.tsx @@ -1,5 +1,4 @@ import { notFound } from "next/navigation"; -import Link from "next/link"; import type { Metadata } from "next"; import { Avatar } from "@prisma/eclipse"; @@ -11,6 +10,7 @@ import { getAuthorBioBySlug } from "@/lib/author-bios"; import { getBaseUrl, withBlogBasePath, withBlogBasePathForImageSrc } from "@/lib/url"; import { AuthorSocialLinks } from "@/components/AuthorBio"; import { BlogGrid, type BlogCardItem } from "@/components/BlogGrid"; +import { BackToBlogLink } from "@/components/BackToBlogLink"; import { BLOG_HOME_TITLE } from "@/lib/blog-metadata"; export const revalidate = false; @@ -94,24 +94,30 @@ export default async function AuthorPage(props: { params: Promise +
- - ← Back to Blog - - -
- {avatarSrc ? : null} + + + {/* Author identity block on a paper panel — the one surface change that + separates "who wrote this" from the feed of what they wrote. */} +
+ {avatarSrc ? ( +
+ +
+ ) : null}
-
+
Author · {items.length} {items.length === 1 ? "post" : "posts"}
-

+

{profile.name}

- {bio ?

{bio.bio}

: null} {bio ? ( - +

{bio.bio}

+ ) : null} + {bio ? ( + ) : null}
diff --git a/apps/blog/src/app/(blog)/layout.tsx b/apps/blog/src/app/(blog)/layout.tsx index f5799a6d14d..0f062fa1554 100644 --- a/apps/blog/src/app/(blog)/layout.tsx +++ b/apps/blog/src/app/(blog)/layout.tsx @@ -1,6 +1,6 @@ -import { Footer } from "@prisma-docs/ui/components/footer"; import { FooterNewsletterForm } from "@prisma-docs/ui/components/newsletter"; import { ThemeProvider } from "@prisma-docs/ui/components/theme-provider"; +import { Footer } from "@/components/chrome/Footer"; import { NavigationWrapper } from "@/components/navigation-wrapper"; import { UtmPersistence } from "@/components/utm-persistence"; import { withBlogBasePath } from "@/lib/url"; @@ -110,7 +110,6 @@ export default function Layout({ children }: { children: React.ReactNode }) { {children}
} diff --git a/apps/blog/src/app/(blog)/page.tsx b/apps/blog/src/app/(blog)/page.tsx index 6099486cb88..ec39928bb51 100644 --- a/apps/blog/src/app/(blog)/page.tsx +++ b/apps/blog/src/app/(blog)/page.tsx @@ -151,17 +151,41 @@ export default async function BlogHome() { }); return ( -
-

- Blog -

+ // Site width (1400px) — the same container the rebranded marketing pages + // use, so the blog's grid lines up with the rest of prisma.io. +
+ {/* CF's centered hero on calm prismatic ground: spectral washes only. + The page's single ray lives on the featured-series card below — one + brand moment per view, and a diagonal band can't safely cross + centered text at every breakpoint anyway. Static by design. */} +
+
+
+
+

Blog

+

+ {BLOG_HOME_DESCRIPTION} +

+
{/* * Suspense is required here because BlogHomeClient uses useSearchParams(). * During static pre-rendering Next.js renders the fallback; after hydration * the client component takes over and applies URL-driven filtering instantly * since all post data is already present in the RSC payload. */} - }> + }> - - ← Back to Blog - +
+ -
-
+
+
Series · {items.length} {items.length === 1 ? "part" : "parts"}
-

+

{meta.title}

{meta.description ? ( -

{meta.description}

+

+ {meta.description} +

) : null} {meta.docsUrl ? ( {meta.docsLabel ?? "Read the docs"} → @@ -99,14 +100,14 @@ export default async function SeriesPage(props: { params: Promise +
Related series:{" "} {related.map((relKey, i) => ( {i > 0 ? ", " : ""} {getSeriesMetadata(relKey).title} diff --git a/apps/blog/src/app/(blog)/series/page.tsx b/apps/blog/src/app/(blog)/series/page.tsx index 518c705eeae..e7201bfc49b 100644 --- a/apps/blog/src/app/(blog)/series/page.tsx +++ b/apps/blog/src/app/(blog)/series/page.tsx @@ -1,10 +1,10 @@ import type { Metadata } from "next"; -import Link from "next/link"; import { blog } from "@/lib/source"; import { getSeriesMetadata, seriesRegistry } from "@/lib/series-registry"; import { withBlogBasePath } from "@/lib/url"; import { SeriesIndexGrid, type SeriesShelfItem } from "@/components/SeriesShelf"; +import { BackToBlogLink } from "@/components/BackToBlogLink"; import { BLOG_HOME_TITLE } from "@/lib/blog-metadata"; export const revalidate = false; @@ -60,16 +60,18 @@ export default function SeriesIndexPage() { }); return ( -
- - ← Back to Blog - -
-
+
+ +
+
{items.length} {items.length === 1 ? "series" : "series"}
-

{PAGE_TITLE}

-

{PAGE_DESCRIPTION}

+

+ {PAGE_TITLE} +

+

+ {PAGE_DESCRIPTION} +

diff --git a/apps/blog/src/app/apple-icon.png b/apps/blog/src/app/apple-icon.png new file mode 100644 index 00000000000..d1151a98960 Binary files /dev/null and b/apps/blog/src/app/apple-icon.png differ diff --git a/apps/blog/src/app/favicon.ico b/apps/blog/src/app/favicon.ico index e7ed74352af..42d94e9aa16 100644 Binary files a/apps/blog/src/app/favicon.ico and b/apps/blog/src/app/favicon.ico differ diff --git a/apps/blog/src/app/global.css b/apps/blog/src/app/global.css index a2527266d86..1fb62c0489f 100644 --- a/apps/blog/src/app/global.css +++ b/apps/blog/src/app/global.css @@ -4,10 +4,232 @@ @import "fumadocs-ui/css/preset.css"; @import "@prisma-docs/ui/styles"; +/* Wire next/font/local preloaded fonts into the design-token variables. + Declared after the @import so this :root wins on cascade order (same + specificity, later position). The bare family name after each variable is + the @font-face from the package's fonts.css — it both backstops a missing + next/font variable and supplies the subsets next/font does not preload + (Sora latin-ext). */ :root { - --color-fd-primary: var(--color-stroke-ppg); + --font-sans-display: + var(--font-sora, "Sora"), "Sora", "Inter", "Roboto", "Helvetica Neue", "Arial Nova", + "Nimbus Sans", "Arial", sans-serif; + --font-sans: + var(--font-inter, "Inter"), "Inter", "Roboto", "Helvetica Neue", "Arial Nova", "Nimbus Sans", + "Arial", sans-serif; + --font-mono: + var(--font-mona-mono, "Mona Sans Mono VF"), ui-monospace, "Cascadia Code", "Source Code Pro", + "Menlo", "Consolas", "DejaVu Sans Mono", monospace; +} + +/* Brand heading rule: display face, Medium weight, natural tracking on every + heading. Deliberately unlayered — fumadocs' `prose` typography emits into + @layer utilities with its own heading weights (800/700/600), and unlayered + declarations outrank every layer regardless of specificity. */ +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: var(--font-sans-display); + font-weight: 500; + letter-spacing: normal; +} + +/* Inter's brand body weight. `@prisma/eclipse` sets this in @layer base, but + `fumadocs-ui/css/preset.css` is imported after it and also writes `body` in + the same layer, so it is restated unlayered here to survive that. */ +body { + font-weight: 380; +} + +/* `.stretch-display` (from `@prisma-docs/ui`, out of scope for this rebrand) + drives the Mona Sans VF `wdth`/`wght` axes. Sora has neither, so the axis + settings are cleared and the brand display weight applied instead. */ +.stretch-display { + font-variation-settings: normal; + font-weight: 500; +} + +/* --------------------------------------------------------------------------- + App chrome retheme — remap the shadcn/fumadocs shell variables onto prism. + + `@prisma-docs/ui` (out of scope for this rebrand: apps/site, apps/blog and + apps/docs consume it) still ships the previous identity in these variables — + teal accents, a blue-navy dark surface, and cool blue-gray text. The + package cannot be edited, so the app remaps the same variable names here. + Every `--color-fd-*` alias fumadocs reads is defined by + `fumadocs-ui/css/shadcn.css` as `var(--)` against exactly these + variables, so overriding the base set carries the whole shell: post prose + (fumadocs' typography plugin resolves every `--tw-prose-*` colour off + `--color-fd-foreground`/`-border`/`-muted-foreground`), TOC, popovers, + search dialog, buttons. + + Placement and shape matter. These blocks sit after the @imports so they win + on source order at equal specificity, and `:root` and `.dark` are BOTH + declared in full: an unpaired `:root` here would also outrank the package's + earlier `.dark`, leaking light values into dark mode. + + Values are eclipse tokens, never literals, so the shell tracks the package. +--------------------------------------------------------------------------- */ +:root { + /* CF's base radius is 10px; fumadocs derives sm/md/xl/2xl.. from this. */ + --radius: 0.625rem; + + --background: var(--color-background-default); /* #ffffff */ + --foreground: var(--color-foreground-neutral); /* #3a3b3c */ + --card: var(--color-background-default); + --card-foreground: var(--color-foreground-neutral); + --popover: var(--color-background-default); + --popover-foreground: var(--color-foreground-neutral); + + /* Brand accent: TOC thumb + active link, prose kbd shadow, active tab + underline. `bg-fd-primary/10` derives the active-item tint. */ + --primary: var(--color-prism-cyan-600); /* #009aaa */ + --primary-foreground: #ffffff; + + --secondary: var(--color-background-neutral-weak); /* paper #f9faf5 */ + --secondary-foreground: var(--color-foreground-neutral); + --muted: var(--color-background-neutral); /* #f5f5f4 */ + --muted-foreground: var(--color-foreground-neutral-weak); /* #646567 */ + + /* Hover wash + hover text. cyan-100 holds the luminance the previous teal + tint had, so hover feedback keeps its weight and only changes hue. */ + --accent: var(--color-prism-cyan-100); /* #dcfdff */ + --accent-foreground: var(--color-prism-cyan-700); /* #007f8d */ + + --destructive: var(--color-foreground-error); /* prism red #d02344 */ + --border: var(--color-stroke-neutral); /* #e5e5e4 */ + --input: var(--color-stroke-neutral); + --ring: var(--color-prism-cyan-600); + + /* Chart ramp — cyan first, the supporting prism hues after it. Nothing in + the blog charts today; kept in agreement so nothing can fall back to the + package's teal/indigo pair. */ + --chart-1: var(--color-prism-cyan-500); + --chart-2: var(--color-prism-yellow-400); + --chart-3: var(--color-prism-red-500); + --chart-4: var(--color-prism-cyan-700); + --chart-5: var(--color-prism-yellow-600); + + /* The blog has no sidebar, but fumadocs' shadcn preset aliases + `--color-fd-sidebar*` off these regardless; kept on-brand so no component + that reaches for one gets the old palette. */ + --sidebar: var(--color-background-default); + --sidebar-foreground: var(--color-foreground-neutral); + --sidebar-primary: var(--color-prism-cyan-600); + --sidebar-primary-foreground: #ffffff; + --sidebar-accent: var(--color-prism-cyan-100); + --sidebar-accent-foreground: var(--color-prism-cyan-700); + --sidebar-border: var(--color-stroke-neutral); + --sidebar-ring: var(--color-prism-cyan-600); +} + +.dark { + /* The neutral dark ramp, chroma-0 off the brand ink — not the old blue-gray. */ + --background: var(--color-background-default); /* #0f0f0f */ + --foreground: var(--color-foreground-neutral); /* #f5f5f4 */ + --card: var(--color-background-neutral-weak); /* #1a1a1a */ + --card-foreground: var(--color-foreground-neutral); + --popover: var(--color-background-neutral-weak); + --popover-foreground: var(--color-foreground-neutral); + + /* Cyan lifts to 400 on dark for legible accents; its foreground goes to ink, + because white on #01d7e4 does not carry. */ + --primary: var(--color-prism-cyan-400); /* #01d7e4 */ + --primary-foreground: var(--color-background-default); /* #0f0f0f */ + + --secondary: var(--color-background-neutral); /* #232323 */ + --secondary-foreground: var(--color-foreground-neutral); + --muted: var(--color-background-neutral); /* #232323 */ + --muted-foreground: var(--color-foreground-neutral-weak); /* #a5a5a6 */ + + --accent: var(--color-prism-cyan-950); /* #00353c */ + --accent-foreground: var(--color-prism-cyan-300); /* #7be7f0 */ + + --destructive: var(--color-foreground-error); /* prism red #f34a60 */ + --border: var(--color-stroke-neutral); /* #2a2a2a */ + --input: var(--color-stroke-neutral); + --ring: var(--color-prism-cyan-400); + + --chart-1: var(--color-prism-cyan-400); + --chart-2: var(--color-prism-yellow-300); + --chart-3: var(--color-prism-red-400); + --chart-4: var(--color-prism-cyan-200); + --chart-5: var(--color-prism-yellow-500); + + --sidebar: var(--color-background-default); + --sidebar-foreground: var(--color-foreground-neutral); + --sidebar-primary: var(--color-prism-cyan-400); + --sidebar-primary-foreground: var(--color-background-default); + --sidebar-accent: var(--color-prism-cyan-950); + --sidebar-accent-foreground: var(--color-prism-cyan-300); + --sidebar-border: var(--color-stroke-neutral); + --sidebar-ring: var(--color-prism-cyan-400); +} + +/* --------------------------------------------------------------------------- + Article prose — the brand reading surface on top of fumadocs' typography. + Colour comes from the `--color-fd-*` remap above; these rules only carry the + moves the plugin has no variable for. +--------------------------------------------------------------------------- */ + +/* Links stay ink — never a coloured label — over a quiet cyan hairline that + firms up on hover. This is the flat-surface reading of `.spectrum-underline` + (which needs a pseudo-element the prose plugin has already spent), and the + rule keeps a resting underline rather than a hover-only one: in body copy an + ink link with no persistent decoration is indistinguishable from bold text. + The plugin's own hover is `opacity: 80%`, i.e. the link fades as you point + at it; that is reversed here so it strengthens instead. + `[data-card]` links are whole card surfaces and opt out, as upstream. */ +.prose a:not([data-card]) { + text-decoration: underline; + text-decoration-color: color-mix(in srgb, var(--color-prism-cyan-500) 45%, transparent); + text-decoration-thickness: 1.5px; + text-underline-offset: 3.5px; + transition: text-decoration-color 300ms ease; +} + +.prose a:not([data-card]):hover { + opacity: 1; + text-decoration-color: var(--color-prism-cyan-500); +} + +@media (prefers-reduced-motion: reduce) { + .prose a:not([data-card]) { + transition: none; + } +} + +/* Pull quotes: a 2px cyan rule on paper, upright rather than italic — the + plugin's default is a 4px border-coloured rule with no surface. */ +.prose blockquote { + border-inline-start-width: 2px; + border-inline-start-color: var(--color-prism-cyan-400); + background: var(--color-paper); + border-radius: 0 var(--radius-square) var(--radius-square) 0; + padding: 0.875em 1.25em; + font-style: normal; + font-weight: 400; +} + +.prose blockquote p:first-of-type::before, +.prose blockquote p:last-of-type::after { + content: none; +} + +.prose hr { + border-color: var(--color-stroke-neutral); } +/* --------------------------------------------------------------------------- + Page surface. White page with a quiet paper wash resting under the top of + the document — prism accents are reserved for small details, so the former + full-width cyan bleed is gone. The footer closes on the same paper tone + (see chrome/Footer), so every page opens and closes one quiet step off the + page surface, the way the docs' paper sidebar frames its pages. +--------------------------------------------------------------------------- */ .bg-blog { background-color: var(--color-background-default); } @@ -18,31 +240,36 @@ top: 0; left: 0; width: 100%; - height: 5000px; + height: 640px; background: linear-gradient( - 0deg, - var(--color-background-default) 95%, - var(--color-background-ppg) 100% + 180deg, + var(--color-paper) 0%, + color-mix(in srgb, var(--color-paper) 45%, var(--color-background-default)) 55%, + var(--color-background-default) 100% ); z-index: -1; } +/* Hero display type: Sora Medium, natural tracking. The old rule ran weight + 900 with a `wdth` 125 axis — both Mona Sans VF axes that Sora does not + have, so they are dropped rather than silently ignored. */ .landing-h1 { color: var(--color-foreground-neutral); font-variant-numeric: lining-nums tabular-nums slashed-zero; - font-variation-settings: "wdth" 125; - /* title/3xl */ font-family: var(--font-sans-display); - font-size: 60px; + font-size: clamp(2.5rem, 6vw, 3.75rem); font-style: normal; - font-weight: 900; - line-height: 120%; /* 120% */ + font-weight: 500; + letter-spacing: normal; + line-height: 1.1; } +/* Newsletter panel: a mode-aware cyan wash (`--color-background-ppg` is + #eeffff light / #00353c dark) fading to the page surface. */ .newsletter-bg { background: linear-gradient( 59deg, - color-mix(in srgb, var(--color-foreground-ppg) 30%, transparent) 6.53%, + var(--color-background-ppg) 6.53%, var(--color-background-default) 74.71% ); } @@ -89,6 +316,14 @@ } } +/* --------------------------------------------------------------------------- + Codehike syntax tokens. Syntax highlighting is not brand surface — a code + theme is a legibility instrument with its own semantics (keyword / string / + comment), and recolouring it to prism would cost meaning and gain nothing. + These are left on the GitHub light/dark palette deliberately; the container + chrome around them is what carries the brand (see the demo frames below and + eclipse's own `CodeBlock`). +--------------------------------------------------------------------------- */ :root { --ch-1: #6e7781; --ch-2: #0550ae; @@ -115,16 +350,27 @@ --ch-16: transparent; } +/* The demo widgets below (agent prompt, bloom filter, runner, b-tree, hash, + sequence diagram, vector space) all followed one off-brand green accent + with GitHub-dark terminal chrome. They now run on prism: cyan is + the working accent, yellow reads as "caution", red as "no match". Anything + that must stay a literal is called out where it appears. */ .agent-prompt { - --agent-prompt-code-light-bg: #ffffff; - --agent-prompt-code-dark-bg: #24292e; - --agent-prompt-terminal-bg: #0c0e10; - --agent-prompt-terminal-fg: #e6e6e6; - --agent-prompt-terminal-muted: #8b949e; - --agent-prompt-terminal-prefix: #5fb878; - --agent-prompt-terminal-stroke: #1f242a; - --agent-prompt-mark-bg: color-mix(in srgb, #5fb878 14%, transparent); - --agent-prompt-mark-border: #5fb878; + /* Code frame sits on paper — #f9faf5 light, #1a1a1a dark — so one + mode-aware token replaces the old light/dark background pair. */ + --agent-prompt-code-bg: var(--color-paper); + /* The terminal is always dark, in either theme, so its chrome cannot use + the mode-aware tokens. These four literals are the eclipse DARK ramp + (background-default / foreground-neutral / -weak / stroke-neutral). */ + --agent-prompt-terminal-bg: #0f0f0f; + --agent-prompt-terminal-fg: #f5f5f4; + --agent-prompt-terminal-muted: #a5a5a6; + --agent-prompt-terminal-stroke: #2a2a2a; + /* Shell prompt on that always-dark surface: cyan-400 is the dark-mode + accent step and is mode-independent. */ + --agent-prompt-terminal-prefix: var(--color-prism-cyan-400); + --agent-prompt-mark-bg: color-mix(in srgb, var(--color-foreground-ppg) 14%, transparent); + --agent-prompt-mark-border: var(--color-foreground-ppg); display: flex; flex-direction: column; gap: 14px; @@ -137,7 +383,7 @@ flex-direction: column; gap: 10px; padding: 20px 22px; - border-radius: 12px; + border-radius: var(--radius-square-high); border: 1px solid var(--color-stroke-neutral); background: var(--color-background-default); box-shadow: @@ -164,7 +410,7 @@ font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); } .agent-prompt-tag::before { @@ -219,17 +465,13 @@ position: relative; display: flex; flex-direction: column; - border-radius: var(--radius-square, 6px); + border-radius: var(--radius-square); border: 1px solid var(--color-stroke-neutral); - background: var(--agent-prompt-code-light-bg); + background: var(--agent-prompt-code-bg); overflow: hidden; transition: box-shadow 320ms ease; } -.dark .agent-prompt-frame { - background: var(--agent-prompt-code-dark-bg); -} - .agent-prompt-skill { display: inline-flex; align-items: center; @@ -269,7 +511,7 @@ font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-size: 0.6875rem; } @@ -290,7 +532,7 @@ padding: 8px 14px; font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 0.75rem; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); border-bottom: 1px solid var(--color-stroke-neutral); } @@ -306,9 +548,9 @@ justify-content: center; width: 22px; height: 22px; - border-radius: 4px; + border-radius: var(--radius-square-low); background: transparent; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); cursor: pointer; transition: background-color 120ms ease, @@ -425,7 +667,7 @@ .agent-prompt-terminal { display: flex; flex-direction: column; - border-radius: var(--radius-square, 6px); + border-radius: var(--radius-square); border: 1px solid var(--agent-prompt-terminal-stroke); background: var(--agent-prompt-terminal-bg); color: var(--agent-prompt-terminal-fg); @@ -450,21 +692,24 @@ gap: 6px; } +/* Window dots. The macOS traffic-light hues are replaced by the prism triad — + red, yellow, cyan — which lands in the same positions and reads as the same + affordance without borrowing another vendor's palette. */ .agent-prompt-terminal-dots span { width: 9px; height: 9px; - border-radius: 999px; - background: #3a4148; + border-radius: var(--radius-circle); + background: color-mix(in srgb, var(--agent-prompt-terminal-fg) 22%, transparent); } .agent-prompt-terminal-dots span:nth-child(1) { - background: #ff5f57; + background: var(--color-prism-red-500); } .agent-prompt-terminal-dots span:nth-child(2) { - background: #febc2e; + background: var(--color-prism-yellow-400); } .agent-prompt-terminal-dots span:nth-child(3) { - background: #28c840; + background: var(--color-prism-cyan-400); } .agent-prompt-terminal-title { @@ -520,19 +765,22 @@ .bloom-demo { --bloom-cell-empty: var(--color-background-default); - --bloom-cell-empty-fg: var(--color-foreground-muted); - --bloom-cell-on-bg: color-mix(in srgb, #5fb878 22%, transparent); - --bloom-cell-on-border: #5fb878; + --bloom-cell-empty-fg: var(--color-foreground-neutral-weak); + --bloom-cell-on-bg: color-mix(in srgb, var(--color-foreground-ppg) 22%, transparent); + --bloom-cell-on-border: var(--color-foreground-ppg); --bloom-cell-on-fg: var(--color-foreground-neutral); - --bloom-cell-probe-present: #5fb878; - --bloom-cell-probe-absent: #d2a8ff; - --bloom-cell-probe-fp: #ffa657; - --bloom-cell-flipping-shadow: 0 0 0 3px color-mix(in srgb, #5fb878 35%, transparent); + /* The three verdicts map onto the prism triad by meaning: cyan = hit, + red = definitely absent, yellow = false positive (caution). */ + --bloom-cell-probe-present: var(--color-foreground-ppg); + --bloom-cell-probe-absent: var(--color-prism-red-500); + --bloom-cell-probe-fp: var(--color-prism-yellow-400); + --bloom-cell-flipping-shadow: 0 0 0 3px + color-mix(in srgb, var(--color-foreground-ppg) 35%, transparent); margin: 1.75rem 0; display: flex; flex-direction: column; border: 1px solid var(--color-stroke-neutral); - border-radius: 10px; + border-radius: var(--radius-square-high); background: var(--color-background-default); overflow: hidden; } @@ -554,7 +802,7 @@ padding: 2px 8px; border-radius: 999px; background: color-mix(in srgb, var(--color-foreground-ppg) 12%, transparent); - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-size: 0.6875rem; letter-spacing: 0.06em; } @@ -570,9 +818,9 @@ justify-content: center; width: 24px; height: 24px; - border-radius: 5px; + border-radius: var(--radius-square-low); background: transparent; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); cursor: pointer; } @@ -597,7 +845,7 @@ padding: 14px 0; border-right: 1px solid var(--color-stroke-neutral); font: normal 400 0.8125rem/1.7 var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); - background: var(--color-background-subtle, transparent); + background: var(--color-paper); min-height: 220px; } @@ -645,7 +893,7 @@ flex-direction: column; align-items: center; justify-content: center; - border-radius: 6px; + border-radius: var(--radius-square-low); border: 1px solid var(--color-stroke-neutral); background: var(--bloom-cell-empty); color: var(--bloom-cell-empty-fg); @@ -710,7 +958,7 @@ .bloom-demo-caption { font-size: 0.875rem; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); line-height: 1.5; } @@ -719,7 +967,7 @@ align-items: center; gap: 10px; padding: 8px 12px; - border-radius: 8px; + border-radius: var(--radius-square); font-size: 0.8125rem; color: var(--color-foreground-neutral); background: color-mix(in srgb, var(--color-foreground-ppg) 6%, transparent); @@ -747,7 +995,7 @@ } .bloom-demo-verdict[data-verdict="idle"] { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); } .bloom-demo-verdict-icon { @@ -790,7 +1038,7 @@ border-radius: 999px; background: transparent; border: 1px solid var(--color-stroke-neutral); - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 0.75rem; cursor: pointer; @@ -806,8 +1054,8 @@ } .bloom-demo-step-pill[data-active="true"] { - background: color-mix(in srgb, #5fb878 18%, transparent); - border-color: #5fb878; + background: color-mix(in srgb, var(--color-foreground-ppg) 18%, transparent); + border-color: var(--color-foreground-ppg); color: var(--color-foreground-neutral); } @@ -824,18 +1072,23 @@ } .runner { - --runner-terminal-bg: #0c0e10; - --runner-terminal-fg: #e6e6e6; - --runner-terminal-muted: #8b949e; - --runner-terminal-stroke: #1f242a; - --runner-mark-bg: color-mix(in srgb, #5fb878 20%, transparent); - --runner-mark-border: #5fb878; + /* Always-dark terminal pane; literals are the eclipse dark ramp, as in + `.agent-prompt` above. */ + --runner-terminal-bg: #0f0f0f; + --runner-terminal-fg: #f5f5f4; + --runner-terminal-muted: #a5a5a6; + --runner-terminal-stroke: #2a2a2a; + /* Two accents: the code pane follows the theme, the terminal pane does not, + so it takes the mode-independent cyan-400 step. */ + --runner-mark-bg: color-mix(in srgb, var(--color-foreground-ppg) 20%, transparent); + --runner-mark-border: var(--color-foreground-ppg); + --runner-terminal-accent: var(--color-prism-cyan-400); container-type: inline-size; margin: 1.75rem 0; display: flex; flex-direction: column; border: 1px solid var(--color-stroke-neutral); - border-radius: 10px; + border-radius: var(--radius-square-high); background: var(--color-background-default); overflow: hidden; } @@ -877,7 +1130,7 @@ } .runner-step-counter-label { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-weight: 400; } @@ -893,7 +1146,7 @@ justify-content: center; width: 28px; height: 28px; - border-radius: 6px; + border-radius: var(--radius-square-low); background: transparent; border: 1px solid var(--color-stroke-neutral); color: var(--color-foreground-neutral); @@ -922,7 +1175,7 @@ border-radius: 999px; background: transparent; border: 1px solid var(--color-stroke-neutral); - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 0.75rem; cursor: pointer; @@ -938,7 +1191,7 @@ } .runner-step-pill[data-active="true"] { - background: color-mix(in srgb, #5fb878 18%, transparent); + background: color-mix(in srgb, var(--color-foreground-ppg) 18%, transparent); border-color: var(--runner-mark-border); color: var(--color-foreground-neutral); } @@ -958,7 +1211,7 @@ .runner-caption { padding: 10px 14px 12px; font-size: 0.875rem; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); border-bottom: 1px solid var(--color-stroke-neutral); background: var(--color-background-default); } @@ -1009,7 +1262,7 @@ font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.08em; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); border-bottom: 1px solid var(--color-stroke-neutral); background: color-mix(in srgb, var(--color-foreground-ppg) 4%, transparent); } @@ -1032,7 +1285,7 @@ color: var(--runner-terminal-muted); background: transparent; border: 1px solid var(--runner-terminal-stroke); - border-radius: 4px; + border-radius: var(--radius-square-low); cursor: pointer; transition: color 160ms ease, @@ -1047,7 +1300,7 @@ } .runner-copy:focus-visible { - outline: 2px solid var(--runner-mark-border); + outline: 2px solid var(--runner-terminal-accent); outline-offset: 2px; } @@ -1109,22 +1362,22 @@ .runner-terminal-line[data-step-state="active"] { opacity: 1; color: var(--runner-terminal-fg); - background: color-mix(in srgb, var(--runner-mark-border) 14%, transparent); - box-shadow: inset 3px 0 0 var(--runner-mark-border); + background: color-mix(in srgb, var(--runner-terminal-accent) 14%, transparent); + box-shadow: inset 3px 0 0 var(--runner-terminal-accent); padding-left: 8px; margin-left: -14px; } .btree-demo, .hash-demo { - --demo-accent: #5fb878; - --demo-accent-bg: color-mix(in srgb, #5fb878 18%, transparent); - --demo-accent-soft: color-mix(in srgb, #5fb878 8%, transparent); + --demo-accent: var(--color-foreground-ppg); + --demo-accent-bg: color-mix(in srgb, var(--color-foreground-ppg) 18%, transparent); + --demo-accent-soft: color-mix(in srgb, var(--color-foreground-ppg) 8%, transparent); margin: 1.75rem 0; display: flex; flex-direction: column; border: 1px solid var(--color-stroke-neutral); - border-radius: 10px; + border-radius: var(--radius-square-high); background: var(--color-background-default); overflow: hidden; container-type: inline-size; @@ -1148,7 +1401,7 @@ padding: 2px 8px; border-radius: 999px; background: color-mix(in srgb, var(--color-foreground-ppg) 12%, transparent); - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-size: 0.6875rem; letter-spacing: 0.06em; } @@ -1174,7 +1427,7 @@ justify-content: center; width: 28px; height: 28px; - border-radius: 6px; + border-radius: var(--radius-square-low); background: transparent; border: 1px solid var(--color-stroke-neutral); color: var(--color-foreground-neutral); @@ -1204,7 +1457,7 @@ border-radius: 999px; background: transparent; border: 1px solid var(--color-stroke-neutral); - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 0.75rem; cursor: pointer; @@ -1311,7 +1564,7 @@ } .btree-demo-query-label { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); } .btree-demo-query-value { @@ -1322,7 +1575,7 @@ .btree-demo-query-placeholder { background: transparent; border-style: dashed; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-style: italic; } @@ -1356,7 +1609,7 @@ flex-direction: column; gap: 6px; padding: 8px 10px; - border-radius: 8px; + border-radius: var(--radius-square); border: 1px solid var(--color-stroke-neutral); background: var(--color-background-default); font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); @@ -1377,7 +1630,7 @@ font-size: 0.625rem; text-transform: uppercase; letter-spacing: 0.08em; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); } .btree-demo-keys { @@ -1388,7 +1641,7 @@ .btree-demo-key { padding: 2px 8px; - border-radius: 4px; + border-radius: var(--radius-square-low); background: color-mix(in srgb, var(--color-foreground-ppg) 10%, transparent); color: var(--color-foreground-neutral); font-weight: 600; @@ -1403,7 +1656,7 @@ .btree-demo-edge { position: relative; - border-left: 1px dashed color-mix(in srgb, var(--color-foreground-muted) 40%, transparent); + border-left: 1px dashed color-mix(in srgb, var(--color-foreground-neutral-weak) 40%, transparent); margin-left: 50%; transition: border-color 200ms ease; } @@ -1428,8 +1681,8 @@ align-items: center; gap: 6px; padding: 2px 4px; - border-radius: 4px; - color: var(--color-foreground-muted); + border-radius: var(--radius-square-low); + color: var(--color-foreground-neutral-weak); transition: background 200ms ease, color 200ms ease; @@ -1452,7 +1705,7 @@ .btree-demo-caption, .hash-demo-caption { font-size: 0.875rem; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); line-height: 1.5; } @@ -1462,7 +1715,7 @@ gap: 8px; align-self: flex-start; padding: 6px 10px; - border-radius: 8px; + border-radius: var(--radius-square); background: var(--demo-accent-bg); border: 1px solid var(--demo-accent); font-size: 0.8125rem; @@ -1496,7 +1749,7 @@ } .hash-demo-input-label { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.625rem; @@ -1519,7 +1772,7 @@ align-items: center; gap: 4px; padding: 10px 8px; - border-radius: 8px; + border-radius: var(--radius-square); border: 1px solid var(--color-stroke-neutral); background: var(--color-background-default); font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); @@ -1549,19 +1802,19 @@ } .hash-demo-pipe-arrow { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-size: 0.875rem; line-height: 1; } .hash-demo-pipe-raw { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-size: 0.625rem; letter-spacing: 0.04em; } .hash-demo-pipe-mod { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-size: 0.625rem; } @@ -1572,7 +1825,7 @@ min-width: 32px; height: 28px; padding: 0 8px; - border-radius: 6px; + border-radius: var(--radius-square-low); background: color-mix(in srgb, var(--color-foreground-ppg) 10%, transparent); color: var(--color-foreground-neutral); font-weight: 700; @@ -1604,10 +1857,10 @@ flex-direction: column; align-items: center; justify-content: center; - border-radius: 6px; + border-radius: var(--radius-square-low); border: 1px solid var(--color-stroke-neutral); background: var(--color-background-default); - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 0.75rem; transition: @@ -1643,11 +1896,11 @@ /* ── Sequence diagram ───────────────────────────────────────────────── */ .seq-diagram { - --seq-accent: #5fb878; - --seq-accent-bg: color-mix(in srgb, #5fb878 15%, transparent); + --seq-accent: var(--color-foreground-ppg); + --seq-accent-bg: color-mix(in srgb, var(--color-foreground-ppg) 15%, transparent); margin: 1.75rem 0; border: 1px solid var(--color-stroke-neutral); - border-radius: 10px; + border-radius: var(--radius-square-high); background: var(--color-background-default); padding: 12px 16px 16px; overflow-x: auto; @@ -1711,12 +1964,15 @@ /* Vector space demo (pgvector post) */ .vector-demo { - --vector-accent: #5fb878; - --vector-query: #7c86ff; + /* Ranked points take the cyan accent; the draggable query marker takes + prism red so it stays the most salient thing on the plane and cannot be + confused with a result. (It was an off-brand indigo.) */ + --vector-accent: var(--color-foreground-ppg); + --vector-query: var(--color-prism-red-500); container-type: inline-size; margin: 1.75rem 0; border: 1px solid var(--color-stroke-neutral); - border-radius: 10px; + border-radius: var(--radius-square-high); background: var(--color-background-default); overflow: hidden; } @@ -1739,7 +1995,7 @@ } .vector-demo-query { - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); font-size: 0.75rem; } @@ -1776,7 +2032,7 @@ } .vector-demo-axis-label { - fill: var(--color-foreground-muted); + fill: var(--color-foreground-neutral-weak); font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 11px; } @@ -1842,7 +2098,7 @@ g[data-top="true"] .vector-demo-point { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.08em; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); } .vector-demo-ranking-list { @@ -1861,7 +2117,7 @@ g[data-top="true"] .vector-demo-point { gap: 8px; font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 0.75rem; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); } .vector-demo-rank[data-top="true"] { @@ -1902,7 +2158,7 @@ g[data-top="true"] .vector-demo-point { .vector-demo-caption { font-size: 0.8125rem; - color: var(--color-foreground-muted); + color: var(--color-foreground-neutral-weak); border-top: 1px solid var(--color-stroke-neutral); padding-top: 10px; margin-top: auto; diff --git a/apps/blog/src/app/icon.svg b/apps/blog/src/app/icon.svg new file mode 100644 index 00000000000..8bfb36cafed --- /dev/null +++ b/apps/blog/src/app/icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/blog/src/app/layout.tsx b/apps/blog/src/app/layout.tsx index f59a6fa194b..917e7718a39 100644 --- a/apps/blog/src/app/layout.tsx +++ b/apps/blog/src/app/layout.tsx @@ -2,7 +2,8 @@ import { Provider } from "@/components/provider"; import { createBlogStructuredData } from "@/lib/structured-data"; import { getBaseUrl } from "@/lib/url"; import "./global.css"; -import { Inter, Barlow } from "next/font/google"; +import { Barlow } from "next/font/google"; +import localFont from "next/font/local"; import type { Metadata } from "next"; import Script from "next/script"; import { BLOG_HOME_DESCRIPTION, BLOG_HOME_TITLE } from "@/lib/blog-metadata"; @@ -10,9 +11,43 @@ import { FontAwesomeScript as EclipseFA } from "@prisma/eclipse"; import { JsonLd } from "@prisma-docs/ui/components/json-ld"; import { GoogleTagManager } from "@prisma-docs/ui/components/google-tag-manager"; -const inter = Inter({ - subsets: ["latin"], +// Inter is vendored inside @prisma/eclipse now, so load the same files here +// rather than pulling a second copy from Google. +const inter = localFont({ + src: [ + { + path: "../../../../packages/eclipse/src/static/fonts/InterVariable.woff2", + weight: "100 900", + style: "normal", + }, + { + path: "../../../../packages/eclipse/src/static/fonts/InterVariable-Italic.woff2", + weight: "100 900", + style: "italic", + }, + ], variable: "--font-inter", + display: "swap", +}); + +// Sora replaces Mona Sans VF as the display face. next/font/local has no +// per-source `unicode-range`, so only the latin subset is preloaded here; the +// latin-ext subset is served by the plain "Sora" @font-face in the package's +// fonts.css, which sits directly behind this variable in the family stack. +const sora = localFont({ + src: "../../../../packages/eclipse/src/static/fonts/SoraVF-latin.woff2", + weight: "100 800", + style: "normal", + variable: "--font-sora", + display: "swap", +}); + +// Code face — unchanged by the rebrand. +const monaSansMono = localFont({ + src: "../../../../packages/eclipse/src/static/fonts/MonaSansMonoVF[wght].woff2", + variable: "--font-mona-mono", + display: "swap", + weight: "200 900", }); const barlow = Barlow({ @@ -31,7 +66,11 @@ const blogStructuredData = createBlogStructuredData(); export default function Layout({ children }: LayoutProps<"/">) { return ( - + {/* FontAwesome — not render-critical; explicit strategy prevents accidental beforeInteractive promotion */} diff --git a/apps/blog/src/app/not-found.tsx b/apps/blog/src/app/not-found.tsx index a1cbdb38b4c..155f67e4e4c 100644 --- a/apps/blog/src/app/not-found.tsx +++ b/apps/blog/src/app/not-found.tsx @@ -8,48 +8,55 @@ export const metadata: Metadata = { export default function NotFound() { return ( -
-

- Blog -

-
+
+
+

Blog

+
+
+ {/* Chromatic-aberration glitch, retinted onto the prism triad: the + offset copies are prism red and prism cyan instead of the CSS + keyword colours they used to use. */}

404

-

+

We could not find the page you were looking for

- - Back to Blog + + Back to blog
diff --git a/apps/blog/src/app/og/image.png/route.tsx b/apps/blog/src/app/og/image.png/route.tsx index d06b24892e4..c58685a1a73 100644 --- a/apps/blog/src/app/og/image.png/route.tsx +++ b/apps/blog/src/app/og/image.png/route.tsx @@ -3,13 +3,25 @@ import { ImageResponse } from "next/og"; export const revalidate = false; -const SECTION_BADGE_COLOR = "#71e8df"; +/* Prism palette, inlined because satori resolves no CSS custom properties. + Each value is the light-mode eclipse token named beside it. */ +const INK = "#151515"; // --color-foreground-neutral-strong +const INK_MUTED = "#646567"; // --color-foreground-neutral-weak +const PAPER = "#f9faf5"; // --color-paper +const WHITE = "#ffffff"; // --color-background-default +const CYAN = "#009aaa"; // --color-prism-cyan-600 +const CYAN_WASH = "#eeffff"; // --color-background-ppg + +/* The six spectrum stops, cyan wrapping back to cyan — the same sequence as + `--gradient-spectrum` in @prisma/eclipse. */ +const SPECTRUM = "linear-gradient(90deg, #01d7e4, #f3c306, #f37a03, #f43531, #f00e5c, #01d7e4)"; + const GOOGLE_FONT_RESOURCE_REGEX = /src: url\((.+)\) format\('(opentype|truetype)'\)/; const BADGE_HORIZONTAL_PADDING = 24; const BADGE_VERTICAL_PADDING = 12; const BADGE_FONT_SIZE = 24; const BADGE_BORDER_RADIUS = 9999; -const BADGE_BORDER_WIDTH = 3; +const BADGE_BORDER_WIDTH = 2; const PrismaLogo = () => ( @@ -17,13 +29,16 @@ const PrismaLogo = () => ( fillRule="evenodd" clipRule="evenodd" d="M0.209637 19.0073C-0.0659575 18.5726 -0.070121 18.0189 0.198904 17.58L10.3282 1.05707C10.8916 0.138071 12.252 0.218426 12.7033 1.19735L21.9569 21.2706C22.3002 22.0154 21.905 22.8917 21.1194 23.1274L6.72474 27.4458C6.14558 27.6195 5.52155 27.3867 5.19781 26.876L0.209637 19.0073ZM11.4969 5.88824C11.5945 5.40217 12.2605 5.33208 12.4572 5.78717L18.8402 20.5571C18.9603 20.8352 18.8108 21.1559 18.5205 21.2425L8.57492 24.2114C8.20935 24.3205 7.85916 24.0011 7.93428 23.627L11.4969 5.88824ZM48.4948 21.1371H51.3226V10.772H48.4948V21.1371ZM48.3744 8.09277C48.3744 7.17221 48.8878 6.7116 49.9137 6.7116C50.9394 6.7116 51.4527 7.17221 51.4527 8.09277C51.4527 8.53176 51.3244 8.87321 51.068 9.11743C50.8114 9.36165 50.4267 9.48343 49.9137 9.48343C48.8878 9.48343 48.3744 9.01987 48.3744 8.09277ZM87.1709 16.335L86.0768 16.372C85.2548 16.3969 84.6429 16.5455 84.2412 16.8172C83.8392 17.0893 83.6386 17.5031 83.6386 18.0596C83.6386 18.8567 84.0959 19.2555 85.0106 19.2555C85.6656 19.2555 86.1897 19.0672 86.5819 18.6898C86.9744 18.313 87.1709 17.8124 87.1709 17.1878V16.335ZM88.0053 21.1375L87.4583 19.7282H87.384C86.908 20.3279 86.4182 20.7437 85.9144 20.9755C85.4109 21.2072 84.7542 21.3228 83.9446 21.3228C82.9491 21.3228 82.1661 21.0386 81.5941 20.47C81.0226 19.9017 80.7368 19.0918 80.7368 18.0409C80.7368 16.941 81.1214 16.1298 81.8907 15.6073C82.6607 15.0851 83.8209 14.7961 85.3723 14.7404L87.1709 14.6848V14.2304C87.1709 13.1799 86.633 12.6544 85.5576 12.6544C84.7293 12.6544 83.7558 12.9045 82.6371 13.4054L81.7009 11.4955C82.8938 10.8716 84.2167 10.559 85.6689 10.559C87.0596 10.559 88.1258 10.8621 88.8676 11.4677C89.6091 12.0734 89.98 12.9946 89.98 14.2304V21.1375H88.0053ZM72.4802 21.1375H69.6524V15.0834C69.6524 14.3357 69.527 13.775 69.2772 13.4008C69.0265 13.0269 68.6326 12.8397 68.0948 12.8397C67.3719 12.8397 66.8465 13.1058 66.5188 13.6371C66.1911 14.1688 66.0275 15.0435 66.0275 16.261V21.1375H63.1996V10.7723H65.3599L65.74 12.0982H65.8978C66.1757 11.6225 66.5778 11.25 67.1029 10.9812C67.6283 10.7121 68.231 10.5776 68.9109 10.5776C70.4623 10.5776 71.5128 11.0846 72.0631 12.0982H72.3132C72.5915 11.616 73.001 11.2421 73.5419 10.9763C74.0827 10.7105 74.6929 10.5776 75.3728 10.5776C76.5471 10.5776 77.4359 10.8791 78.0382 11.4817C78.6409 12.0844 78.9421 13.0502 78.9421 14.3786V21.1375H76.1051V15.0834C76.1051 14.3357 75.9798 13.775 75.73 13.4008C75.4792 13.0269 75.0854 12.8397 74.5475 12.8397C73.8555 12.8397 73.3379 13.0872 72.9945 13.5815C72.6517 14.0761 72.4802 14.8608 72.4802 15.9362V21.1375ZM60.17 20.4885C60.9088 19.9323 61.2781 19.1227 61.2781 18.0594C61.2781 17.5468 61.1887 17.1045 61.0093 16.7336C60.8299 16.3627 60.5517 16.0353 60.1749 15.7508C59.7981 15.4667 59.2046 15.1609 58.3946 14.8332C57.4862 14.4685 56.8976 14.1932 56.6285 14.0079C56.3601 13.8226 56.2252 13.6033 56.2252 13.3496C56.2252 12.8985 56.6426 12.6729 57.477 12.6729C57.9465 12.6729 58.4071 12.7443 58.8582 12.886C59.3093 13.0284 59.7948 13.2104 60.314 13.4331L61.1668 11.3936C59.9863 10.8498 58.7718 10.5778 57.5232 10.5778C56.2127 10.5778 55.2009 10.8295 54.4872 11.3333C53.7729 11.8371 53.416 12.5495 53.416 13.4701C53.416 14.0079 53.5012 14.461 53.6714 14.8286C53.841 15.1963 54.113 15.5223 54.4872 15.8065C54.8607 16.091 55.4467 16.4 56.2438 16.7336C56.8 16.9686 57.2453 17.1742 57.5788 17.3503C57.9128 17.5265 58.1475 17.6843 58.2837 17.8231C58.4195 17.9622 58.4876 18.1429 58.4876 18.3655C58.4876 18.9587 57.9743 19.2553 56.9483 19.2553C56.4478 19.2553 55.8684 19.1718 55.2103 19.0052C54.5517 18.8382 53.9601 18.6313 53.4347 18.3838V20.7203C53.8983 20.918 54.3959 21.0679 54.9275 21.1701C55.4591 21.2719 56.1014 21.3229 56.8557 21.3229C58.3266 21.3229 59.4314 21.0447 60.17 20.4885ZM46.9948 10.661C46.7414 10.6054 46.4232 10.5776 46.0398 10.5776C45.3969 10.5776 44.8021 10.7553 44.2554 11.1108C43.708 11.4664 43.2739 11.9345 42.9524 12.5152H42.8136L42.3962 10.7723H40.2546V21.1375H43.0824V15.8622C43.0824 15.0278 43.3341 14.3786 43.8376 13.9151C44.3418 13.4515 45.0446 13.2197 45.9472 13.2197C46.2749 13.2197 46.5528 13.2508 46.7817 13.3124L46.9948 10.661ZM31.9317 13.9614H32.8774C33.7613 13.9614 34.4223 13.7869 34.8613 13.4376C35.3003 13.0886 35.5196 12.5799 35.5196 11.9124C35.5196 11.239 35.3356 10.7414 34.968 10.4199C34.6 10.0984 34.0239 9.93766 33.2388 9.93766H31.9317V13.9614ZM38.4214 11.8106C38.4214 13.2694 37.9657 14.385 37.0537 15.1573C36.1423 15.9302 34.8459 16.3162 33.1649 16.3162H31.9317V21.1373H29.0577V7.58296H33.3872C35.0315 7.58296 36.2814 7.93684 37.1375 8.64461C37.9936 9.35238 38.4214 10.4079 38.4214 11.8106Z" - fill="#FFFFFF" + fill={INK} /> ); +// Sora Medium is the brand display face; Inter carries body copy. Both are +// fetched from Google here rather than from the woff2 files vendored in +// @prisma/eclipse, because satori (behind `next/og`) cannot parse woff2. const FONT_DEFINITIONS = [ - { name: "Barlow", family: "Barlow", weight: 700 }, + { name: "Sora", family: "Sora", weight: 500 }, { name: "Inter", family: "Inter", weight: 400 }, { name: "JetBrains Mono", family: "JetBrains+Mono", weight: 400 }, ] as const; @@ -48,11 +63,24 @@ function PrismaOGImage({ title, description }: { title: string; description: str display: "flex", flexDirection: "column", justifyContent: "center", - background: "linear-gradient(to bottom, #0B1A1E, #0A0B16)", + background: `linear-gradient(to bottom, ${WHITE}, ${PAPER})`, padding: 60, position: "relative", }} > + {/* The spectrum hairline — the brand's interaction signature, held + still. It is the only saturated element at full width. */} +
+
Blog @@ -84,10 +112,11 @@ function PrismaOGImage({ title, description }: { title: string; description: str

@@ -98,7 +127,7 @@ function PrismaOGImage({ title, description }: { title: string; description: str fontSize: "2rem", fontFamily: "Inter, sans-serif", fontWeight: 400, - color: "#a0aec0", + color: INK_MUTED, lineHeight: 1.5, margin: 0, }} @@ -112,12 +141,16 @@ function PrismaOGImage({ title, description }: { title: string; description: str position: "absolute", bottom: 60, left: 60, + display: "flex", + alignItems: "center", + gap: 12, fontSize: 22, - fontFamily: "Barlow, sans-serif", - fontWeight: 700, - color: "#71e8df", + fontFamily: "Inter, sans-serif", + fontWeight: 400, + color: INK_MUTED, }} > +
prisma.io/blog
diff --git a/apps/blog/src/components/AgentPrompt/Client.tsx b/apps/blog/src/components/AgentPrompt/Client.tsx index a3f0db8c3a0..ca31f6eb322 100644 --- a/apps/blog/src/components/AgentPrompt/Client.tsx +++ b/apps/blog/src/components/AgentPrompt/Client.tsx @@ -1,19 +1,7 @@ "use client"; -import { - Component, - createRef, - useEffect, - useRef, - useState, - type RefObject, -} from "react"; -import { - InnerLine, - Pre, - type AnnotationHandler, - type HighlightedCode, -} from "codehike/code"; +import { Component, createRef, useEffect, useRef, useState, type RefObject } from "react"; +import { InnerLine, Pre, type AnnotationHandler, type HighlightedCode } from "codehike/code"; import { calculateTransitions, getStartingSnapshot, @@ -21,13 +9,7 @@ import { } from "codehike/utils/token-transitions"; import { Pause, Play } from "lucide-react"; -type Phase = - | "idle" - | "typing" - | "thinking" - | "morphing" - | "running" - | "settled"; +type Phase = "idle" | "typing" | "thinking" | "morphing" | "running" | "settled"; const TYPE_CHAR_MS = 45; const PAUSE_AFTER_TYPING_MS = 900; @@ -125,10 +107,9 @@ export function AgentPromptClient({ setInView(true); return; } - const obs = new IntersectionObserver( - ([entry]) => setInView(entry.isIntersecting), - { threshold: 0.25 }, - ); + const obs = new IntersectionObserver(([entry]) => setInView(entry.isIntersecting), { + threshold: 0.25, + }); obs.observe(el); return () => obs.disconnect(); }, []); @@ -210,19 +191,13 @@ export function AgentPromptClient({ : undefined; return ( -
+
You

{typed} - {phase === "typing" ? ( -

-
+
{hasTerminalCommand ? (
$ - {terminalCmdTyped || - phase === "settled" || - terminalVisibleLines > 0 + {terminalCmdTyped || phase === "settled" || terminalVisibleLines > 0 ? terminalCommand : ""} {phase === "running" && !terminalCmdTyped ? ( diff --git a/apps/blog/src/components/AuthorAvatarGroup.tsx b/apps/blog/src/components/AuthorAvatarGroup.tsx index e09d0510fc0..0f0e1e273c0 100644 --- a/apps/blog/src/components/AuthorAvatarGroup.tsx +++ b/apps/blog/src/components/AuthorAvatarGroup.tsx @@ -44,7 +44,7 @@ export function AuthorAvatarGroup({ {profile.name} diff --git a/apps/blog/src/components/AuthorBio.tsx b/apps/blog/src/components/AuthorBio.tsx index 349d67c4f67..d6d7d842193 100644 --- a/apps/blog/src/components/AuthorBio.tsx +++ b/apps/blog/src/components/AuthorBio.tsx @@ -43,7 +43,7 @@ export function AuthorSocialLinks({ rel="me noopener noreferrer" aria-label={`${name} on ${meta.label}`} title={meta.label} - className="text-lg transition-colors hover:[&>div]:bg-background-ppg-strong" + className="text-lg transition-colors hover:[&>div]:bg-background-neutral hover:[&_i]:text-foreground-neutral" > -

+

{profiles.length === 1 ? "About the author" : "About the authors"}

@@ -105,11 +105,13 @@ export function AuthorBio({ authors = [] }: { authors?: string[] }) {
{name} -

{bio?.bio}

+

+ {bio?.bio} +

diff --git a/apps/blog/src/components/AutoplayYoutubeEmbed.tsx b/apps/blog/src/components/AutoplayYoutubeEmbed.tsx index b8a6b5bccca..1233f1b103f 100644 --- a/apps/blog/src/components/AutoplayYoutubeEmbed.tsx +++ b/apps/blog/src/components/AutoplayYoutubeEmbed.tsx @@ -15,8 +15,7 @@ export const AutoplayYoutubeEmbed = ({ videoId, title }: Props) => { const onMessage = (event: MessageEvent) => { if (event.source !== iframeRef.current?.contentWindow) return; try { - const data = - typeof event.data === "string" ? JSON.parse(event.data) : event.data; + const data = typeof event.data === "string" ? JSON.parse(event.data) : event.data; if (data?.event === "onStateChange" && data?.info === 1) { setPlaying(true); } diff --git a/apps/blog/src/components/BackToBlogLink.tsx b/apps/blog/src/components/BackToBlogLink.tsx new file mode 100644 index 00000000000..3444a71127b --- /dev/null +++ b/apps/blog/src/components/BackToBlogLink.tsx @@ -0,0 +1,23 @@ +import Link from "next/link"; +import { ArrowLeft } from "lucide-react"; +import { cn } from "@prisma-docs/ui/lib/cn"; + +/** + * The single "← Back to blog" affordance shared by the post, series and author + * pages. Muted at rest, ink on hover, with the arrow nudging back a couple of + * pixels — the same 300ms ease every other hover on the blog uses. + */ +export function BackToBlogLink({ className }: { className?: string }) { + return ( + + + Back to blog + + ); +} diff --git a/apps/blog/src/components/BlogCTA.tsx b/apps/blog/src/components/BlogCTA.tsx index f84161e89b1..77aef288469 100644 --- a/apps/blog/src/components/BlogCTA.tsx +++ b/apps/blog/src/components/BlogCTA.tsx @@ -5,20 +5,44 @@ import { trackCTA } from "@prisma-docs/ui/lib/analytics"; const CTA_HREF = "https://console.prisma.io/sign-up"; +/** + * The end-of-post conversion panel, and the one place in the reading flow + * where the brand is allowed to be loud. + * + * Two moves, borrowed from the marketing site's CTA burst: + * - `spectrum-border-on` keeps the prism ring lit rather than waiting for a + * hover, so the panel reads as a destination instead of a card. + * - a blurred spectral wash along the bottom edge — cyan, yellow, red in the + * gradient's own order — sitting under a paper surface so the saturation + * never becomes the surface itself. + * + * The wash is a decorative layer with `aria-hidden`; the ring's slide + * animation carries the utility's own `prefers-reduced-motion` guard. + */ export const BlogCTA = () => { return ( -
-
-
-
-

+
+
+
+
+

Build your next app with Prisma

-

+

Start free. Scale when you’re ready.

-
- {uniqueTags.map((category, idx) => ( - handleSelect(category)} - onKeyDown={(event) => { - if (event.key === "Enter" || event.key === " ") { - event.preventDefault(); - handleSelect(category); - } - }} - tabIndex={0} - className="cursor-pointer transition-colors hover:bg-background-ppg/50" - label={formatTag(category)} - /> - ))} + {uniqueTags.map((category, idx) => { + const isSelected = currentCategory === category; + return ( + + ); + })}
); diff --git a/apps/blog/src/components/DecisionTree.tsx b/apps/blog/src/components/DecisionTree.tsx index 712af5a8ac7..633860e9112 100644 --- a/apps/blog/src/components/DecisionTree.tsx +++ b/apps/blog/src/components/DecisionTree.tsx @@ -344,13 +344,7 @@ function TreeBranch({ ); } -function TextTree({ - byId, - nodeId, -}: { - byId: Map; - nodeId: string; -}) { +function TextTree({ byId, nodeId }: { byId: Map; nodeId: string }) { const node = byId.get(nodeId); if (!node) return null; if (isResult(node)) { diff --git a/apps/blog/src/components/Employee.tsx b/apps/blog/src/components/Employee.tsx index 580081110b4..8dad44a1332 100644 --- a/apps/blog/src/components/Employee.tsx +++ b/apps/blog/src/components/Employee.tsx @@ -2,7 +2,7 @@ import Image from "next/image"; const employeeWrapperClasses = [ - "w-full rounded-lg p-8 mb-8", + "w-full rounded-square-high border border-stroke-neutral p-8 mb-8", "shadow-[0px_0px_2.4px_rgba(0,0,0,0.01),0px_1.51px_6.64px_rgba(0,0,0,0.02),0px_5.44px_15.98px_rgba(0,0,0,0.04),0px_22px_53px_rgba(0,0,0,0.07)]", "[&>strong]:block [&>strong]:mt-4 [&>strong]:ml-[72px] max-md:[&>strong]:ml-0", "[&>p]:my-2 [&>p]:ml-[72px] max-md:[&>p]:ml-0", @@ -11,14 +11,14 @@ const employeeWrapperClasses = [ const employeeHeaderClasses = "flex max-md:flex-col"; const employeeNamePlateClasses = [ - "flex flex-[2] items-center text-gray-500", + "flex flex-[2] items-center text-foreground-neutral-weak", "[&>img]:w-14 [&>img]:h-14 [&>img]:rounded-full [&>img]:mr-4", - "[&>div>strong]:font-bold [&>div>strong]:text-xl [&>div>strong]:block [&>div>strong]:mb-1 [&>div>strong]:text-gray-800", + "[&>div>strong]:font-bold [&>div>strong]:text-xl [&>div>strong]:block [&>div>strong]:mb-1 [&>div>strong]:text-foreground-neutral-strong", ].join(" "); const employeeSocialsClasses = [ "flex max-md:mt-4 max-md:-ml-2", - "[&>a]:bg-gray-300 [&>a]:text-gray-700 [&>a]:block [&>a]:w-8 [&>a]:h-8 [&>a]:rounded-full [&>a]:p-2 [&>a]:ml-2", + "[&>a]:bg-background-neutral [&>a]:text-foreground-neutral [&>a]:block [&>a]:w-8 [&>a]:h-8 [&>a]:rounded-full [&>a]:p-2 [&>a]:ml-2", "[&>a>svg]:w-4 [&>a>svg]:h-4", ].join(" "); diff --git a/apps/blog/src/components/KeepReading.tsx b/apps/blog/src/components/KeepReading.tsx index 4b9eefbd441..11b4928e228 100644 --- a/apps/blog/src/components/KeepReading.tsx +++ b/apps/blog/src/components/KeepReading.tsx @@ -5,8 +5,10 @@ export function KeepReading({ posts }: { posts: BlogCardItem[] }) { if (posts.length === 0) return null; return ( -
-

Keep reading

+
+

+ Keep reading +

{posts.map((post) => ( diff --git a/apps/blog/src/components/Meetup.tsx b/apps/blog/src/components/Meetup.tsx index dd1f9822d5c..2ff51cce453 100644 --- a/apps/blog/src/components/Meetup.tsx +++ b/apps/blog/src/components/Meetup.tsx @@ -3,16 +3,16 @@ import Image from "next/image"; import { ArrowRight } from "lucide-react"; const meetupWrapperClasses = [ - "w-full rounded-lg p-8 mb-8 flex", + "w-full rounded-square-high border border-stroke-neutral p-8 mb-8 flex", "shadow-[0px_0px_2.4px_rgba(0,0,0,0.01),0px_1.51px_6.64px_rgba(0,0,0,0.02),0px_5.44px_15.98px_rgba(0,0,0,0.04),0px_22px_53px_rgba(0,0,0,0.07)]", - "[&>div>strong]:font-bold [&>div>strong]:text-xl [&>div>strong]:block [&>div>strong]:mb-1 [&>div>strong]:text-gray-800", - "[&>div>p]:text-gray-600 [&>div>p]:my-4 [&>div>p]:ml-4 [&>div>p]:list-item", + "[&>div>strong]:font-bold [&>div>strong]:text-xl [&>div>strong]:block [&>div>strong]:mb-1 [&>div>strong]:text-foreground-neutral-strong", + "[&>div>p]:text-foreground-neutral-weak [&>div>p]:my-4 [&>div>p]:ml-4 [&>div>p]:list-item", ].join(" "); const meetupListClasses = [ - "w-full rounded-lg p-8 mb-8", + "w-full rounded-square-high border border-stroke-neutral p-8 mb-8", "shadow-[0px_0px_2.4px_rgba(0,0,0,0.01),0px_1.51px_6.64px_rgba(0,0,0,0.02),0px_5.44px_15.98px_rgba(0,0,0,0.04),0px_22px_53px_rgba(0,0,0,0.07)]", - "[&>div]:shadow-none [&>div]:border-b [&>div]:border-gray-200 [&>div]:p-0 [&>div]:mb-6 [&>div]:pb-6", + "[&>div]:shadow-none [&>div]:border-b [&>div]:border-stroke-neutral [&>div]:p-0 [&>div]:mb-6 [&>div]:pb-6", "[&>div:last-child]:mb-0 [&>div:last-child]:pb-0 [&>div:last-child]:border-b-0", ].join(" "); diff --git a/apps/blog/src/components/Mermaid.tsx b/apps/blog/src/components/Mermaid.tsx index 39410534f29..88853ce73e7 100644 --- a/apps/blog/src/components/Mermaid.tsx +++ b/apps/blog/src/components/Mermaid.tsx @@ -1,17 +1,22 @@ -import { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock'; -import { renderMermaidSVG } from 'beautiful-mermaid'; +import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock"; +import { renderMermaidSVG } from "beautiful-mermaid"; export function Mermaid({ chart }: { chart: string }) { try { const svg = renderMermaidSVG(chart, { - bg: 'var(--color-fd-background)', - fg: 'var(--color-fd-foreground)', + bg: "var(--color-fd-background)", + fg: "var(--color-fd-foreground)", // Edge/message labels default to a too-dim bg/fg mix; use the theme's muted-foreground for a softer, legible gray. - muted: 'var(--color-fd-muted-foreground)', + muted: "var(--color-fd-muted-foreground)", transparent: true, interactive: false, }); - return
; + return ( +
+ ); } catch { return ( @@ -19,4 +24,4 @@ export function Mermaid({ chart }: { chart: string }) { ); } -} \ No newline at end of file +} diff --git a/apps/blog/src/components/PostCard.tsx b/apps/blog/src/components/PostCard.tsx index 4936aeea19e..a8fbde96b9d 100644 --- a/apps/blog/src/components/PostCard.tsx +++ b/apps/blog/src/components/PostCard.tsx @@ -1,13 +1,9 @@ "use client"; -import { - PostCard as SharedPostCard, - type PostCardItem as SharedPostCardItem, -} from "@prisma-docs/ui/components/post-card"; -import { type AuthorProfile } from "@prisma-docs/ui/components/author-avatar-group"; -import { getAuthorProfiles } from "@/lib/authors"; +import { AuthorAvatarGroup } from "@/components/AuthorAvatarGroup"; import { formatDate, formatTag } from "@/lib/format"; import { withBlogBasePathForImageSrc } from "@/lib/url"; +import { cn } from "@prisma-docs/ui/lib/cn"; type PostCardItem = { url: string; @@ -23,6 +19,29 @@ type PostCardItem = { tags?: string[]; }; +/** + * The blog's card idiom, and the one place the brand's interaction signature + * carries a whole page. + * + * Resting state is deliberately quiet — a hairline `stroke-neutral` ring on the + * page surface, 14px radius, a single-pixel shadow. On hover the hairline fades + * to transparent while `.spectrum-border` lights that same ring with the + * sliding prism gradient and the shadow lifts: one gesture, 500ms. The utility + * ships its own `prefers-reduced-motion` guard for the gradient slide; the + * transitions declared here carry an explicit `motion-reduce:` of their own. + * + * Three shapes, one surface language: + * - default — feed card in the 3-up grid. + * - vertical — the same upright card, kept as a separate prop so the series + * prev/next and "Keep reading" call sites don't have to change. + * - featured — the lead slot: full grid width, image beside the body from md + * up, seated on `card-wash` so it reads as a panel above the + * white cards below it. + * + * Previously this file wrapped `@prisma-docs/ui`'s shared PostCard. That + * package is shared with the other apps and out of scope for this rebrand, so + * the card is implemented locally instead — same props, same data mapping. + */ export function PostCard({ post, currentCategory, @@ -34,31 +53,115 @@ export function PostCard({ featured?: boolean; vertical?: boolean; }) { - const sourceAuthorNames = + const authorNames = post.authors && post.authors.length > 0 ? post.authors : post.author ? [post.author] : []; - const authorProfiles: AuthorProfile[] = getAuthorProfiles(sourceAuthorNames).map((profile) => ({ - name: profile.name, - imageSrc: profile.imageSrc ? withBlogBasePathForImageSrc(profile.imageSrc) : null, - })); - const author: AuthorProfile | null = authorProfiles[0] ?? null; const badge = post.tags && post.tags.length > 0 ? formatTag(currentCategory !== "show-all" ? currentCategory : post.tags[0]) : null; - const sharedPost: SharedPostCardItem = { - url: post.url, - title: post.title, - date: formatDate(new Date(post.date).toISOString()), - updatedAt: post.updatedAt ? formatDate(new Date(post.updatedAt).toISOString()) : null, - excerpt: post.excerpt, - author, - authors: authorProfiles, - imageSrc: post.imageSrc ? withBlogBasePathForImageSrc(post.imageSrc) : null, - imageAlt: post.imageAlt, - badge, - }; + // `formatDate` already returns "" for an empty or unparseable value. + const date = formatDate(post.date); + const updatedAt = post.updatedAt ? formatDate(post.updatedAt) : ""; - return ; + const imageSrc = post.imageSrc ? withBlogBasePathForImageSrc(post.imageSrc) : null; + + // The featured slot only splits into two columns when there is an image to + // put in the second one; without one it falls back to the upright card so no + // empty grid track is left behind. + const isSplit = featured && !vertical && Boolean(imageSrc); + + const body = ( +
+
+ {badge ? ( + + {badge} + + ) : null} + {date ? {date} : null} + {date && updatedAt ? ( + + · + + ) : null} + {updatedAt ? ( + Updated {updatedAt} + ) : null} +
+ +

+ {post.title} +

+ + {post.excerpt ? ( +

+ {post.excerpt} +

+ ) : null} + + {authorNames.length > 0 ? ( + // `linkAuthors={false}` — the whole card is already an anchor, and an + // author link nested inside it would be invalid markup. + + ) : null} +
+ ); + + return ( +
+ {imageSrc ? ( +
+ {post.imageAlt +
+ ) : null} + {body} +
+ ); } diff --git a/apps/blog/src/components/Quote.tsx b/apps/blog/src/components/Quote.tsx index b6736eb3e55..deb4843fc08 100644 --- a/apps/blog/src/components/Quote.tsx +++ b/apps/blog/src/components/Quote.tsx @@ -21,23 +21,19 @@ export function Quotes({ }: QuoteProps) { return (
{children}
-
+
{speakerImgLink && ( )} diff --git a/apps/blog/src/components/SeriesBanner.tsx b/apps/blog/src/components/SeriesBanner.tsx index e1d1f8dfa4a..c3dea97d897 100644 --- a/apps/blog/src/components/SeriesBanner.tsx +++ b/apps/blog/src/components/SeriesBanner.tsx @@ -11,44 +11,52 @@ export function SeriesBanner({ series }: { series: SeriesContext }) { >
-
- Series -
+
Series
{series.title}
View series page →
{series.description ? ( -

{series.description}

+

+ {series.description} +

) : null} -
    + {/* Paper surface, hairline ring — a quiet index that sits under the + article rather than competing with it. */} +
      {series.posts.map((post, i) => { const isCurrent = i + 1 === series.index; const label = (post.seriesIndex ?? i + 1).toString().padStart(2, "0"); + // Hover on non-current rows is the docs sidebar's move: the row + // washes in `fd-accent` cyan and the title answers in + // `fd-accent-foreground` via group-hover (the title carries an + // explicit ink colour, so the wash alone would not recolour it). const inner = ( - + {label} {post.title} {isCurrent ? ( - + Reading ) : null} @@ -63,7 +71,7 @@ export function SeriesBanner({ series }: { series: SeriesContext }) { ) : ( {inner} diff --git a/apps/blog/src/components/SeriesMarker.tsx b/apps/blog/src/components/SeriesMarker.tsx index 7100e5698cf..150e665cb7f 100644 --- a/apps/blog/src/components/SeriesMarker.tsx +++ b/apps/blog/src/components/SeriesMarker.tsx @@ -4,23 +4,26 @@ import type { SeriesContext } from "@/lib/series"; export function SeriesMarker({ series }: { series: SeriesContext }) { const seriesUrl = `/series/${series.key}`; return ( -
      +
      Part{" "} - + {series.index} of {series.total} {" "} in the{" "} {series.title} {" "} series. - + View full series →
      diff --git a/apps/blog/src/components/SeriesNavigation.tsx b/apps/blog/src/components/SeriesNavigation.tsx index fff16b73c77..b1316a7b18a 100644 --- a/apps/blog/src/components/SeriesNavigation.tsx +++ b/apps/blog/src/components/SeriesNavigation.tsx @@ -8,7 +8,7 @@ export function SeriesNavigation({ series }: { series: SeriesContext }) {

MeterExpected pricePrice What it represents
- $1.00 / 1M requests + $1 per million The familiar per-request anchor that keeps a normal app easy to estimate