Skip to content

docs(blog): add Langfuse v4 launch post - #3502

Open
maxdeichmann wants to merge 25 commits into
mainfrom
codex/v4-launch-blog
Open

docs(blog): add Langfuse v4 launch post#3502
maxdeichmann wants to merge 25 commits into
mainfrom
codex/v4-launch-blog

Conversation

@maxdeichmann

@maxdeichmann maxdeichmann commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

  • add the Langfuse v4 launch post with clear paths for new users, Cloud projects, and self-hosted deployments
  • lead with product outcomes, feature cards, an inline Pulse demo, and measured performance improvements
  • add project-specific Cloud migration guidance and treat the in-app checklist as the source of truth
  • document the safe self-hosted upgrade sequence, infrastructure requirements, Helm blocker, backfill expectations, and rollback boundary
  • preserve self-closing Card content and links in generated Markdown

Why

Langfuse v4 needs a calm, performance-led launch post that helps every reader quickly understand what changed and whether they need to act. Independent reviews covered newcomers, non-technical leads, Cloud owners, self-hosted operators, skeptical migration users, SDK/API integrators, and data-platform engineers.

Validation

  • pnpm run format:check
  • node scripts/check-h1-headings.js
  • node scripts/copy_md_sources.js and inspected public/md-src/blog/2026-08-13-langfuse-v4.md
  • rendered /blog/2026-08-13-langfuse-v4 locally and inspected the hero, audience cards, feature cards, Pulse demo, Cloud screenshot, warning callout, migration table, architecture diagram, and CTA grid
  • confirmed responsive card classes and overflow-safe table wrapper
  • browser console: no errors
  • pnpm run link-check scanned all 1,421 files; the new post links passed, with nine unrelated existing /llms*.txt localhost failures

Note

Low Risk
Documentation, redirects, and static-site component changes only; no application runtime or auth/data paths are modified.

Overview
Langfuse v4 launch and Cloud cutover date. Adds a changelog entry for the v4 GA announcement (audience cards, feature links, migration assistant screenshot, Q&A links) and points the top site banner at it. Permanent redirects move the former blog URL to /changelog/2026-08-13-langfuse-v4.

November 15, 2026 replaces placeholder “date will follow” language in compatibility snippets, VersionTimeline, v4 overview, blob export, public API ingestion callouts, and the upgrade FAQ. Cloud rollout copy now centers the v4 Upgrade Check / migration status page instead of generic “Action required” UI.

Docs UI and md-src pipeline. Linked Card components can show a trailing chevron when arrow is set (used heavily on the new post). Plain-Markdown generation converts self-closing Cards groups to bullet links (only when the whole group is supported) and renders VersionTimeline as text lines.

