diff --git a/apps/marketing/src/components/Footer.astro b/apps/marketing/src/components/Footer.astro index 24bbc08aa..c6f9756d5 100644 --- a/apps/marketing/src/components/Footer.astro +++ b/apps/marketing/src/components/Footer.astro @@ -12,6 +12,7 @@
  • Quick Start
  • Docs
  • Blog
  • +
  • Showcase
  • Roadmap
  • Changelog
  • Releases
  • diff --git a/apps/marketing/src/components/Nav.astro b/apps/marketing/src/components/Nav.astro index 34b5a5717..5cf297f05 100644 --- a/apps/marketing/src/components/Nav.astro +++ b/apps/marketing/src/components/Nav.astro @@ -1,6 +1,6 @@ --- interface Props { - currentPage?: "blog" | "roadmap"; + currentPage?: "blog" | "roadmap" | "showcase"; } const { currentPage } = Astro.props; @@ -19,6 +19,8 @@ const linkClass = (page?: string) => Docs Blog + Showcase + Roadmap Changelog
    @@ -45,6 +47,8 @@ const linkClass = (page?: string) =>
    Docs Blog + Showcase + Roadmap Changelog
    diff --git a/apps/marketing/src/content.config.ts b/apps/marketing/src/content.config.ts index 8cae23293..cb921de69 100644 --- a/apps/marketing/src/content.config.ts +++ b/apps/marketing/src/content.config.ts @@ -22,4 +22,21 @@ const blog = defineCollection({ }), }); -export const collections = { roadmap, blog }; +const showcase = defineCollection({ + loader: glob({ pattern: "**/*.md", base: "./src/content/showcase" }), + schema: z.object({ + title: z.string(), + description: z.string(), + thumbnail: z.string(), + tags: z.array(z.string()), + languages: z.array(z.enum(["python", "rust", "typescript", "ruby"])), + github: z.string(), + models: z.array(z.string()), + skills: z.array(z.string()), + prompt: z.string(), + workflow: z.string(), + sortOrder: z.number(), + }), +}); + +export const collections = { roadmap, blog, showcase }; diff --git a/apps/marketing/src/content/showcase/docs-sync.md b/apps/marketing/src/content/showcase/docs-sync.md new file mode 100644 index 000000000..ae0ab6c80 --- /dev/null +++ b/apps/marketing/src/content/showcase/docs-sync.md @@ -0,0 +1,46 @@ +--- +title: "Docs Sync" +description: "Keeps documentation in sync with code changes by detecting drift and auto-updating affected pages." +thumbnail: "/showcase/docs-sync.png" +tags: ["documentation", "automation", "ci-cd"] +languages: ["typescript"] +github: "https://github.com/fabro-sh/fabro/tree/main/examples/docs-sync" +models: ["claude-sonnet-4-5"] +skills: ["code-review", "git", "documentation"] +prompt: "Compare the current codebase against the documentation. Identify any docs pages that are out of date with the code — changed APIs, renamed functions, removed features, or new features without docs. Update each affected page to match the current code, preserving the existing writing style and structure." +workflow: | + digraph DocsSync { + graph [ + goal="Detect and fix documentation drift from code changes" + model_stylesheet=" + * { model: claude-sonnet-4-5; } + " + ] + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + diff [label="Get Changes", prompt="Identify code changes since the last docs sync."] + scan [label="Scan Docs", prompt="Find documentation pages that reference changed code."] + update [label="Update Docs", prompt="Rewrite affected doc sections to match current code."] + review [shape=hexagon, label="Review Updates"] + + start -> diff -> scan -> update -> review + review -> exit [label="Approve"] + review -> update [label="Revise"] + } +sortOrder: 3 +--- + +The Docs Sync workflow detects when documentation has drifted from the codebase and automatically updates affected pages — with a human review gate before changes are committed. + +## How it works + +1. **Get Changes** — Identifies code changes since the last documentation sync using git history. +2. **Scan Docs** — Searches documentation pages for references to changed functions, APIs, types, and features. +3. **Update Docs** — Rewrites affected sections to match the current code, preserving the original writing style and page structure. +4. **Human Review** — Updated pages are presented for review. Approve to commit, or send back for revision. + +## Keeping docs honest + +Documentation drift is one of the most common sources of developer frustration. This workflow runs on every merge to main, catching drift before it reaches users. Because it understands both the code and the docs, it can make precise, targeted updates rather than generic rewrites. diff --git a/apps/marketing/src/content/showcase/pr-review-bot.md b/apps/marketing/src/content/showcase/pr-review-bot.md new file mode 100644 index 000000000..ff659b6ec --- /dev/null +++ b/apps/marketing/src/content/showcase/pr-review-bot.md @@ -0,0 +1,45 @@ +--- +title: "PR Review Bot" +description: "Automated code review that catches bugs, style issues, and security concerns before human reviewers see the PR." +thumbnail: "/showcase/pr-review-bot.png" +tags: ["code-review", "ci-cd", "github"] +languages: ["typescript", "python"] +github: "https://github.com/fabro-sh/fabro/tree/main/examples/pr-review-bot" +models: ["claude-sonnet-4-5", "claude-haiku-4-5"] +skills: ["code-review", "git", "github"] +prompt: "Review this pull request for bugs, security issues, and style violations. Focus on logic errors and potential runtime failures. Summarize findings as inline comments on the diff, then produce a top-level review with an overall assessment and a clear approve/request-changes verdict." +workflow: | + digraph PRReview { + graph [ + goal="Review a pull request for bugs, security, and style" + model_stylesheet=" + * { model: claude-haiku-4-5; } + .review { model: claude-sonnet-4-5; } + " + ] + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + fetch [label="Fetch Diff", prompt="Fetch the PR diff and changed file contents."] + triage [label="Triage Files", prompt="Categorize changed files by risk level."] + review [label="Deep Review", class="review", prompt="Review high-risk files for bugs, security issues, and style."] + comment [label="Post Comments", prompt="Post inline comments and a summary review on the PR."] + + start -> fetch -> triage -> review -> comment -> exit + } +sortOrder: 1 +--- + +The PR Review Bot workflow automates the first pass of code review on every pull request. It fetches the diff, triages files by risk level, performs a deep review on high-risk changes using a frontier model, and posts structured feedback directly on the PR. + +## How it works + +1. **Fetch Diff** — Pulls the PR diff and full contents of changed files using the GitHub API. +2. **Triage Files** — A fast model categorizes each changed file as high, medium, or low risk based on the type of change (new logic vs. formatting, test files vs. production code). +3. **Deep Review** — A frontier model examines high-risk files for logic errors, security vulnerabilities, race conditions, and style violations. +4. **Post Comments** — Inline comments are posted on specific lines, and a top-level review summary gives an overall verdict. + +## Cost optimization + +By using a model stylesheet, the workflow routes expensive frontier-model calls only to the deep review stage. File fetching and triaging use a fast, cheap model — keeping the total cost per review under $0.10 for most PRs. diff --git a/apps/marketing/src/content/showcase/test-generator.md b/apps/marketing/src/content/showcase/test-generator.md new file mode 100644 index 000000000..099f5fa95 --- /dev/null +++ b/apps/marketing/src/content/showcase/test-generator.md @@ -0,0 +1,52 @@ +--- +title: "Test Generator" +description: "Generates comprehensive test suites from source code, covering edge cases and error paths that humans often miss." +thumbnail: "/showcase/test-generator.png" +tags: ["testing", "code-generation", "automation"] +languages: ["typescript", "rust"] +github: "https://github.com/fabro-sh/fabro/tree/main/examples/test-generator" +models: ["claude-sonnet-4-5", "claude-haiku-4-5"] +skills: ["code-review", "testing", "code-generation"] +prompt: "Analyze the source files in this project and generate a comprehensive test suite. For each public function or method, write tests covering: happy path, edge cases, error conditions, and boundary values. Use the project's existing test framework and conventions. Run the tests and fix any failures before finishing." +workflow: | + digraph TestGenerator { + graph [ + goal="Generate and validate a test suite for source code" + model_stylesheet=" + * { model: claude-haiku-4-5; } + .analysis { model: claude-sonnet-4-5; } + .coding { model: claude-sonnet-4-5; } + " + ] + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + analyze [label="Analyze Source", class="analysis", prompt="Read source files and identify all public interfaces, edge cases, and error paths."] + plan [label="Plan Tests", prompt="Create a test plan covering happy paths, edge cases, and error conditions."] + approve [shape=hexagon, label="Approve Plan"] + generate [label="Generate Tests", class="coding", prompt="Write the test suite following the plan and project conventions."] + run [label="Run Tests", prompt="Execute the test suite and collect results."] + fix [label="Fix Failures", class="coding", prompt="Fix any failing tests, ensuring they test the right behavior."] + + start -> analyze -> plan -> approve + approve -> generate [label="Approve"] + approve -> plan [label="Revise"] + generate -> run -> fix -> run + run -> exit [label="All pass"] + } +sortOrder: 2 +--- + +The Test Generator workflow reads your source code, plans a comprehensive test suite, and writes tests that actually pass — with a human checkpoint to approve the plan before generation begins. + +## How it works + +1. **Analyze Source** — A frontier model reads the codebase and identifies all public functions, methods, and types that need test coverage. +2. **Plan Tests** — Generates a structured test plan covering happy paths, edge cases, boundary values, and error conditions. +3. **Human Approval** — The plan is presented for review. You can approve it or send it back for revision. +4. **Generate & Validate** — Tests are written following your project's conventions, then executed. Any failures are automatically fixed in a retry loop. + +## Why a workflow beats a single prompt + +A single "write tests" prompt often produces tests that don't compile or test the wrong things. By separating analysis, planning, and generation into distinct stages — and adding a human gate — this workflow produces tests that are both comprehensive and correct. diff --git a/apps/marketing/src/pages/index.astro b/apps/marketing/src/pages/index.astro index babd9445a..bd7f447da 100644 --- a/apps/marketing/src/pages/index.astro +++ b/apps/marketing/src/pages/index.astro @@ -52,7 +52,8 @@ const cssExample = `/* All nodes default to fast + ch - + +
    @@ -81,7 +82,8 @@ const cssExample = `/* All nodes default to fast + ch
    Docs Blog - + Showcase + Roadmap Changelog
    @@ -684,6 +686,7 @@ const cssExample = `/* All nodes default to fast + ch
  • Quick Start
  • Docs
  • Blog
  • +
  • Showcase
  • Roadmap
  • Changelog
  • Releases
  • diff --git a/apps/marketing/src/pages/showcase/[slug].astro b/apps/marketing/src/pages/showcase/[slug].astro new file mode 100644 index 000000000..5b04bcb64 --- /dev/null +++ b/apps/marketing/src/pages/showcase/[slug].astro @@ -0,0 +1,207 @@ +--- +import Layout from "../../layouts/Layout.astro"; +import Nav from "../../components/Nav.astro"; +import Footer from "../../components/Footer.astro"; +import PageScripts from "../../components/PageScripts.astro"; +import { getCollection, render } from "astro:content"; + +export async function getStaticPaths() { + const entries = await getCollection("showcase"); + return entries.map((entry) => ({ + params: { slug: entry.id }, + props: { entry }, + })); +} + +const { entry } = Astro.props; +const { Content } = await render(entry); + +const langIcons: Record = { + python: { + label: "Python", + path: "M12 1.5c-5.1 0-4.8 2.2-4.8 2.2l.006 2.3H12.4v.7H4.8S1.5 6.3 1.5 11.5s2.9 5 2.9 5h1.7V14.1s-.1-2.9 2.8-2.9h4.9s2.8 0 2.8-2.7V3.8s.4-2.3-4.6-2.3zm-2.7 1.3a.9.9 0 1 1 0 1.8.9.9 0 0 1 0-1.8zM12 22.5c5.1 0 4.8-2.2 4.8-2.2l-.006-2.3H11.6v-.7h7.6s3.3.4 3.3-4.8-2.9-5-2.9-5h-1.7v2.4s.1 2.9-2.8 2.9h-4.9s-2.8 0-2.8 2.7v4.7s-.4 2.3 4.6 2.3zm2.7-1.3a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8z", + }, + rust: { + label: "Rust", + path: "M23.8 14.1l-1.2-.7a10.5 10.5 0 0 0 0-2.8l1.2-.7a.3.3 0 0 0 .1-.4 12 12 0 0 0-2.6-4.5.3.3 0 0 0-.4 0l-1.2.7a10.2 10.2 0 0 0-2.4-1.4V3a.3.3 0 0 0-.2-.3 12 12 0 0 0-5.2 0 .3.3 0 0 0-.2.3v1.3a10.2 10.2 0 0 0-2.4 1.4l-1.2-.7a.3.3 0 0 0-.4 0A12 12 0 0 0 5.1 9.5a.3.3 0 0 0 .1.4l1.2.7a10.5 10.5 0 0 0 0 2.8l-1.2.7a.3.3 0 0 0-.1.4 12 12 0 0 0 2.6 4.5.3.3 0 0 0 .4 0l1.2-.7c.7.6 1.5 1 2.4 1.4V21a.3.3 0 0 0 .2.3 12 12 0 0 0 5.2 0 .3.3 0 0 0 .2-.3v-1.3c.9-.4 1.7-.8 2.4-1.4l1.2.7a.3.3 0 0 0 .4 0 12 12 0 0 0 2.6-4.5.3.3 0 0 0-.1-.4zM12 16.5a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9z", + }, + typescript: { + label: "TypeScript", + path: "M1.5 1.5h21v21h-21V1.5zm10.2 10.2v-1.8h6.6v1.8h-2.3v6.6h-2v-6.6h-2.3zm-4.1-1.8h2v4.5c0 .7.1 1.2.3 1.5.4.5 1 .8 1.8.8s1.4-.3 1.8-.8c.2-.3.3-.8.3-1.5V9.9h2v4.7c0 1-.2 1.8-.7 2.4-.7.9-1.8 1.3-3.4 1.3s-2.7-.4-3.4-1.3c-.5-.6-.7-1.4-.7-2.4V9.9z", + }, + ruby: { + label: "Ruby", + path: "M20.6 18.3L21.7 5l-5.5 1.5-2.5-3.5-3 3.2L4.3 3 3 10.5l3.3 2-3 4.2 5.3.8 1.5 4 4.5-2.8 4 3.6 2-4z", + }, +}; +--- + + +