Check every Supabase upload for NSFW content

View Markdown

In this guide, you will learn:

  • How to upload files to Supabase Storage with signed URLs
  • How to send POST requests to the ittybit Task API for NSFW detection
  • How to configure webhooks to Supabase when NSFW content is detected
  • How to automatically flag NSFW content in your database
  • How to set up optional actions like email alerts, file deletion, or user suspension

1. Upload to Supabase Storage

Ensure you have already created a Storage bucket in your Supabase project. If you haven't, you can follow the Supabase guide on creating buckets.

First, upload a file to your Storage bucket. This will generate a signed URL needed for the next step.

2. Send a POST request to ittybit Task API for NSFW detection (use SDK)

Prerequisite: This section uses the ittybit TypeScript SDK. Make sure it's installed in your project or build faster in your favorite language from the ittybit list of SDKs.

npm install @ittybit/sdk

Next, use the ittybit SDK to create an NSFW detection task with the public URL from Supabase Storage.

import { IttybitClient } from "@ittybit/sdk";

const ittybit = new IttybitClient({ 
  apiKey: process.env.ITTYBIT_API_KEY!
});

const task = await ittybit.tasks.create({
  kind: 'nsfw',
  url: imageUrl,
  description: 'NSFW content detection analysis',
  webhook_url: "https://<your-domain-or-ngrok>.ngrok-free.app/nsfw-webhook"
});

console.log('Task created:', task.id);
console.log('Task status:', task.status);

3. Configure webhooks to Supabase when NSFW content is detected

To capture NSFW detection results from ittybit and update your Supabase database, you need a webhook endpoint that listens for POST requests from ittybit when tasks complete.

A sample app with a /nsfw-webhook route:

app.post("/nsfw-webhook", async (req, res) => {
  const { id, kind, status, results } = req.body || {};

  if (kind !== 'nsfw' || status !== 'completed') {
    return res.status(200).send("Not a completed NSFW task");
  }

  const { error } = await supabase
    .from("uploads")
    .update({ 
      nsfw_detected: results?.is_nsfw || false,
      nsfw_confidence: results?.confidence || 0,
      processed_at: new Date().toISOString()
    })
    .eq("task_id", id);

  if (error) {
    console.error(error);
    return res.status(500).send("Update failed");
  }

  res.status(200).send("NSFW status updated in DB");
});

app.listen(3000, () => {
  console.log("Listening on http://localhost:3000/nsfw-webhook");
});

This function checks if it's a completed NSFW task, then updates the NSFW detection results in your uploads table in Supabase.

4. Automatically flag NSFW content in your database

When ittybit detects NSFW content, it sends the results to your webhook endpoint. Your function then updates the database with the NSFW status:

// In your webhook function
await supabase
  .from("uploads")
  .update({ 
    nsfw_detected: results?.is_nsfw || false,
    nsfw_confidence: results?.confidence || 0,
    processed_at: new Date().toISOString()
  })
  .eq("task_id", id);

This automatically flags uploads as NSFW in your database when detected. For the full webhook setup guide, see Auto-generate titles, descriptions & tags for Supabase uploads.

5. (Optional) Email alerts, file deletion, or user suspension

You can extend your webhook function to take additional actions when NSFW content is detected:

if (results?.is_nsfw) {
  // Send email alert
  await sendEmailAlert(results);
  
  // Delete file from storage
  await deleteFileFromStorage(filePath);
  
  // Suspend user account
  await suspendUserAccount(userId);
}

Choose which actions fit your moderation needs.

When ittybit finishes NSFW detection, it sends the results to your webhook endpoint with the detection status and confidence scores. Your function then automatically updates the NSFW flags in your Supabase database.

You now have a working pipeline where files are uploaded to Supabase Storage, NSFW detection tasks are created in ittybit, and when processing completes, ittybit delivers the NSFW results to your webhook endpoint. The webhook then updates the NSFW status directly in your Supabase database, creating a fully automated moderation flow without manual polling.

On this page