Integration Recipes
Next.js App Router Integration
How to integrate `@cloudizero/sdk` with Next.js 14, 15, and 16 using React Server Actions and Client Components.
Server Action Upload Pattern
Using Server Actions keeps your master API key completely secure on the server while offering a clean, type-safe API for client forms:
app/actions/upload.ts
// app/actions/upload.ts
"use server";
import { Cloudizero } from "@cloudizero/sdk";
const cz = new Cloudizero({
apiKey: process.env.CLOUDIZERO_API_KEY!,
});
export async function uploadAvatar(formData: FormData) {
const file = formData.get("avatar") as File;
if (!file) throw new Error("No file provided");
const buffer = Buffer.from(await file.arrayBuffer());
const asset = await cz.storage.upload({
file: buffer,
fileName: file.name,
projectId: process.env.CLOUDIZERO_PROJECT_ID!,
mimeType: file.type,
});
return { success: true, url: asset.url };
}Client Form Component
Consuming the server action inside a React 19 Client Component:
app/components/avatar-uploader.tsx
// app/components/avatar-uploader.tsx
"use client";
import { useTransition } from "react";
import { uploadAvatar } from "@/app/actions/upload";
export function AvatarUploader() {
const [isPending, startTransition] = useTransition();
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
startTransition(async () => {
const res = await uploadAvatar(formData);
alert("Uploaded! " + res.url);
});
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<input type="file" name="avatar" required />
<button
type="submit"
disabled={isPending}
className="px-4 py-2 bg-blue-600 text-white rounded-lg disabled:opacity-50"
>
{isPending ? "Uploading..." : "Upload Avatar"}
</button>
</form>
);
}