Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nayalsaurav/Storx/llms.txt

Use this file to discover all available pages before exploring further.

Storx uses ImageKit as its file storage and CDN layer. When a user uploads a file, Storx sends the binary data to ImageKit and stores the returned delivery URL in Neon PostgreSQL. All subsequent file access goes directly through the ImageKit CDN — no file bytes are stored in the database or on the Next.js server.

Creating an ImageKit Account

1

Sign up at imagekit.io

Go to imagekit.io and create a free account. The free tier includes 20 GB of storage and 20 GB of bandwidth per month, which is sufficient for development and small-scale use.
2

Locate your credentials

After signing in, open the Developer Options section in the ImageKit dashboard (or go to Settings → API Keys). You will find:
  • Public Key — safe to use in the browser
  • Private Key — server-only; never expose this to the client
  • URL Endpoint — the base URL for all files in your account, e.g. https://ik.imagekit.io/your_imagekit_id
3

Add the three values to .env.local

.env.local
NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY=public_...
IMAGEKIT_PRIVATE_KEY=private_...
NEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/your_imagekit_id

How Storx Uses ImageKit

ImageKit Instance

A single ImageKit client is initialised once in lib/imagekit.ts and imported wherever uploads or authentication parameters are needed:
lib/imagekit.ts
import ImageKit from "imagekit";

export const imagekit = new ImageKit({
  publicKey: process.env.NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY!,
  privateKey: process.env.IMAGEKIT_PRIVATE_KEY!,
  urlEndpoint: process.env.NEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT!,
});

Upload Path Structure

Every file is placed in a deterministic folder path inside ImageKit based on the uploading user’s Clerk ID and the optional parent folder ID:
ScenarioImageKit folder path
File at the root level/storex/{userId}/
File inside a nested folder/storex/{userId}/folder/{parentId}/
The filename itself is a UUID with the original file extension appended (e.g. 550e8400-e29b-41d4-a716-446655440000.pdf). This is generated server-side so filenames are always unique within a folder:
app/api/files/upload/route.ts
const folderPath = parentId
  ? `/storex/${userId}/folder/${parentId}`
  : `/storex/${userId}`;

const filename = `${uuidv4()}.${fileExtension}`;

const uploadResponse = await imagekit.upload({
  file: fileBuffer,
  fileName: filename,
  folder: folderPath,
  useUniqueFileName: false,
});
useUniqueFileName: false is explicitly set because Storx manages uniqueness itself via UUIDs. Letting ImageKit append its own suffix would make the stored filename unpredictable.

Authentication Parameters

Client-side ImageKit uploads require a short-lived token that proves the request is authorised. Storx exposes a GET /api/imagekit-auth endpoint that:
  1. Validates the caller has an active Clerk session
  2. Calls imagekit.getAuthenticationParameters() on the server (using the private key)
  3. Returns the token, expire time, and signature to the browser
app/api/imagekit-auth/route.ts
import { imagekit } from "@/lib/imagekit";
import { auth } from "@clerk/nextjs/server";
import { NextResponse } from "next/server";

export async function GET() {
  try {
    const { userId } = await auth();
    if (!userId) {
      return NextResponse.json({ error: "unauthorized" }, { status: 401 });
    }

    const authParams = imagekit.getAuthenticationParameters();

    return Response.json({
      authParams,
    });
  } catch (error) {
    return NextResponse.json(
      { error: "failed to generate auth parameters for imagekit" },
      { status: 500 },
    );
  }
}
The endpoint returns 401 for unauthenticated callers and 500 if parameter generation fails.

Supported File Types

Only two MIME type groups are accepted. Any other type is rejected at the upload API route before the file is sent to ImageKit:
AcceptedMIME pattern
Imagesimage/* (JPEG, PNG, WebP, GIF, SVG, …)
Documentsapplication/pdf
app/api/files/upload/route.ts
// Validate file type
if (!file.type.startsWith("image/") && file.type !== "application/pdf") {
  return NextResponse.json(
    { error: "Only images and PDF files are supported" },
    { status: 400 },
  );
}
Attempting to upload any other MIME type (e.g. .docx, .zip, .mp4) returns a 400 Bad Request response with the message "Only images and PDF files are supported".
ImageKit’s free tier provides 20 GB of storage and 20 GB of monthly bandwidth. For a production deployment with multiple users, monitor your usage in the ImageKit dashboard and upgrade to a paid plan before hitting the limits. Exceeding the free quota does not automatically delete files, but new uploads and CDN delivery may be restricted until the plan is upgraded.

Build docs developers (and LLMs) love