Removes several internal research/*.md notes that are no longer needed in-repo.

Reviewed by Cursor Bugbot for commit 66e77da. Bugbot is set up for automated code reviews on this repo. Configure here.

Greptile Summary

The PR adds the Langfuse v4 launch post and extends plain-Markdown generation to preserve links and descriptions from self-closing Card groups.

  • Documents Cloud and self-hosted v4 migration paths, performance improvements, and data-model changes.
  • Converts supported Card groups into Markdown bullet links for md-src and LLM-oriented output.
  • The conversion should reject partially matched groups to avoid silently dropping unsupported children.

Confidence Score: 4/5

The PR appears safe to merge, with a non-blocking robustness issue in partial Card-group conversion.

The new post’s repository-backed dependencies resolve, while the Markdown converter should verify that it consumed the complete Cards group before replacing it.

Files Needing Attention: lib/markdown-component-renderers.js

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A["Content MDX"] --> B["replaceComponentsWithMarkdown"]
  B --> C["Convert supported Cards to Markdown links"]
  C --> D["stripMdxForPlainMarkdown"]
  D --> E["public/md-src Markdown"]
  E --> F[".md routes / LLM consumers"]
Loading
Prompt To Fix All With AI
### Issue 1
lib/markdown-component-renderers.js:52-54
**Partial card groups lose content**

When a `<Cards>` group combines matching self-closing `<Card />` elements with text or unsupported children, `renderSelfClosingCards` renders only the matched cards and replaces the entire group, silently omitting the remaining content from generated Markdown.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "docs(blog): refine Langfuse v4 launch po..." | Re-trigger Greptile

Context used:

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
langfuse-docs Ready Ready Preview Aug 12, 2026 7:19pm

Request Review

@maxdeichmann
maxdeichmann marked this pull request as ready for review August 11, 2026 19:51
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. documentation Improvements or additions to documentation labels Aug 11, 2026
@github-actions

Copy link
Copy Markdown

@claude review

Comment thread lib/markdown-component-renderers.js

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is mostly a new blog post (low risk) plus a small helper in lib/markdown-component-renderers.js for converting <Cards> blocks to Markdown. The inline finding is a real, reproducible bug: the new card-conversion regex silently drops non-matching cards (e.g. single-line self-closing cards) whenever at least one card in the group matches, which deletes real content from content/marketing/careers.mdx in the generated Markdown export today. Given that's silent data loss on existing content (not just a missed case for the new post), I'd like a human to confirm the fix before merging.

Extended reasoning...

Overview

The PR adds the Langfuse v4 launch blog post (content/blog/2026-08-13-langfuse-v4.mdx) and a new replaceCardGroupsWithMarkdown/renderSelfClosingCards helper in lib/markdown-component-renderers.js intended to preserve self-closing <Card> content when converting MDX <Cards> blocks to plain Markdown for the public/md-src export (used by llms.txt/PDF generation).

Security risks

None. This is a docs-content addition plus a build-time text transform used only for a secondary Markdown export; it does not touch auth, data handling, or any runtime product code.

Level of scrutiny

The blog post itself warrants light scrutiny (content-only, no logic). The renderer change, though small, warrants closer scrutiny because it's a regex-based transform with a silent-fallback design (?? fullMatch) — exactly the kind of code where a partial match can quietly corrupt output instead of failing loudly. That's what happened here: I verified by inspecting content/marketing/careers.mdx that it contains a <Cards> group mixing multi-line self-closing cards (which the new regex matches) with single-line self-closing cards (which it doesn't), and confirmed the existing bug report's claim that the guard (cardMatches.length === 0) only fires on zero matches, not partial matches, so non-matching cards are dropped rather than falling back to raw JSX.

Other factors

This is exactly the kind of bug that should block approval per the review guidelines — it causes silent content loss on a page that already exists in production, not just an edge case in the new post. No prior reviews from me exist on this PR, so this is a fresh assessment rather than a repeat of prior feedback.

Comment on lines +54 to +71
function renderSelfClosingCards(cardsSource) {
const cardMatches = [
...cardsSource.matchAll(/^\s*<Card\b([\s\S]*?)^\s*\/>\s*$/gm),
];
if (cardMatches.length === 0) return null;

const lines = [];
for (const [, attributes] of cardMatches) {
const title = extractAttributeString(attributes, "title");
const href = extractAttributeString(attributes, "href");
const description = extractAttributeString(attributes, "description");

if (!title || !href) return null;

lines.push(`- [${title}](${href})${description ? `: ${description}` : ""}`);
}

return `\n${lines.join("\n")}\n`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 The new renderSelfClosingCards helper (lib/markdown-component-renderers.js:54-71) uses a regex that only matches self-closing <Card ... /> tags when the closing /> sits alone on its own line, so single-line cards never match it. Worse, when a <Cards> group mixes matching and non-matching cards, the block is still rewritten because cardMatches.length > 0, so the non-matching cards are silently dropped instead of falling back to the raw JSX. This is reproducible today: running the exporter on content/marketing/careers.mdx drops the "Documentation", "Roadmap", and "Example project" links, keeping only the two multi-line cards.

Extended reasoning...

The bug: renderSelfClosingCards finds Card tags with /^\s*<Card\b([\s\S]*?)^\s*\/>\s*$/gm. The ^\s* immediately before \/> (combined with the m flag) requires the closing /> to be the first non-whitespace token on its own line. That's only true for the multi-line attribute style used by the new v4 blog post itself (each attribute on its own line, /> alone on the last line). The far more common single-line style, e.g. <Card title=\"Documentation\" href=\"/docs\" icon={<BookOpen />} />, never matches because /> is preceded by other content on the same line.\n\nWhy this causes silent data loss, not just a missed conversion: replaceCardGroupsWithMarkdown calls renderSelfClosingCards(cardsSource) ?? fullMatch per <Cards>...</Cards> block. The ?? fullMatch fallback is only reached when cardMatches.length === 0 (i.e. zero cards in the group matched). If a group mixes matching and non-matching cards — some multi-line self-closing cards plus one or more single-line/children-based cards — cardMatches.length is still greater than zero, so the function returns a real markdown list instead of null. The whole <Cards> block is then replaced by that list, and every non-matching card inside it silently vanishes from the output with no warning, error, or fallback.\n\nConcrete proof from real repo content: content/marketing/careers.mdx has exactly this mixed pattern:\njsx\n<Cards num={3}>\n <Card title=\"GitHub Repositories\" href=\"...\" icon={<Github />} /> {/* multi-line, matches */}\n <Card title=\"GitHub Discussions\" href=\"...\" icon={<Github />} /> {/* multi-line, matches */}\n <Card title=\"Documentation\" href=\"/docs\" icon={<BookOpen />} /> {/* single-line, does NOT match */}\n <Card title=\"Roadmap\" href=\"/docs/roadmap\" icon={<ListOrdered />} /> {/* single-line, does NOT match */}\n <Card title=\"Example project\" href=\"/docs/demo\" icon={<Joystick />} /> {/* single-line, does NOT match */}\n</Cards>\n\nI ran replaceComponentsWithMarkdown directly on this file's contents. The output collapses the block to:\n\n- [GitHub Repositories](https://github.com/orgs/langfuse/repositories)\n- [GitHub Discussions](https://github.com/orgs/langfuse/discussions)\n\nThe Documentation, Roadmap, and Example project links are gone entirely — not left as raw JSX, just deleted. This directly contradicts the PR's own stated goal of "preserve self-closing Card content and links in generated Markdown."\n\nA second, related manifestation (also verified by a node repro) is a <Cards> group that mixes a self-closing <Card ... /> with a children-based <Card ...>...</Card>. The non-greedy [\s\S]*? in the regex can span across an entire children-based card to reach a later self-closing card's />, or simply skip the children card altogether — either way the children card's title/href/content disappears from the output with cardMatches.length > 0 still true, so the safety fallback never fires.\n\nWhy the existing code doesn't catch this: the only guard is cardMatches.length === 0, which assumes "no matches" is the only failure mode. It doesn't check that every <Card\b> in the source was actually captured, so partial matches are treated as success.\n\nSuggested fix: only accept the conversion when every <Card\b occurrence in cardsSource was captured by the match — e.g. compare (cardsSource.match(/<Card\b/g) ?? []).length against cardMatches.length, and return null (falling back to the safe raw-JSX path) whenever they differ. Widening the regex to also accept single-line self-closing cards would fix the common case, but the count-based guard is what actually closes the silent-data-loss hole for any pattern the regex doesn't anticipate (including future children-based cards).\n\nImpact: this only affects the secondary Markdown/PDF export path (public/md-src, used by llms.txt and PDF generation), not the live rendered site — the actual blog post and site pages render correctly via JSX regardless. But it silently deletes real, existing content (careers page links) from that export today, and will keep doing so for any other page with a similar mixed <Cards> group.

