Using grabr with Next.js
Because grabr writes directly to the filesystem and performs high-speed parallel network requests, it is designed to run in server environments (Node.js or Bun). You cannot run grabr directly inside a browser component.
In this tutorial, we will integrate grabr into a Next.js App Router project using a Server Action to trigger a backend download when a user clicks a button.
1. Create a Next.js Project
Start by initializing a fresh Next.js app and installing grabr.
npx create-next-app@latest my-grabr-app
cd my-grabr-app
npm install @linuxctrl/grabr2. Build the Server Action
We need a secure backend environment to run grabr. We'll create a Next.js Server Action that instantiates the downloader, adds a job, and starts the transfer.
Create a file at src/app/actions.ts:
"use server";
import { Downloader } from "@linuxctrl/grabr";
import path from "path";
import fs from "fs";
export async function triggerDownload(url: string, filename: string) {
const outputDir = path.join(process.cwd(), "downloads");
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const downloader = new Downloader();
await downloader.start();
try {
const job = await downloader.addJob(url, {
outputDir,
filename,
chunks: 8,
});
console.log(`Started downloading ${job.filename} (ID: ${job.id})`);
return { success: true, jobId: job.id };
} catch (error) {
console.error("Download failed to start:", error);
return { success: false, error: String(error) };
}
}3. Create the Frontend UI
Now we'll build a simple client component where the user can enter a URL and click a button to tell the server to fetch it using grabr.
Open src/app/page.tsx and replace its contents:
"use client";
import { useState } from "react";
import { triggerDownload } from "./actions";
export default function HomePage() {
const [url, setUrl] = useState("https://speed.hetzner.de/100MB.bin");
const [status, setStatus] = useState("");
const handleDownload = async () => {
setStatus("Starting grabr engine...");
const result = await triggerDownload(url, "test-file.bin");
if (result.success) {
setStatus(`Downloading! Check your terminal and the ./downloads folder.`);
} else {
setStatus(`Error: ${result.error}`);
}
};
return (
<main className="p-10 max-w-xl mx-auto space-y-4">
<h1 className="text-2xl font-bold">Grabr Next.js Demo</h1>
<input
type="text"
value={url}
onChange={(e) => setUrl(e.target.value)}
className="w-full p-2 border rounded text-black"
placeholder="Enter file URL..."
/>
<button
onClick={handleDownload}
className="px-4 py-2 bg-cyan-500 text-white font-bold rounded"
>
Download on Server
</button>
{status && <p className="text-sm font-medium mt-4">{status}</p>}
</main>
);
}4. Run the Application
Start your development server:
npm run devOpen your browser, click "Download on Server", and watch your server terminal! grabr will instantly parallel-chunk the file directly to your Next.js server's ./downloads folder at maximum speed.
Pro Tip: Progress Streaming
In a full production app, you can use grabr's built-in EventEmitter or WebSocket capabilities to stream live download progress (speeds and ETAs) from the Node.js server back to the React frontend using Server-Sent Events (SSE) or Socket.io!