Get started
Next.js CSV importer
Integrate CSVJetty with Next.js App Router or Pages Router and save imported CSV records through your own API route.
CSVJetty works with both Next.js routing systems. In the App Router, place the importer inside a client component because it opens a browser modal and uses client-side callbacks.

Install
BASH
npm install csvjettyApp Router
Add the importer to a client component. Keep database writes and secrets on the server by forwarding imported records to a route handler or server API.
app/contacts/ImportContacts.jsx
"use client";
import CSVJetty from "csvjetty";
export default function ImportContacts() { return ( <CSVJetty importerKey="YOUR_IMPORTER_KEY" onData={async ({ rows, importId, rowNumbers }) => { const response = await fetch("/api/contacts/import", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ rows, importId, rowNumbers }), });
if (!response.ok) throw new Error("Could not save contacts."); return response.json(); }} > Import contacts </CSVJetty> );}Pages Router
Pages Router components can import CSVJetty directly. The importer itself still runs in the browser.
components/ImportContacts.jsx
import CSVJetty from "csvjetty";
export default function ImportContacts() { return ( <CSVJetty importerKey="YOUR_IMPORTER_KEY" onData={async ({ rows, importId, rowNumbers }) => { const response = await fetch("/api/contacts/import", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ rows, importId, rowNumbers }), });
if (!response.ok) throw new Error("Could not save contacts."); return response.json(); }} > Import contacts </CSVJetty> );}Save through your API
With callback delivery, your browser handler should pass the records into an authenticated API endpoint that validates and persists them.
pages/api/contacts/import.js
export default async function handler(req, res) { if (req.method !== "POST") { res.setHeader("Allow", "POST"); return res.status(405).end(); }
// Authenticate the request for your application here. const { rows, importId, rowNumbers } = req.body;
// Validate rows again and make this write idempotent using importId. await saveContacts({ rows, importId, rowNumbers });
return res.status(200).json({ errors: [] });}Do not trust browser validation alone
Read Validation and corrections for the boundary between CSVJetty validation and your server-side rules.
Development mode
Enable Development Mode for the importer in the CSVJetty dashboard when testing. Development imports still deliver records, so point them at a test backend or safe development database. Localhost by itself does not enable Development Mode.
See Importer settings for the rest of the development and presentation controls.