Zero-Code AI App BuilderZero-Code AI App Builder
Vibe Coding

Admin and roles

Give some users special powers

Most real apps have two kinds of users: the people who use the app, and the people who run it. In this lesson, you'll learn how roles work, how to build admin-only pages, and how to keep them safe.

What are roles?

Think of a shop. Customers stay at the front. Only staff can go in the back room to unpack boxes, change price tags, and check the order book. A role is the label that says who is staff and who is a customer.

  • A role is a word stored with each user, like user or admin
  • An admin is a user who can manage the app's content
  • An admin dashboard is the private set of pages where admins do that work

For example, a recipe app might let admins approve new recipes. A booking page might let admins see every booking. An online shop might let admins add products and view orders.

Where the role is stored

A common pattern is a profiles table with one row per user and a role column. New users get user by default.

Example profiles table
profiles
  id      -- the same id as the logged-in user
  name    -- display name
  role    -- 'user' or 'admin' (default 'user')

To make yourself an admin, open the table in your database dashboard (for example, Supabase's Table Editor) and change your own role to admin.

Users must never be able to change their own role. If your policy lets users update "their own profile row", ask the AI to make sure the role column is excluded. Otherwise anyone can promote themselves to admin.

Never trust the frontend

The frontend is the part of the app that runs in the user's browser. The user controls their browser, so they can change anything in it. Hiding the "Admin" link is like hiding the back-room key under the doormat.

Real protection needs three locks:

Hide the link
nice, not secure
→
Server check
every admin page and API route checks the role
→
Database rule
Row Level Security checks the role
Three checks, so a non-admin is stopped even if one fails.

A server-side check means the code that runs on the server looks up the user's role before it does anything. The browser can't skip it.

If a non-admin can open /admin by typing the address, your dashboard is not protected. The server and the database must both check the role every time.

Building admin-only pages

Here is a reusable prompt. Replace the parts in brackets with what your app manages:

Prompt
Build an admin dashboard at /admin for my [type of app].

Access:
- Only users whose profiles.role is 'admin' can open any /admin page.
- Check the role on the server for every admin page and every admin API route.
- Add Row Level Security so only admins can insert, update, or delete [items].
- Non-admins get redirected to the home page.
- Show an "Admin" link in the header only for admins.

Pages:
- /admin/[items]: a table of all [items] with Edit and Delete buttons
  and an "Add new" button.
- A form to add and edit an [item] with these fields: [fields].
- Ask "Are you sure?" before deleting.
- /admin/[other data, e.g. orders or bookings]: a read-only list, newest first.

Show me the plan first. Do not edit files yet.

Let's break this down:

  • The "Access" part comes first, because security is the most important rule
  • "every admin API route" matters. The Save and Delete buttons call server routes, and those need the check too.
  • The "Are you sure?" step stops one-click accidents

Managing content

Once admins can add, edit, and delete things, a few habits keep your data healthy:

  • Hide instead of delete: mark old items as inactive, so old orders or bookings still make sense
  • Validate input: prices can't be negative, required fields can't be empty
  • Show who changed what: an "updated at" column helps when something looks wrong

File uploads

Admins often need to upload files, like product photos or recipe images. Apps store these in file storage, a bit like a shared photo folder for your app. In Supabase Storage, each folder is called a bucket.

Prompt
Add image upload to the admin form.
- Use a storage bucket called [bucket-name].
- Anyone can view images, but only admins can upload, replace, or delete them.
- Accept only JPG, PNG, or WebP files under 5 MB.
- Save the image URL in the [image_url] column.
- Give me any SQL or storage policies I need to run, and explain them.

Run any SQL it gives you in your database's SQL editor. Then upload a test image and check it shows up on the public page.

Testing your admin area

  1. As an admin, add an item, edit it, then delete (or hide) it
  2. Check that the public pages update each time
  3. Log in as a normal user and type /admin in the address bar. You should be sent away.
  4. As a normal user, try to upload a file. It should fail.
Ask the AI to check its own work: "Review the admin pages, API routes, and database policies. Is there any way a non-admin could add, edit, or delete data?"

Common mistakes

Checking the role only in the browser

text
Wrong: "If the user is not an admin, hide the dashboard."
Right: "Check the admin role on the server for every admin page and API route, and in the database rules."
  • Using a secret database key (like Supabase's service_role key) in the browser so uploads "just work"
  • Making a storage bucket writable by everyone
  • Letting users edit their own role column

Practice

Try these exercises to lock in what you just learned.

Quiz
Not started
The Admin link is hidden for normal users. A normal user types /admin into the address bar and the dashboard opens. What's missing?
Quiz
Not started
Your database rule lets users update every column of their own profile row, including role. What is the risk?
Quiz
Not started
Who should be allowed to upload images to the bucket that holds your app's public photos?

What's next?

You can now run your app without editing the database by hand. Next, you'll learn how to add AI features, like an assistant that answers questions using your app's own data.