API Reference/CLI

CLI Reference

Complete reference for the pushduck CLI tool with all commands, options, and examples

🚀 Recommended: Use our CLI for the fastest setup experience

Quick Start

Get your file uploads working in under 2 minutes with our interactive CLI tool.

npx @pushduck/cli@latest init
pnpm dlx pushduck init
yarn dlx pushduck init
bunx pushduck init

The CLI will automatically:

  • 🔍 Detect your package manager (npm, pnpm, yarn, bun)
  • 📦 Install dependencies using your preferred package manager
  • ☁️ Set up your storage provider (Cloudflare R2, AWS S3, etc.)
  • 🛠️ Generate type-safe code (API routes, client, components)
  • ⚙️ Configure environment variables and bucket setup

What the CLI Does

Project Detection

Automatically detects your Next.js setup

  • Detects App Router vs Pages Router
  • Finds existing TypeScript configuration
  • Checks for existing upload implementations
  • Validates project structure

Provider Setup

Configures your chosen cloud storage provider

  • AWS S3, Cloudflare R2, DigitalOcean Spaces
  • Google Cloud Storage, MinIO
  • Automatic bucket creation
  • CORS configuration

Code Generation

Creates production-ready code

  • Type-safe API routes
  • Upload client configuration
  • Example components
  • Environment variable templates

Interactive Setup

Guided configuration with smart defaults

The CLI walks you through each step, asking only what's necessary for your specific setup.

CLI Commands

init - Initialize Setup

npx @pushduck/cli@latest init [options]

Options:

  • --provider <type> - Skip provider selection (aws|cloudflare-r2|digitalocean|minio|gcs)
  • --skip-examples - Don't generate example components
  • --skip-bucket - Don't create S3 bucket automatically
  • --api-path <path> - Custom API route path (default: /api/upload)
  • --dry-run - Show what would be created without creating
  • --verbose - Show detailed output

Examples:

# Interactive setup with all prompts
npx @pushduck/cli@latest init
# Skip provider selection, use AWS S3
npx @pushduck/cli@latest init --provider aws
# Use custom API route path
npx @pushduck/cli@latest init --api-path /api/files
# Generate only components, skip bucket creation
npx @pushduck/cli@latest init --skip-bucket --skip-examples

add - Add Upload Route

npx @pushduck/cli@latest add

Add new upload routes to existing configuration:

# Interactive route builder
npx @pushduck/cli@latest add

# Example output:
# ✨ Added imageUpload route for profile pictures
# ✨ Added documentUpload route for file attachments
# ✨ Updated router types

test - Test Configuration

npx @pushduck/cli@latest test [options]

Options:

  • --verbose - Show detailed test output

Validates your current setup:

npx @pushduck/cli@latest test

# Example output:
# ✅ Environment variables configured
# ✅ S3 bucket accessible
# ✅ CORS configuration valid
# ✅ API routes responding
# ✅ Types generated correctly

Interactive Setup Walkthrough

Step 1: Project Detection

🔍 Detecting your project...
  ✓ Next.js App Router detected
  ✓ TypeScript configuration found
  ✓ Package manager: pnpm detected
  ✓ No existing upload configuration
  ✓ Project structure validated

Step 2: Provider Selection

? Which cloud storage provider would you like to use?
❯ Cloudflare R2 (recommended)
  AWS S3 (classic, widely supported)
  DigitalOcean Spaces (simple, affordable)
  Google Cloud Storage (enterprise-grade)
  MinIO (self-hosted, open source)
  Custom S3-compatible endpoint

Step 3: Credential Setup

🔧 Setting up Cloudflare R2...

🔍 Checking for existing credentials...
  ✓ Found CLOUDFLARE_R2_ACCESS_KEY_ID
  ✓ Found CLOUDFLARE_R2_SECRET_ACCESS_KEY
  ✓ Found CLOUDFLARE_R2_ACCOUNT_ID
  ⚠ CLOUDFLARE_R2_BUCKET_NAME not found

? Enter your R2 bucket name: my-app-uploads
? Create bucket automatically? Yes

Step 4: API Configuration

? Where should we create the upload API?
❯ app/api/upload/route.ts (recommended)
  app/api/s3-upload/route.ts (classic)
  Custom path

? Generate example upload page? 
❯ Yes, create app/upload/page.tsx with full example
  Yes, just add components to components/ui/
  No, I'll build my own

Step 5: File Generation

🛠️ Generating files...

✨ Created files:
  ├── app/api/upload/route.ts
  ├── app/upload/page.tsx
  ├── components/ui/upload-button.tsx
  ├── components/ui/upload-dropzone.tsx
  ├── lib/upload-client.ts
  └── .env.example

📦 Installing dependencies...
  ✓ pushduck
  ✓ @aws-sdk/client-s3
  ✓ react-dropzone

🎉 Setup complete! Your uploads are ready.

Generated Project Structure

After running the CLI, your project will have:

.env.local
.env.example

Generated API Route

app/api/upload/route.ts
// No longer needed - use uploadRouter.handlers directly
import { s3 } from '@/lib/upload'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'

const s3Router = s3.createRouter({
  // Image uploads for profile pictures
  imageUpload: s3.image()
    .max("5MB")
    .count(1)
    .formats(["jpeg", "png", "webp"])
    .middleware(async ({ req, metadata }) => {
      const session = await getServerSession(authOptions)
      
      if (!session?.user?.id) {
        throw new Error("Authentication required")
      }
      
      return {
        ...metadata,
        userId: session.user.id,
        folder: `uploads/${session.user.id}`
      }
    }),

  // Document uploads
  documentUpload: s3.file()
    .max("10MB")
    .count(5)
    .types(["application/pdf", "text/plain", "application/msword"])
    .middleware(async ({ req, metadata }) => {
      const session = await getServerSession(authOptions)
      
      if (!session?.user?.id) {
        throw new Error("Authentication required")
      }
      
      return {
        ...metadata,
        userId: session.user.id,
        folder: `documents/${session.user.id}`
      }
    })
})

