Adapters

Supabase Storage

Use Shelf UI components with Supabase Storage for seamless file uploads.

SupabaseStorage

Introduction

The Supabase adapter provides first-class integration with Supabase Storage, making it easy to upload, manage, and serve files directly from your Supabase project.

Installation

pnpm add @supabase/supabase-js

Setup

1. Create Supabase Client

// lib/supabase.ts
import { createClient } from '@supabase/supabase-js'

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

2. Create Storage Bucket

In your Supabase dashboard:

  1. Go to Storage
  2. Create a new bucket (e.g., uploads)
  3. Set the bucket policy (public or private)

Storage Policies

Make sure to configure Row Level Security (RLS) policies for your storage bucket to control access.

Usage

Basic Upload

import { Dropzone } from "@/components/ui/dropzone"
import { supabase } from "@/lib/supabase"
import { useState } from "react"

export function SupabaseUpload() {
  const [uploading, setUploading] = useState(false)

  const handleUpload = async (files: File[]) => {
    setUploading(true)

    for (const file of files) {
      const filePath = `${Date.now()}-${file.name}`

      const { data, error } = await supabase.storage
        .from('uploads')
        .upload(filePath, file)

      if (error) {
        console.error('Upload error:', error)
      } else {
        console.log('Uploaded:', data.path)
      }
    }

    setUploading(false)
  }

  return (
    <Dropzone onDrop={handleUpload} disabled={uploading}>
      {uploading ? 'Uploading...' : 'Drop files to upload'}
    </Dropzone>
  )
}

Get Public URL

const { data } = supabase.storage
  .from('uploads')
  .getPublicUrl('file-path.jpg')

console.log(data.publicUrl)

Download File

const { data, error } = await supabase.storage
  .from('uploads')
  .download('file-path.jpg')

Delete File

const { error } = await supabase.storage
  .from('uploads')
  .remove(['file-path.jpg'])

Advanced

Upload with Progress

import { UploadProgress } from "@/components/ui/upload-progress"

const { data, error } = await supabase.storage
  .from('uploads')
  .upload(filePath, file, {
    cacheControl: '3600',
    upsert: false,
    onUploadProgress: (progress) => {
      const percent = (progress.loaded / progress.total) * 100
      console.log(`Upload ${percent}% complete`)
    }
  })

Image Transformations

Supabase supports on-the-fly image transformations:

const { data } = supabase.storage
  .from('uploads')
  .getPublicUrl('image.jpg', {
    transform: {
      width: 500,
      height: 500,
      resize: 'cover',
      quality: 80
    }
  })

Optimized Delivery

Supabase Storage uses Cloudflare CDN for fast, global file delivery.

Environment Variables

Add these to your .env.local:

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

Last Updated on Jun 22, 2026

On this page