Skip to content
  • Integrations
  • Third-party tools

Create a to-do app with Kinde and Supabase

User authentication and secure data access are critical components of modern web applications. Kinde simplifies the process by handling user authentication, managing session tokens, and offering robust user management features.

When combined with Supabase’s powerful database management and PostgreSQL’s Row-Level Security (RLS) policies, you can create a secure, scalable application that ensures user-specific data access.

In this guide, we will walk through building a personalized and secure to-do application. We’ll use Next.js as the application framework.

Step 1: Create to-do table in Supabase

Link to this section
  1. Sign in to your Supabase dashboard and go to SQL Editor.

  2. Select the plus “+” icon, and then Create a new snippet.

    Create Snippet in Supabase

  3. Paste the following SQL code into the command window and select Run:

    -- Create the table
    CREATE TABLE todos (
    id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    task TEXT NOT NULL,
    user_id TEXT NOT NULL,
    completed_state BOOLEAN DEFAULT FALSE
    );
    -- Insert some sample data into the table
    INSERT INTO todos (task, user_id, completed_state)
    VALUES
    ('Finish writing blog post', 'kp_123', FALSE),
    ('Buy groceries', 'kp_456', TRUE),
    ('Work out at the gym', 'kp_789', FALSE),
    ('Read 10 pages of a book', 'kp_101', TRUE);
    -- Enable row-level security
    ALTER TABLE todos ENABLE ROW LEVEL SECURITY;

    This command creates a todos table with the following columns:

    • task: with a type of text.
    • user_id: with a type of text.
    • completed_state: with a type of boolean. We use boolean because the completed state of each item is either true or false.

    It also inserts four sample todo items. We will need this for later.

  4. Create another new snippet and run the following SQL statement to enable the row-level policy.

    create policy "users can read only their todos" on public.todos
    for select to public
    using (get_user_id() = user_id);

Your database policy is now set up to ensure that only the authenticated user’s to-do items are displayed. In the next step, you’ll update your table rows to include user IDs.

Step 2: Build a simple to-do app

Link to this section
  1. Open the /components/hero.tsx file with your favorite code editor.

  2. Add the following code to hero.tsx which is a basic to-do list table:

    import { createClient } from "@/lib/supabase/server"
    export async function Hero() {
    const supabase = await createClient()
    const { data: todos } = await supabase.from("todos").select()
    return (
    <div className="flex flex-col gap-16 items-center">
    <table style={{ width: "100%", borderCollapse: "collapse" }}>
    <thead>
    <tr>
    <th
    style={{
    border: "1px solid #ddd",
    padding: "8px",
    textAlign: "left",
    backgroundColor: "#f2f2f2",
    }}
    >
    ID
    </th>
    <th
    style={{
    border: "1px solid #ddd",
    padding: "8px",
    textAlign: "left",
    backgroundColor: "#f2f2f2",
    }}
    >
    Task
    </th>
    <th
    style={{
    border: "1px solid #ddd",
    padding: "8px",
    textAlign: "left",
    backgroundColor: "#f2f2f2",
    }}
    >
    Is Complete
    </th>
    </tr>
    </thead>
    <tbody>
    {todos?.map((row) => (
    <tr key={row.id}>
    <td style={{ border: "1px solid #ddd", padding: "8px" }}>
    {row.id}
    </td>
    <td style={{ border: "1px solid #ddd", padding: "8px" }}>
    {row.task}
    </td>
    <td style={{ border: "1px solid #ddd", padding: "8px" }}>
    {String(row.completed_state)}
    </td>
    </tr>
    ))}
    </tbody>
    </table>
    </div>
    )
    }
  3. Run the project with the following terminal command:

    Terminal window
    npm run dev
  4. Go to http://localhost:3000, sign in/sign up, and preview the page. You won’t see any to-do items because we haven’t set any user ID yet.

    Empty to do list

Link to this section
  1. Sign in to your Kinde dashboard and select Users to view the user list.

  2. Locate the user registered with your Supabase to-do app (e.g: Tamal Chowdhury) and select their name to view their profile.

    List of Kinde users

  3. Copy the unique Kinde profile ID displayed on their profile page.

    Kinde profile ID

  4. Go to Table Editor in your Supabase project, and open the todos table.

  5. Locate the rows corresponding to your to-do items and update the user_id column with the Kinde ID you copied. Save your changes.

    to-do items

  6. In the Kinde project, log in with the same user you signed up with. Verify that the to-do items linked to this user are now visible on the to-do page of your app.

    to-do list finished

This step links the Kinde user ID to specific to-do items, enabling the app to filter and display tasks based on the authenticated users.

Excellent work!

Link to this section

You’ve successfully built a secure and personalized to-do app using Kinde for authentication and Supabase for database management.

With this foundation, your app is now equipped to manage user authentication and personalized data securely. You can extend this project further by adding features like task creation, deletion, updates, or even real-time collaboration.