DevFlow

AI code review for GitHub pull requests

Connect a GitHub account, open a pull request, and get back a structured review — a plain-language summary, a ranked list of likely bugs with file locations and severity, and non-blocking suggestions — in a panel beside the diff.

Next.js 16TypeScriptSupabasePostgreSQLGeminiOctokitTailwind CSSFramer Motion
DevFlow

DevFlow reads a pull request diff and hands back something you can act on: a summary of what the PR does, a ranked list of likely bugs with severity and file locations, and separate non-blocking suggestions. Reviews are saved per user, so you can reopen a PR and see what the model said last time.

Why bother

Asking a chat window to "review this PR" gives you prose — confident, unstructured, and impossible to triage. I wanted the opposite: output with a fixed shape, so a review can be sorted, ranked, stored, and compared against the next one. That constraint drove almost every decision in the project.

Making the model return data, not paragraphs

Gemini is called with a JSON response schema, so the shape of a review is enforced by the model rather than hoped for. What comes back is then parsed and validated against a Zod schema before it is trusted — if the model returns malformed JSON or drifts from the contract, the request fails loudly with a clean error state instead of writing junk to the database.

The overall severity of a review isn't taken from the model's own summary judgment. It's derived: the worst individual bug wins, falling back to the model's call only when there are no bugs at all. Small thing, but it means the badge on a review can never disagree with the findings underneath it.

The system prompt spends most of its length discouraging invention — an honest empty review beats a padded one, and the model is told so explicitly. It's also told it can only see the diff, not the surrounding codebase, which noticeably cuts down on confident speculation about code that isn't there.

Working within GitHub's limits

  • Diffs are fetched through Octokit in GitHub's raw diff format, then capped at 60k characters with an explicit truncation marker — big enough for real PRs, bounded enough to keep prompts and payloads predictable.
  • Supabase only exposes the GitHub provider token right after sign-in, and drops it when its own access token later refreshes. DevFlow copies that token into its own httpOnly cookie at the OAuth callback and reads from there first, so GitHub access survives a refresh.
  • Every review is written with the user's id attached and read back through Postgres Row Level Security — each policy compares auth.uid(), so a user can only ever touch their own rows, enforced by the database rather than by application code.

The app itself

It's Next.js 16 on the App Router with React Server Components, typed end-to-end in TypeScript strict mode. Review generation runs as a server action so the API keys never reach the browser, and the result comes back serializable to update the panel in place. Every async route has a loading skeleton and an error boundary — the difference between a demo and something you'd actually leave open in a tab.

DevFlow dashboard listing repositories and recent activity
The dashboard — your repositories, sorted by recent activity.
A pull request diff beside the AI review panel, in dark mode
The review panel sits beside the diff, so findings stay next to the code they describe.
DevFlow sign-in screen with GitHub OAuth, in dark mode
One-click GitHub OAuth — the only credential the app ever asks for.