Supawald
Supawald is a headless CMS for Supabase Storage. An out-of-the-box interface for managing files, images, and content in your Supabase Storage buckets with real-time updates and static site generation support. Manage files, set permissions, and connect directly to your Supabase project.
Install / Use
/learn @StructuredLabs/SupawaldREADME
🚀 Quick Start with Template
-
Create a new project
npx create-supawald my-app cd my-app -
Set up your Supabase project
- Create a new bucket in Supabase Storage
- Get your project URL and anon key from Settings -> API
- Copy
.env.exampleto.env.localand fill in your credentials:NEXT_PUBLIC_SUPABASE_URL=your-project-url NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key NEXT_PUBLIC_BUCKET_NAME=your-bucket-name AUTH_USERNAME=admin AUTH_PASSWORD=your-secure-password
-
Start the development server
npm install npm run dev -
Visit http://localhost:3000 and log in with your credentials
Note: The template includes a complete Next.js application with file management, authentication, and static site generation support.
Supawald
A headless CMS for Supabase Storage. Built with Next.js 14, TypeScript, and Tailwind CSS. Provides a clean interface for managing files in Supabase Storage buckets with real-time updates and static site generation support.

What is Supawald?
Supawald is a file management system that turns Supabase Storage into a full-featured CMS. It's designed for developers who need a simple way to manage assets for their Next.js applications, blogs, or any project using Supabase Storage.
Key Features
-
File Management
- Drag & drop file uploads
- Folder navigation
- File deletion
- In-place file editing
- Real-time updates via Supabase subscriptions
-
Developer Experience
- TypeScript for type safety
- Next.js 14 App Router
- Tailwind CSS for styling
- Basic auth protection
- Publish API for static site generation
-
Storage Features
- Public/private bucket support
- File type detection
- File size tracking
- Last modified timestamps
Use Cases
-
Blog Asset Management
- Store and manage images, documents, and other media
- Organize content by date, category, or project
- Quick access to frequently used assets
-
Document Management
- Store and organize PDFs, spreadsheets, and other documents
- Version control through Supabase's built-in features
- Secure access control via bucket policies
-
Application Assets
- Manage static assets for web applications
- Store user uploads and generated content
- Handle media files for user profiles or content
Technical Requirements
- Node.js 18+
- Supabase account (free tier works)
- npm or yarn
▶️ Quick Start
Use the CLI
npx create-supawald my-app
cd my-app
npm install
npm run dev
Or clone manually
git clone https://github.com/yourusername/supawald.git
cd supawald/template
npm install
npm run dev
-
Set Up Supabase
-- Create a new bucket in Supabase Storage -- Name it something like 'blog-content' or 'assets' -- Set appropriate privacy settings (public/private) -
Configure Environment
cp .env.example .env.local# Supabase NEXT_PUBLIC_SUPABASE_URL=your-project-url NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key NEXT_PUBLIC_BUCKET_NAME=your-bucket-name # Auth (for admin access) AUTH_USERNAME=admin AUTH_PASSWORD=your-secure-password # Publish API (for static site generation) PUBLISH_URL=https://your-site.com/api/publish PUBLISH_TOKEN=your-secure-token -
Run Development Server
npm run dev
Static Site Generation Integration
Supawald includes a publish API that triggers regeneration of static pages that depend on Supabase Storage data. This is useful for:
- Blog posts that display uploaded images
- Product pages with product images
- Any static page that needs to reflect changes in your storage bucket
Setting Up Your Static Site
-
Create a Publish API Route Create a new API route in your Next.js application at
pages/api/publish.ts:import { NextApiRequest, NextApiResponse } from 'next' export default async function handler( req: NextApiRequest, res: NextApiResponse ) { // Check for secret to confirm this is a valid request if (req.headers.authorization !== `Bearer ${process.env.PUBLISH_TOKEN}`) { return res.status(401).json({ message: 'Invalid token' }) } try { // Revalidate your static pages await res.revalidate('/') // Revalidate homepage await res.revalidate('/blog') // Revalidate blog pages await res.revalidate('/products') // Revalidate product pages return res.json({ revalidated: true }) } catch (err) { // If there was an error, Next.js will continue // to show the last successfully generated page return res.status(500).send('Error revalidating') } } -
Configure Environment Variables In your Supawald instance:
PUBLISH_URL=https://your-static-site.com/api/publish PUBLISH_TOKEN=your-secure-tokenIn your static site:
PUBLISH_TOKEN=your-secure-token # Same token as above -
Using the Publish Button When you click the publish button in Supawald:
- It sends a POST request to your static site's publish API
- Your static site regenerates the specified pages
- The new content becomes available on your static site

Example Usage
// In your static site's page component
export async function getStaticProps() {
// Fetch data from Supabase Storage
const { data: images } = await supabase.storage
.from('your-bucket')
.list('blog-images')
return {
props: {
images,
// ... other props
},
// Revalidate every hour
revalidate: 3600
}
}
When you update an image in Supawald and click publish:
- The image is updated in Supabase Storage
- The publish API is called
- Your static pages are regenerated with the new image
- The changes are live on your static site
API Integration
File Operations
// Example: Upload a file
const { data, error } = await supabase.storage
.from('your-bucket')
.upload('path/to/file.jpg', file)
// Example: Get file URL
const { data: { publicUrl } } = supabase.storage
.from('your-bucket')
.getPublicUrl('path/to/file.jpg')
Static Site Generation
// Trigger static page regeneration
await fetch('/api/publish', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PUBLISH_TOKEN}`
}
})
🔒 Security Best Practices
-
Supabase Storage
- Use private buckets for sensitive content
- Implement RLS policies for bucket access
- Set up CORS rules for your domain
- Use signed URLs for temporary access
-
Authentication
- Use strong passwords for admin access
- Implement rate limiting
- Set up proper CORS headers
- Use HTTPS in production
-
Environment Variables
- Never commit
.env.local - Rotate credentials regularly
- Use different keys for development/production
- Consider using a secrets manager
- Keep your
PUBLISH_TOKENsecure and only share with trusted services
- Never commit
Development
# Install dependencies
npm install
# Run development server
npm run dev
# Build for production
npm run build
# Start production server
npm start
🤝 Contributing
See CONTRIBUTING.md for development guidelines.
📄 License
Apache 2.0 - See LICENSE for details.
🎉 Join the Community
- GitHub Issues: Found a bug? Let us know here.
- Community Forum: Reach out here
- Discussions: Share your ideas and ask questions in our discussion forum.
📢 Stay Connected
<p> <a href="https://www.linkedin.com/company/structuredlabs/" target="_blank"> <img src="https://img.shields.io/badge/Follow%20Us-LinkedIn-blue?style=for-the-badge&logo=linkedin" alt="Follow us on LinkedIn"> </a> <a href="https://x.com/StructuredLabs" target="_blank"> <img src="https://img.shields.io/badge/Follow%20Us-Twitter-1DA1F2?style=for-the-badge&logo=twitter" alt="Follow us on Twitter"> </a> </p>Related Skills
openhue
339.3kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
339.3kElevenLabs text-to-speech with mac-style say UX.
weather
339.3kGet current weather and forecasts via wttr.in or Open-Meteo
FastGPT
27.6kFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.
