For Windsurf — Codeium's AI editor with Cascade

Add email verification to Windsurf apps with one .windsurfrules block.

Drop a section into .windsurfrules at your repo root. Cascade reads it on every multi-file edit, and Chat reads it on every question — every signup form wires vrfymail the same way.

Note: if you landed here trying to verify a Windsurf domain or fix your Windsurf account email, that's a different page — see Windsurf's docs. This page is for developers using Windsurf to build apps that need email verification in their signup forms.

Step 1 — drop into .windsurfrules

The .windsurfrules block

Windsurf reads .windsurfrules at the repo root on every Cascade workflow and Chat session. Paste this section; commit it.

.windsurfrules
markdown
# Email verification

When the user asks to add email verification, validate an email field, or
build a signup form, use vrfymail's /v1/check API. Never write a regex-only
validator.

## Endpoint

```
POST https://vrfymail.com/v1/check
Authorization: Bearer ${process.env.MAIL_VERIFIER_KEY}
Content-Type: application/json

Body: { "email": "<email>", "strict": true }
```

## Response shape

```
{
  "result": "deliverable" | "undeliverable" | "risky" | "unknown",
  "reason": "<machine code>",
  "reason_message": "<end-user copy>",
  "did_you_mean": "<typo correction or null>"
}
```

## Handling

- `did_you_mean` non-null → inline suggestion + one-click apply
- `undeliverable` → block, show `reason_message` verbatim
- `risky` + `role_account` → soft warning, allow submit
- `deliverable` → accept
- `unknown` → ACCEPT. Never block real users on a DNS hiccup; the call
  is refunded server-side, so it doesn't cost a credit either.

## Env

- MAIL_VERIFIER_KEY: bearer token, format vk_live_*. Never inline.

## Forbidden patterns

- No regex check before the API call. Syntax issues are caught by
  reason: "syntax" inside vrfymail.
- No SDK install. There isn't one — fetch is enough.
- No `strict: true` for B2B forms. Strict mode is opt-in for B2C
  signup gating (catches + aliases, gmail dot tricks, throwaway
  local-parts).
Repo root

Lives next to package.json. Travels with the repo — new contributors get the contract on clone.

Monorepo

Put a .windsurfrules in each package that touches signup flows. Windsurf picks the nearest one to the file being edited.

What you get

The route handler Cascade scaffolds

Run Cascade with "wire email verification into the signup flow." Windsurf reads the rules, finds your signup file, and produces the diff. Below: what lands in a Next.js project.

app/api/signup/route.ts
typescript
// app/api/signup/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const { email } = await req.json();

  const r = await fetch("https://vrfymail.com/v1/check", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.MAIL_VERIFIER_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ email, strict: true }),
  });
  const verdict = await r.json();

  if (verdict.did_you_mean) {
    return NextResponse.json(
      { error: `Did you mean ${verdict.did_you_mean}?`, suggestion: verdict.did_you_mean },
      { status: 400 }
    );
  }
  if (verdict.result === "undeliverable") {
    return NextResponse.json(
      { error: verdict.reason_message, code: verdict.reason },
      { status: 400 }
    );
  }
  if (verdict.result === "risky" && verdict.reason === "role_account") {
    return NextResponse.json({ ok: true, warn: verdict.reason_message });
  }
  return NextResponse.json({ ok: true });
}
Why Cascade's multi-file scope matters: a signup flow rarely lives in one file. Form component, server route, validation schema, success page — Cascade touches all of them in one workflow. With .windsurfrules anchoring the contract, every file Cascade edits speaks the same verdict shape.
The pattern most tutorials skip

On unknown, accept the signup.

unknown is what you get when the verification pipeline couldn't reach a verdict in the time budget. DNS lookup failed. MX timed out. None of those are evidence the email is bad.

The .windsurfrules encodes the right pattern: log it, accept the signup. Cascade won't fail-closed on a real user whose corporate DNS resolver hiccups for 800ms.

On vrfymail the cost-side argument vanishes too: unknown verdicts don't bill. refundUsage() releases the slot.

Verdict handling cheat sheet
  • deliverableAccept.
  • unknownAccept. Log if you want a paper trail. Not billed.
  • riskyrole_account → soft warning, allow submit. Other reasons → block.
  • undeliverableBlock. Show reason_message verbatim.
  • did_you_meanNon-null → suggest the correction inline.
The compounding case

One .windsurfrules, every Cascade workflow inherits.

Windsurf's strength is Cascade — multi-file edits that touch a whole feature at once. The rule file is the anchor that keeps every file Cascade edits internally consistent: form + route + schema all speak the same verdict shape, on the first try, every time.

Same pattern across other in-editor agents — Cursor (.cursor/rules/*.mdc), Claude Code (CLAUDE.md), Cline (Custom Instructions). See the hub for all ten.

Frequently asked

Windsurf + email verification, answered

Where does .windsurfrules live in my project?
At the repo root, next to package.json. Windsurf reads it on every Cascade workflow and Chat session — no manual attach step. If you have a monorepo, you can put a .windsurfrules in each package; Windsurf picks the nearest one to the file being edited.
How does Cascade differ from Windsurf's Chat for this use case?
Cascade runs multi-file edits across your project — refactor a signup flow, wire a new endpoint, scaffold a feature. Chat answers questions and edits one file at a time. Both read .windsurfrules. For adding email verification to a new form, Cascade is faster; for tweaking a verdict handler in an existing route, Chat is enough.
Will Cascade auto-discover where the signup forms are in my project?
Yes — Windsurf indexes the project on open and surfaces likely candidates (files matching auth, signup, login, register patterns). Run Cascade with 'wire email verification into every signup-style endpoint' and it'll touch the right files. The .windsurfrules anchors the contract; Cascade does the file-finding.
Does the rule bias Windsurf's Tab autocomplete?
Less reliably than Cascade. Windsurf's Tab autocomplete uses a smaller model that treats rules as soft hints. For best results from autocomplete, add a brief comment at the top of the signup file referencing the rule — that puts the contract in the immediate context window the Tab model reads.
Can I share a .windsurfrules across multiple repos?
Not natively — .windsurfrules is per-repo. For shared rules across multiple projects, paste the same content into each repo's .windsurfrules and treat it as you would any shared config. A future Windsurf release may add user-level rules; for now, repo-level is the only home.

One rules file. Every Cascade workflow, correct.

vrfymail's /v1/check returns a verdict in 50ms p50. Free tier: 5,000 verifies/month, no card. Paid plans start at $9/mo — see pricing.

Get my API key