export type AppRouter = typeof s3Router
export const { GET, POST } = s3Router.handlers

Generated Upload Client

lib/upload-client.ts
import { createUploadClient } from 'pushduck/client'
import type { AppRouter } from '@/app/api/upload/route'

export const upload = createUploadClient<AppRouter>({
  endpoint: '/api/upload'
})

Generated Example Page

app/upload/page.tsx
import { UploadButton } from '@/components/ui/upload-button'
import { UploadDropzone } from '@/components/ui/upload-dropzone'

export default function UploadPage() {
  return (
    <div className="container mx-auto py-8">
      <h1 className="text-3xl font-bold mb-8">File Upload Demo</h1>
      
      <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
        <div>
          <h2 className="text-xl font-semibold mb-4">Profile Picture</h2>
          <UploadButton uploadType="imageUpload" />
        </div>
        
        <div>
          <h2 className="text-xl font-semibold mb-4">Documents</h2>
          <UploadDropzone uploadType="documentUpload" />
        </div>
      </div>
    </div>
  )
}

Environment Variables

The CLI automatically creates .env.example and prompts for missing values:

.env.example
# Cloudflare R2 Configuration (Recommended)
CLOUDFLARE_R2_ACCESS_KEY_ID=your_access_key_here
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_secret_key_here
CLOUDFLARE_R2_ACCOUNT_ID=your_account_id_here
CLOUDFLARE_R2_BUCKET_NAME=your-bucket-name

# Alternative: AWS S3 Configuration
# AWS_ACCESS_KEY_ID=your_access_key_here
# AWS_SECRET_ACCESS_KEY=your_secret_key_here
# AWS_REGION=us-east-1
# AWS_S3_BUCKET_NAME=your-bucket-name

# Next.js Configuration
NEXTAUTH_SECRET=your_nextauth_secret_here
NEXTAUTH_URL=http://localhost:3000

# Optional: Custom S3 endpoint (for MinIO, etc.)
# S3_ENDPOINT=https://your-custom-endpoint.com

Provider-Specific Setup

npx @pushduck/cli@latest init --provider cloudflare-r2

What gets configured:

  • Cloudflare R2 S3-compatible endpoints
  • Global edge network optimization
  • Zero egress fee configuration
  • CORS settings for web uploads
npx @pushduck/cli@latest init --provider aws

What gets configured:

  • AWS S3 regional endpoints
  • IAM permissions and policies
  • Bucket lifecycle management
  • CloudFront CDN integration (optional)
npx @pushduck/cli@latest init --provider digitalocean

Required Environment Variables:

  • AWS_ACCESS_KEY_ID (DO Spaces key)
  • AWS_SECRET_ACCESS_KEY (DO Spaces secret)
  • AWS_REGION (DO region)
  • AWS_S3_BUCKET_NAME
  • S3_ENDPOINT (DO Spaces endpoint)

What the CLI does:

  • Configures DigitalOcean Spaces endpoints
  • Sets up CDN configuration
  • Validates access permissions
  • Configures CORS policies
npx @pushduck/cli@latest init --provider minio

Required Environment Variables:

  • AWS_ACCESS_KEY_ID (MinIO access key)
  • AWS_SECRET_ACCESS_KEY (MinIO secret key)
  • AWS_REGION=us-east-1
  • AWS_S3_BUCKET_NAME
  • S3_ENDPOINT (MinIO server URL)

What the CLI does:

  • Configures self-hosted MinIO endpoints
  • Sets up bucket policies
  • Validates server connectivity
  • Configures development-friendly settings

Troubleshooting

CLI Not Found

# If you get "command not found"
npm install -g pushduck

# Or use npx for one-time usage
npx @pushduck/cli@latest@latest init

Permission Errors

# If you get permission errors during setup
sudo npx @pushduck/cli@latest init

# Or fix npm permissions
npm config set prefix ~/.npm-global
export PATH=~/.npm-global/bin:$PATH

Existing Configuration

# Force overwrite existing configuration
npx @pushduck/cli@latest init --force

# Or backup and regenerate
cp app/api/upload/route.ts app/api/upload/route.ts.backup
npx @pushduck/cli@latest init

Bucket Creation Failed

# Test your credentials first
npx @pushduck/cli@latest test

# Skip automatic bucket creation
npx @pushduck/cli@latest init --skip-bucket

# Create bucket manually, then run:
npx @pushduck/cli@latest test

Advanced Usage

Custom Templates

# Use custom file templates
npx @pushduck/cli@latest init --template enterprise

# Available templates:
# - default: Basic setup with examples
# - minimal: Just API routes, no examples  
# - enterprise: Full security and monitoring
# - ecommerce: Product images and documents

Monorepo Support

# For monorepos, specify the Next.js app directory
cd apps/web
npx @pushduck/cli@latest init

# Or use the --cwd flag
npx @pushduck/cli@latest init --cwd apps/web

CI/CD Integration

# Non-interactive mode for CI/CD
npx @pushduck/cli@latest init \
  --provider aws \
  --skip-examples \
  --api-path /api/upload \
  --no-interactive

Complete CLI Reference: This guide covers all CLI commands, options, and use cases. For a quick start, see our Getting Started guide.