Back to articles

Building a Fullstack CRUD App with SvelteKit and Supabase

AuthorMajd Muhtaseb05/24/202515 minutes
Building a Fullstack CRUD App with SvelteKit and Supabase

Introduction

This article guides you through building a simple yet functional CRUD (Create, Read, Update, Delete) application using SvelteKit and Supabase. SvelteKit provides a fast and efficient development experience for building web applications, while Supabase offers a complete backend-as-a-service solution with a PostgreSQL database, authentication, and real-time capabilities.

Prerequisites

  • Node.js and npm installed
  • A Supabase account and project created

Setting Up Your SvelteKit Project

  1. Create a new SvelteKit project:

    npm create svelte@latest my-sveltekit-app
    cd my-sveltekit-app
    npm install
    
  2. Install the Supabase JavaScript client:

    npm install @supabase/supabase-js
    

Connecting to Supabase

  1. Retrieve your Supabase URL and anon key from your Supabase project dashboard.

  2. Create a .env file in your SvelteKit project root:

    VITE_SUPABASE_URL="YOUR_SUPABASE_URL"
    VITE_SUPABASE_ANON_KEY="YOUR_SUPABASE_ANON_KEY"
    
  3. Initialize the Supabase client in src/lib/supabaseClient.js:

    import { createClient } from '@supabase/supabase-js';
    import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
    
    export const supabase = createClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY);
    

Creating the Data Model (Tasks)

Let's assume we're building a task management application. Create a table named tasks in your Supabase database with the following columns:

  • id (UUID, primary key)
  • task (text)
  • completed (boolean, default: false)

Implementing CRUD Operations

1. Reading Tasks (GET)

In src/routes/+page.svelte:

<script>
  import { supabase } from '$lib/supabaseClient';
  import { onMount } from 'svelte';

  let tasks = [];

  onMount(async () => {
    const { data, error } = await supabase.from('tasks').select('*').order('id');

    if (data) {
      tasks = data;
    }

    if (error) {
      console.error('Error fetching tasks:', error);
    }
  });
</script>

<h1>Tasks</h1>

{#each tasks as task (task.id)}
  <div>
    <input type="checkbox" checked={task.completed} />
    {task.task}
  </div>
{/each}

2. Creating Tasks (POST)

Add an input field and button to create new tasks:

<script>
  // ... (previous code)

  let newTask = '';

  async function createTask() {
    const { data, error } = await supabase
      .from('tasks')
      .insert([{ task: newTask }]);

    if (data) {
      tasks = [...tasks, data[0]]; // Add new task to the local array
      newTask = ''; // Clear the input field
    }

    if (error) {
      console.error('Error creating task:', error);
    }
  }
</script>

// ... (previous code)

<input type="text" bind:value={newTask} placeholder="Add new task" />
<button on:click={createTask}>Add Task</button>

3. Updating Tasks (PUT/PATCH)

Modify the task list to include a function for updating the completed status:

<script>
  // ... (previous code)

  async function updateTask(task) {
    const { error } = await supabase
      .from('tasks')
      .update({ completed: !task.completed })
      .eq('id', task.id);

    if (error) {
      console.error('Error updating task:', error);
    }
  }
</script>

{#each tasks as task (task.id)}
  <div>
    <input type="checkbox" checked={task.completed} on:change={() => updateTask(task)} />
    {task.task}
  </div>
{/each}

4. Deleting Tasks (DELETE)

Add a delete button to each task:

<script>
  // ... (previous code)

  async function deleteTask(task) {
    const { error } = await supabase
      .from('tasks')
      .delete()
      .eq('id', task.id);

    if (error) {
      console.error('Error deleting task:', error);
    }
  }
</script>

{#each tasks as task (task.id)}
  <div>
    <input type="checkbox" checked={task.completed} on:change={() => updateTask(task)} />
    {task.task}
    <button on:click={() => deleteTask(task)}>Delete</button>
  </div>
{/each}

Conclusion

This article provides a basic foundation for building a CRUD application using SvelteKit and Supabase. You can expand this application by adding features like authentication, real-time updates, and more complex data models. Remember to handle errors gracefully and optimize your code for performance.