Next.js · Gender prediction
Suggest gender from names in Next.js server actions
This server action, suggestGender, prefills an optional field during onboarding. It trims the first name, adds an ISO 3166-1 alpha-2 country code when your form or profile has one, and calls /v1/gender/name. The result is returned as a discriminated union, so the Client Component can switch on kind: suggested shows a preselected but editable option, ask leaves the field empty, and retry waits before asking again.
When result_status is unknown, gender is null and the action returns the reason, which could be not_found, ambiguous or insufficient_evidence. That answer has already been charged, so the code does not retry it. Errors other than rate limits also fall back to ask. The prediction is a statistical estimate of how a name is typically used, so the person's own selection always replaces it.
Steps
- 1
Add lib/finowl.ts and set FINOWL_API_KEY in your server environment.
- 2
Create app/onboarding/actions.ts with the suggestGender action.
- 3
Call it from your onboarding Client Component when the first name field loses focus.
- 4
Render the suggestion as an editable choice that includes a prefer-not-to-say option.
- 5
Save only the value the user confirms, never the raw prediction on its own.
npm install server-only// app/onboarding/actions.ts
"use server";
import { finowl, FinowlError } from "@/lib/finowl";
type Prediction = {
result_status: "identified" | "unknown";
gender: string | null;
confidence: number | null;
source: string | null;
reason: "not_found" | "no_name_candidate" | "ambiguous" | "insufficient_evidence" | null;
};
export type Suggestion =
| { kind: "suggested"; gender: string; confidence: number | null }
| { kind: "ask"; reason: string | null } // show an empty, optional field
| { kind: "retry"; afterSeconds: number | null };
// Prefills an optional, editable field. The user's own choice always wins.
export async function suggestGender(firstName: string, country?: string): Promise<Suggestion> {
const name = firstName.trim().slice(0, 254);
if (!name) return { kind: "ask", reason: "no_name_candidate" };
try {
const { data } = await finowl<{ data: Prediction }>(
"/v1/gender/name",
country ? { name, country } : { name },
);
if (data.result_status === "unknown" || !data.gender) {
return { kind: "ask", reason: data.reason }; // normal, billed result: don't retry
}
return { kind: "suggested", gender: data.gender, confidence: data.confidence };
} catch (err) {
if (!(err instanceof FinowlError)) throw err;
if (err.status === 429) return { kind: "retry", afterSeconds: err.retryAfter };
if (err.status === 400) return { kind: "ask", reason: "invalid_input" }; // e.g. bad country code
if (err.status === 401) console.error("Finowl rejected FINOWL_API_KEY");
return { kind: "ask", reason: null };
}
}IN PRODUCTION
Production tips
Call the action once per name rather than on each keystroke. Every lookup, including an unknown result, costs a credit, and a blur event is a natural moment to ask.
Mention name-based gender estimation in your privacy notice and in a short hint near the field, so people understand why a value was suggested and know they can change it.
Skip the AI options here. ai_mode always and forceToGenderize cost 3 credits each, and the default fallback mode already consults AI when the dataset has no answer.
Each lookup costs 1 credit (3 when it requests AI), with 100 free credits every month. See pricing and error codes.
A FEW GOOD QUESTIONS
Common questions
Related guides
- Check email breaches in a Next.js route handler
- Check breached passwords in a Next.js server action
- Predict gender from names in Python
- Predict gender from a name in Node.js
- Batch gender prediction in TypeScript
- Predict gender from names in Go with net/http
- Gender analytics from names for fintech audiences
- Gender insights from names for e-commerce analytics
- Gender estimates for SaaS user research and analytics
Suggest gender from names in Next.js server actions
Grab an API key, paste the example and run it. 100 free credits every month.