MCPcopy Index your code
hub / github.com/StructuredLabs/supawald

github.com/StructuredLabs/supawald @v1.0.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.0.2 ↗ · + Follow
69 symbols 143 edges 27 files 0 documented · 0%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Supawald Banner

<em>A headless CMS for Supabase Storage. Built with Next.js 14, TypeScript, and Tailwind CSS.</em>







<a href="https://github.com/StructuredLabs/supawald/raw/v1.0.2/LICENSE">
    <img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="Apache 2.0 License">
</a>
<a href="https://nodejs.org/">
    <img src="https://img.shields.io/badge/node-18%2B-blue.svg" alt="Node.js Version">
</a>
<a href="https://nextjs.org/">
    <img src="https://img.shields.io/badge/Next.js-14-black" alt="Next.js">
</a>
<a href="https://supabase.com/">
    <img src="https://img.shields.io/badge/Supabase-Platform-green" alt="Supabase">
</a>

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.

Supawald Screenshot

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
Supawald Screenshot Supawald Screenshot

Use Cases

  1. Blog Asset Management
  2. Store and manage images, documents, and other media
  3. Organize content by date, category, or project
  4. Quick access to frequently used assets

  5. Document Management

  6. Store and organize PDFs, spreadsheets, and other documents
  7. Version control through Supabase's built-in features
  8. Secure access control via bucket policies

  9. Application Assets

  10. Manage static assets for web applications
  11. Store user uploads and generated content
  12. 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
  1. Set Up Supabase sql -- Create a new bucket in Supabase Storage -- Name it something like 'blog-content' or 'assets' -- Set appropriate privacy settings (public/private)

  2. Configure Environment bash cp .env.example .env.local ```env # 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 ```

  1. Run Development Server bash 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

  1. Create a Publish API Route Create a new API route in your Next.js application at pages/api/publish.ts:

```typescript 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')
 }

} ```

  1. Configure Environment Variables In your Supawald instance: env PUBLISH_URL=https://your-static-site.com/api/publish PUBLISH_TOKEN=your-secure-token

In your static site: env PUBLISH_TOKEN=your-secure-token # Same token as above

  1. Using the Publish Button When you click the publish button in Supawald:
  2. It sends a POST request to your static site's publish API
  3. Your static site regenerates the specified pages
  4. The new content becomes available on your static site

Supawald Screenshot

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: 1. The image is updated in Supabase Storage 2. The publish API is called 3. Your static pages are regenerated with the new image 4. 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

  1. Supabase Storage
  2. Use private buckets for sensitive content
  3. Implement RLS policies for bucket access
  4. Set up CORS rules for your domain
  5. Use signed URLs for temporary access

  6. Authentication

  7. Use strong passwords for admin access
  8. Implement rate limiting
  9. Set up proper CORS headers
  10. Use HTTPS in production

  11. Environment Variables

  12. Never commit .env.local
  13. Rotate credentials regularly
  14. Use different keys for development/production
  15. Consider using a secrets manager
  16. Keep your PUBLISH_TOKEN secure and only share with trusted services

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

<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>

Extension points exported contracts — how you extend this code

FileObject (Interface)
(no doc)
template/app/page.tsx
Frontmatter (Interface)
(no doc)
template/app/types/markdown.ts
ProcessedContent (Interface)
(no doc)
template/app/types/markdown.ts
MarkdownEditorProps (Interface)
(no doc)
template/app/components/MarkdownEditor.tsx
PublishButtonProps (Interface)
(no doc)
template/app/components/PublishButton.tsx

Core symbols most depended-on inside this repo

fetchFiles
called by 8
template/app/page.tsx
fetchFolderContents
called by 6
template/app/page.tsx
handleDelete
called by 3
template/app/page.tsx
handleDeleteFolder
called by 3
template/app/page.tsx
getFileIcon
called by 3
template/app/page.tsx
handleFileClick
called by 2
template/app/components/FileList.tsx
loadImageDirectly
called by 2
template/app/components/ImageModal.tsx
processFrontmatter
called by 2
template/app/utils/markdown.ts

Shape

Function 58
Interface 11

Languages

TypeScript100%

Modules by API surface

template/app/page.tsx20 symbols
template/app/components/ImageModal.tsx6 symbols
template/app/components/FileList.tsx5 symbols
template/app/components/CreateFolderModal.tsx5 symbols
template/app/components/PublishButton.tsx4 symbols
template/app/components/MarkdownEditor.tsx4 symbols
template/app/components/FileViewModal.tsx4 symbols
template/app/utils/markdown.ts3 symbols
template/app/lib/publish.ts3 symbols
template/app/edit/layout.tsx3 symbols
template/app/edit/[...filename]/page.tsx3 symbols
template/app/types/markdown.ts2 symbols

For agents

$ claude mcp add supawald \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact