Browse docs

Next.js Upload Guardrail

Scan browser uploads in a Next.js Route Handler before storage, OCR, extraction, or review.

Goal

Use this page when a browser uploads a file to your Next.js app.

This page proves one product flow:

browser upload -> Next.js server route -> Mighty scan -> store, quarantine, or reject

The point is not Next.js itself. The point is keeping the API key server-side and making sure files are scanned before storage, OCR, AI extraction, or review queues trust them.

When To Use This

Use it for:

  • Claim packet uploads.
  • Invoice or repair estimate uploads.
  • Damage photos uploaded through a web form.
  • Support attachments.
  • Any file that will later go to OCR, AI extraction, search, or workflow automation.

Architecture

  1. Browser posts the file to your Next.js route.
  2. The route forwards the file to Mighty with server-side auth.
  3. Mighty returns ALLOW, WARN, or BLOCK.
  4. The route stores, quarantines, or rejects the file.
  5. Downstream OCR or AI only runs after routing.

Route Handler

export const runtime = "nodejs";

export async function POST(request: Request) {
  const incoming = await request.formData();
  const file = incoming.get("file");

  if (!(file instanceof File)) {
    return Response.json({ error: "file is required" }, { status: 400 });
  }

  const mightyForm = new FormData();
  mightyForm.append("file", file);
  mightyForm.append("content_type", "auto");
  mightyForm.append("scan_phase", "input");
  mightyForm.append("mode", "secure");
  mightyForm.append("focus", "both");
  mightyForm.append("data_sensitivity", "tolerant");

  const scanResponse = await fetch("https://gateway.trymighty.ai/v1/scan", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.MIGHTY_API_KEY}`,
    },
    body: mightyForm,
  });

  if (!scanResponse.ok) {
    return Response.json(
      { error: "upload scan failed" },
      { status: scanResponse.status },
    );
  }

  const scan = await scanResponse.json();

  if (scan.action === "BLOCK") {
    return Response.json(
      { error: "upload blocked", scan_id: scan.scan_id },
      { status: 400 },
    );
  }

  if (scan.action === "WARN") {
    await saveUploadForReview(file, scan);
    return Response.json({ status: "review", scan_id: scan.scan_id });
  }

  await saveUploadForProcessing(file, scan);
  return Response.json({ status: "accepted", scan_id: scan.scan_id });
}

Routing Logic

async function saveUploadForReview(file: File, scan: { scan_id: string }) {
  // Store in quarantine or a restricted bucket.
}

async function saveUploadForProcessing(file: File, scan: { scan_id: string }) {
  // Store normally and enqueue OCR or extraction.
}

Common Mistake

Do not call Mighty directly from the browser. The upload route should proxy the file so your API key stays server-side.

Do not store first and scan later unless the storage location is quarantine-only. The safer default is scan first, then store normally only after routing.

Acceptance Criteria

  • Missing file returns 400.
  • Mighty BLOCK prevents normal storage.
  • Mighty WARN stores to review or quarantine.
  • Mighty ALLOW stores and continues processing.
  • Logs include scan_id.
Next step

Ready to scan real traffic?

Create an API key, keep it on your server, then wire Mighty into the workflow that handles untrusted material.

AI-Agent Prompt

AI-ready prompt
Add a Next.js upload guardrail

Paste this into Cursor, Codex, Claude Code, or Windsurf.

Add Mighty to a Next.js App Router upload endpoint.

Requirements:
- Use runtime=nodejs.
- Parse request.formData().
- Require a file field.
- Forward the file to POST https://gateway.trymighty.ai/v1/scan with multipart form data.
- Use content_type=auto, scan_phase=input, mode=secure, focus=both, data_sensitivity=tolerant.
- Route BLOCK to reject or quarantine.
- Route WARN to quarantine and review.
- Route ALLOW to normal storage and processing.
- Store scan_id and scan_group_id with the upload record.

Acceptance criteria:
- API key only exists server-side.
- Tests cover missing file, ALLOW, WARN, BLOCK, and Mighty error status.