Examples & Demos
Experience pushduck with interactive demos and real-world examples. All demos use live Cloudflare R2 integration.
Live Demos: These are fully functional demos using real Cloudflare R2 storage. Files are uploaded to a demo bucket and may be automatically cleaned up. Don't upload sensitive information.
Having Issues? If uploads aren't working (especially with next dev --turbo
), check our Troubleshooting Guide for common solutions including the known Turbo mode compatibility issue.
Interactive Upload Demo
The full-featured demo showcasing all capabilities:
🚀 Full-Featured Demo
Complete upload experience with type-safe client, progress tracking, and error handling
Live Demo: Files are uploaded to Cloudflare R2. Don't upload sensitive information.
Drag & drop files or click to browse
Maximum 5 files allowed
Drop files above or click to browse
💻 Code powering this demo:
// Enhanced type-safe client
const imageUpload = upload.imageUpload();
// Upload with full type safety
await imageUpload.uploadFiles(files);
// Access state with TypeScript inference
const {
files, // Individual file progress
isUploading, // Upload status
errors, // Any errors
progress, // Overall progress (0-100)
uploadSpeed, // Overall bytes/sec
eta // Overall time remaining
} = imageUpload;
ETA & Speed Tracking: Upload speed (MB/s) and estimated time remaining (ETA) appear below the progress bar during active uploads. Try uploading larger files (1MB+) to see these metrics in action! ETA becomes more accurate after the first few seconds of upload.
Image-Only Upload
Focused demo for image uploads with preview capabilities:
🖼️ Image Upload Demo
Optimized for images with instant previews and validation
Drag & drop files or click to browse
Maximum 5 files allowed
Drop files above or click to browse
Document Upload
Streamlined demo for document uploads:
📄 Document Upload Demo
Professional document handling with type validation
Drag & drop files or click to browse
Maximum 3 files allowed
Drop files above or click to browse
Key Features Demonstrated
✅ Type-Safe Client
// Property-based access with full TypeScript inference
const imageUpload = upload.imageUpload();
const fileUpload = upload.fileUpload();
// No string literals, no typos, full autocomplete
await imageUpload.uploadFiles(selectedFiles);
⚡ Real-Time Progress
- Individual file progress tracking with percentage completion
- Upload speed monitoring (MB/s) with live updates
- ETA calculations showing estimated time remaining
- Pause/resume functionality (coming soon)
- Comprehensive error handling with retry mechanisms
🔒 Built-in Validation
- File type validation (MIME types)
- File size limits with user-friendly errors
- Custom validation middleware
- Malicious file detection
🌐 Provider Agnostic
- Same code works with any S3-compatible provider
- Switch between Cloudflare R2, AWS S3, DigitalOcean Spaces
- Zero vendor lock-in
Code Examples
"use client";
import { upload } from "@/lib/upload-client";
export function SimpleUpload() {
const { uploadFiles, files, isUploading } = upload.imageUpload();
return (
<div>
<input
type="file"
multiple
accept="image/*"
onChange={(e) => uploadFiles(Array.from(e.target.files || []))}
disabled={isUploading}
/>
{files.map(file => (
<div key={file.id}>
<span>{file.name}</span>
<span>{file.status}</span>
{file.url && <a href={file.url}>View</a>}
</div>
))}
</div>
);
}
// app/api/upload/route.ts
import { createUploadConfig } from "pushduck/server";
const { s3, } = createUploadConfig()
.provider("cloudflareR2",{
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
bucket: process.env.R2_BUCKET!,
})
.defaults({
maxFileSize: "10MB",
acl: "public-read",
})
.build();
const uploadRouter = s3.createRouter({
imageUpload: s3
.image()
.maxFileSize("5MB")
.formats(["jpeg", "png", "webp"])
.middleware(async ({ file, metadata }) => {
// Custom authentication and metadata
const session = await getServerSession();
if (!session) throw new Error("Unauthorized");
return {
...metadata,
userId: session.user.id,
uploadedAt: new Date().toISOString(),
};
})
.onUploadComplete(async ({ file, url, metadata }) => {
// Post-upload processing
console.log(`Upload complete: ${url}`);
await saveToDatabase({ url, metadata });
}),
});
export const { GET, POST } = uploadRouter.handlers;
export type AppRouter = typeof uploadRouter;
"use client";
import { upload } from "@/lib/upload-client";
export function RobustUpload() {
const { uploadFiles, files, errors, reset } = upload.imageUpload();
const handleUpload = async (fileList: FileList) => {
try {
await uploadFiles(Array.from(fileList));
} catch (error) {
console.error("Upload failed:", error);
// Error is automatically added to the errors array
}
};
return (
<div>
<input
type="file"
onChange={(e) => e.target.files && handleUpload(e.target.files)}
/>
{/* Display errors */}
{errors.length > 0 && (
<div className="error-container">
<h4>Upload Errors:</h4>
{errors.map((error, index) => (
<p key={index} className="error">{error}</p>
))}
<button onClick={reset}>Clear Errors</button>
</div>
)}
{/* Display files with status */}
{files.map(file => (
<div key={file.id} className={`file-item ${file.status}`}>
<span>{file.name}</span>
<span>{file.status}</span>
{file.status === "uploading" && (
<progress value={file.progress} max={100} />
)}
{file.status === "error" && (
<span className="error">{file.error}</span>
)}
{file.status === "success" && file.url && (
<a href={file.url} target="_blank">View File</a>
)}
</div>
))}
</div>
);
}
Real-World Use Cases
Profile Picture Upload
Single image upload with instant preview and crop functionality.
Document Management
Multi-file document upload with categorization and metadata.
Media Gallery
Batch image upload with automatic optimization and thumbnail generation.
File Sharing
Secure file upload with expiration dates and access controls.
Next Steps
Troubleshooting
Fix common pushduck issues including CORS errors, TypeScript problems, upload failures, and environment variable configuration. Complete troubleshooting guide with solutions.
AI & LLM Integration
Access documentation content in AI-friendly formats for large language models and automated tools.