Framework Integrations

Hono

Fast, lightweight file uploads with Hono using Web Standards - no adapter needed!

Hono Integration

Hono is a fast, lightweight web framework built on Web Standards. Since Hono uses Request and Response objects natively, pushduck handlers work directly without any adapters!

Web Standards Native: Hono exposes c.req.raw as a Web Standard Request object, making pushduck integration seamless with zero overhead.

Quick Setup

Install dependencies

npm install pushduck
yarn add pushduck
pnpm add pushduck
bun add pushduck

Configure upload router

lib/upload.ts
import { createUploadConfig } from 'pushduck/server';

const { s3, createS3Router } = createUploadConfig()
  .provider("cloudflareR2",{
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
    region: 'auto',
    endpoint: process.env.AWS_ENDPOINT_URL!,
    bucket: process.env.S3_BUCKET_NAME!,
    accountId: process.env.R2_ACCOUNT_ID!,
  })
  .build();

export const uploadRouter = createS3Router({
  imageUpload: s3.image().max("5MB"),
  documentUpload: s3.file().max("10MB")
});

export type AppUploadRouter = typeof uploadRouter;

Create Hono app with upload routes

app.ts
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';

const app = new Hono();

// Direct usage - no adapter needed!
app.all('/api/upload/*', (c) => {
  return uploadRouter.handlers(c.req.raw);
});

export default app;

Basic Integration

Simple Upload Route

app.ts
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';

const app = new Hono();

// Method 1: Combined handler (recommended)
app.all('/api/upload/*', (c) => {
  return uploadRouter.handlers(c.req.raw);
});

// Method 2: Separate handlers (if you need method-specific logic)
app.get('/api/upload/*', (c) => uploadRouter.handlers.GET(c.req.raw));
app.post('/api/upload/*', (c) => uploadRouter.handlers.POST(c.req.raw));

export default app;

With Middleware

app.ts
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { uploadRouter } from './lib/upload';

const app = new Hono();

// Global middleware
app.use('*', logger());
app.use('*', cors({
  origin: ['http://localhost:3000', 'https://your-domain.com'],
  allowMethods: ['GET', 'POST'],
  allowHeaders: ['Content-Type'],
}));

// Upload routes
app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));

// Health check
app.get('/health', (c) => c.json({ status: 'ok' }));

export default app;

Advanced Configuration

Authentication with Hono

lib/upload.ts
import { createUploadConfig } from 'pushduck/server';
import { verify } from 'hono/jwt';

const { s3, createS3Router } = createUploadConfig()
  .provider("cloudflareR2",{
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
    region: 'auto',
    endpoint: process.env.AWS_ENDPOINT_URL!,
    bucket: process.env.S3_BUCKET_NAME!,
    accountId: process.env.R2_ACCOUNT_ID!,
  })
  .paths({
    prefix: 'uploads',
    generateKey: (file, metadata) => {
      return `${metadata.userId}/${Date.now()}/${file.name}`;
    }
  })
  .build();

export const uploadRouter = createS3Router({
  // Private uploads with JWT authentication
  privateUpload: s3
    .image()
    .max("5MB")
    .middleware(async ({ req }) => {
      const authHeader = req.headers.get('authorization');
      if (!authHeader?.startsWith('Bearer ')) {
        throw new Error('Authorization required');
      }

      const token = authHeader.substring(7);
      
      try {
        const payload = await verify(token, process.env.JWT_SECRET!);
        return {
          userId: payload.sub as string,
          userRole: payload.role as string
        };
      } catch (error) {
        throw new Error('Invalid token');
      }
    }),

  // Public uploads (no auth)
  publicUpload: s3
    .image()
    .max("2MB")
    // No middleware = public access
});

export type AppUploadRouter = typeof uploadRouter;

Deployment Options

src/index.ts
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';

const app = new Hono();

app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));

export default app;
wrangler.toml
name = "my-upload-api"
main = "src/index.ts"
compatibility_date = "2023-12-01"

[env.production]
vars = { NODE_ENV = "production" }
# Deploy to Cloudflare Workers
npx wrangler deploy
server.ts
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';

const app = new Hono();

app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));

export default {
  port: 3000,
  fetch: app.fetch,
};
# Run with Bun
bun run server.ts
server.ts
import { serve } from '@hono/node-server';
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload';

const app = new Hono();

app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));

const port = 3000;
console.log(`Server is running on port ${port}`);

serve({
  fetch: app.fetch,
  port
});
# Run with Node.js
npm run dev
server.ts
import { Hono } from 'hono';
import { uploadRouter } from './lib/upload.ts';

const app = new Hono();

app.all('/api/upload/*', (c) => uploadRouter.handlers(c.req.raw));

Deno.serve(app.fetch);
# Run with Deno
deno run --allow-net --allow-env server.ts

Performance Benefits

🚀 Zero Overhead

Direct Web Standards integration

No adapter layer means zero performance overhead - pushduck handlers run directly in Hono.

⚡ Fast Runtime

Hono's lightweight design

Hono is one of the fastest web frameworks, perfect for high-performance upload APIs.

🌐 Edge Ready

Deploy anywhere

Works on Cloudflare Workers, Bun, Node.js, and Deno with the same code.

📦 Small Bundle

Minimal dependencies

Hono + pushduck creates incredibly lightweight upload services.


Perfect Match: Hono's Web Standards foundation and pushduck's universal design create a powerful, fast, and lightweight file upload solution that works everywhere.