@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Aug 11, 2026
Comment thread lib/redirects.js
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Aug 12, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c8d3f89. Configure here.

Comment thread lib/redirects.js Outdated
Import the lucide icons used by the changelog CTA cards, format the upgrade FAQ, harden Cards-to-Markdown conversion against partial matches, and keep /docs/v4 on the docs overview while redirecting the blog .md URL.

Co-authored-by: Max Deichmann <max@langfuse.com>
cursoragent and others added 2 commits August 12, 2026 18:22
Co-authored-by: Max Deichmann <max@langfuse.com>
Co-authored-by: Max Deichmann <max@langfuse.com>
cursoragent and others added 2 commits August 12, 2026 18:37
Co-authored-by: Max Deichmann <max@langfuse.com>
Co-authored-by: Max Deichmann <max@langfuse.com>

Langfuse v4 is live on Langfuse Cloud and generally available for [self-hosted deployments](/self-hosting/upgrade/upgrade-guides/upgrade-v3-to-v4). It makes it faster to debug, evaluate, and monitor complex LLM applications by letting you work with every LLM call, tool execution, and agent step directly. Initial table loads over large datasets drop from seconds to milliseconds, and dashboards over longer time ranges load at least 10x faster in large projects.

Langfuse Cloud becomes v4-only on **November 15, 2026**. Most projects need no migration. If **Action required** lists checks for your project, complete them before this date.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grammar issue here, "If Action required lists checks for your project, complete them before this date."

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think that Action Required is a good way to refer to this, I would call it v4 Upgrade Check or similar


Langfuse Cloud becomes v4-only on **November 15, 2026**. Most projects need no migration. If **Action required** lists checks for your project, complete them before this date.

<Cards num={3} className="gap-3">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did not realize first that these were clickable, I would suggest they have an arrow, seems like generally useful for all cards


Langfuse v4 is much faster and also ships new ways to search, monitor, evaluate, and query your application data.

<Cards num={2} className="gap-3">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can these open in a new tab?


## What we shipped in Langfuse v4

Langfuse v4 is much faster and also ships new ways to search, monitor, evaluate, and query your application data.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Langfuse v4 is much faster and also ships new ways to search, monitor, evaluate, and query your application data.
Langfuse v4 is much faster and also ships new ways to search, monitor, evaluate, and query your application data. Check them out:


<VersionTimeline deployments={["cloud"]} />

New projects already use v4 and need no migration. For existing projects, organization owners can open the **Migration sidebar** and the [**Migration status page**](https://cloud.langfuse.com/v4-migration) to see if any actions are required:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here it is not called "Action Required", this naming is better

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a line break, this should be two paragraphs or an UL


You can also join a live Q&A with the Langfuse engineering team. Bring migration questions or your actual setup:

- [Wed, Aug 19 · 9:00 AM CEST](https://lu.ma/vtp4ofae)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why CEST time here? I'd show a list of timezones, PST, EST, CEST, bangalore time, singapore time

Rename Action Required to v4 Upgrade Check, add card arrows, open feature
cards in a new tab, split the Cloud migration copy, and list Q&A times
across PT/ET/CEST/IST/SGT.

Co-authored-by: Max Deichmann <max@langfuse.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants