How to Add User Authentication and Roles to Your App on Creatr
- What you need
- A Creatr account
- Token cost
- Light
- Time
- About 45 minutes

Sign-up, login, and password reset feel like table stakes - but they are also where many apps quietly break. Add roles on top, and the surface area for mistakes grows: the wrong user sees a record they should not, an admin panel loads for someone who is not an admin, or a data query returns everyone's rows instead of just the current user's. Getting this right from the start saves you from a painful retrofit later.
This tutorial walks you through adding full authentication and role-based access to an app built on Creatr. No code required - every step is a plain-English prompt you give to Creatr at build time or via a change request.
Before you start
- Have a rough idea of your user types. Even something simple like "customers" and "admins" is enough. You do not need a full permissions matrix - just a clear picture of who uses the app and what each group should be able to do.
- Know which pages or actions are private. Think through which parts of your app should require a login, and which - if any - are public.
- Have a domain or email address ready for verification emails. Creatr uses Gmail integration to send transactional email, including email verification and password reset. You will need an email sender set up before those flows can go live.
If you are still shaping your app, read through all the steps first. The prompts build on each other, so understanding the full picture before you start will make your requests cleaner.
Step 1 - Describe your users and the roles they fall into
Authentication without roles is just a gate. Roles are what determine what each person can do once they are inside. Start by telling Creatr exactly who your users are and what each group needs.
Think in terms of actions, not just labels. "Admin" is a label. "Can create, edit, and delete any record, and can invite other users" is a role definition. The more specific you are here, the more accurately Creatr can wire the access rules.
A prompt that works:
My app has two types of users. The first is "Customer" - they can sign up, log in, view and edit only their own profile, submit orders, and see only their own order history. The second is "Admin" - they can log in, view all customers and all orders, update order status, and invite new admin users. No customer should ever see another customer's data. Admins should have a separate dashboard at /admin that customers cannot access.
If your app has more roles - say, a "Manager" tier between customer and admin, or a "Read-only" role for a reporting user - describe each one in the same format. One paragraph per role, actions spelled out.
Step 2 - Turn on authentication
Once Creatr knows your roles, ask it to wire up the authentication flows. This includes sign-up, login, logout, and password reset. Creatr uses Supabase under the hood for auth, which gives you a battle-tested identity layer without building it yourself.
Add authentication to my app. Users should be able to sign up with an email and password, log in, log out, and reset their password via email. After sign-up, send a verification email before the account is active. New accounts should default to the "Customer" role. Admins will be created manually or via invite - they should not be able to self-register as admins.
A few things this prompt handles:
- Default role on sign-up. Telling Creatr which role new accounts get prevents a situation where a freshly registered user has no role and falls through access checks unexpectedly.
- No self-service admin registration. This is important. If your admin role carries elevated access, you do not want anyone to be able to claim it by picking a value in a sign-up form.
- Email verification before account activation. This prevents throwaway accounts and ensures you have a valid email on file before the user can take any action.
Step 3 - Define the roles in your data model
Authentication proves who someone is. Roles determine what they can do. These are two separate things, and Creatr needs to know about both.
After you have your auth flows in place, prompt Creatr to add a role field to your users table and set it correctly:
Add a "role" field to the users table with two possible values: "customer" and "admin". When a new user signs up, set their role to "customer" automatically. Admins should only be created by existing admins. Make sure the role field cannot be changed by the user themselves - only an admin can update another user's role.
This last point matters. If users can edit their own role through a profile update form, your entire access model collapses. Creatr will lock down the role field so it is only writable through admin-level operations.
Step 4 - Gate pages and actions by role
With roles defined, you can now tell Creatr which parts of the app each role can reach and what they can do once they get there.
For page-level access:
The /admin route and all routes under /admin should only be accessible to users with the "admin" role. If a customer tries to visit /admin, redirect them to their dashboard at /dashboard. If an unauthenticated user tries to visit any protected route, redirect them to /login.
For action-level access:
The "Update order status" button should only appear for admin users. Customers should not see it at all - not greyed out, just absent. The "Delete customer" action in the admin panel should only be available to admins, and should require a confirmation step before executing.
Hiding UI elements is not the same as securing them - but for the reader's experience, removing them from the UI reduces confusion. Creatr handles both: it removes the UI element for unauthorized users and also blocks the underlying action at the server level, so there is no way to trigger it by manipulating the interface.
Step 5 - Data-level access so users only see their own records
Page and action gating stops the wrong person from reaching a feature. Data-level access stops the wrong person from seeing a record even if they somehow get there.
This is one of the most common failure points in apps built quickly. A customer visits their order history page - and because the query was written as "get all orders" instead of "get orders where user_id = current user", they see every order in the system. This kind of leak is quiet. No error is thrown. The app works. The data is just wrong.
Creatr uses Supabase's row-level security (RLS) for this. In plain terms: row-level security means the database itself enforces rules about which rows each user can read, write, or delete. Even if a query does not filter by user, the database refuses to return rows the current user is not allowed to see.
Enable row-level security on all tables that contain user data. Customers should only be able to read and write rows where the user_id matches their own account. Admins should be able to read and write all rows. Apply this to the orders table, the profiles table, and any other table that stores per-user data.
When in doubt, default to stricter access and open it up later. It is much easier to give a user access they did not have than to explain to them why they saw data that was not theirs.
Step 6 - Verification emails
Email verification does two things: it confirms the address is real, and it creates a moment of friction that discourages low-effort abuse of your sign-up flow.
Creatr connects to Gmail to send transactional emails. Tell it what the verification flow should look like:
After a user signs up, send them a verification email with a confirmation link. The account should not be usable until the email is verified. If the user has not verified within 24 hours, allow them to request a new verification email from the login page. The email should come from our company address and include our logo and a clear call to action button.
You can also ask Creatr to handle the password reset email in the same pass:
When a user requests a password reset, send them a time-limited reset link via email. The link should expire after one hour. If the link has expired, show a clear message and let them request a new one.
These are standard flows, but spelling them out ensures nothing is left at a default that does not match your expectations - particularly around expiry times and sender identity.
Step 7 - Test each role from a clean account
Before shipping, verify that every role works exactly as described - not by checking the code, but by signing in as each type of user and walking through the app.
Prompt Creatr to create test accounts:
Create two test accounts: one with the "customer" role (test-customer@example.com) and one with the "admin" role (test-admin@example.com). Use placeholder passwords I can change on first login. Do not delete these accounts after testing - I will use them during QA.
Then walk through the following manually for each account:
- Sign up (or log in) and confirm the correct landing page appears.
- Try to visit a route that should be blocked for that role. Confirm the redirect happens.
- For the customer account: check that you can only see your own records. If there are two customer accounts, log in as each and confirm neither can see the other's data.
- For the admin account: confirm you can see all records and use all admin actions.
- Request a password reset and follow the email link. Confirm it works and expires correctly.
This is not a substitute for automated testing - but it is the fastest way to catch a misconfigured rule before a real user finds it.
Step 8 - Ship and iterate
Once you have tested each role and the access rules are working as expected, ship. Authentication and roles do not need to be perfect on day one - they need to be correct on day one.
After launch, you will likely find edge cases: a new feature that needs its own access rule, a role that needs a permission added, a page that was missed in the initial gating pass. Use Creatr change requests to tighten these as they come up:
The new "Reports" page at /reports should only be visible to admins. Customers who try to visit it should see a "You don't have access to this page" message instead of a redirect.
Keep change requests scoped. One rule change per request is easier for Creatr to apply cleanly and easier for you to verify afterward.
Recap
Authentication is not just sign-up and login - it is the full system of who can be in your app, what they can do there, and which data they can see. Here is what this tutorial covered:
- Describe your user types and roles with specific actions, not just labels
- Turn on sign-up, login, and password reset via Creatr with Supabase handling the identity layer
- Lock down the role field so users cannot elevate their own permissions
- Gate pages and actions by role - at the UI level and at the server level
- Use row-level security so the database itself enforces per-user data access, not just your queries
- Send verification and reset emails via the Gmail integration
- Test every role from a clean account before shipping
- Iterate with scoped change requests as new access rules come up
Data-level access is where vibe-coded apps most often leak information. Getting it right means describing it explicitly - not assuming Creatr or any system will infer stricter rules than you asked for. When in doubt, ask for less access and open it up deliberately.
Related tutorials: Build an admin dashboard, Build an internal tool for your team.

Co-founder and CTO of Creatr, building DeepBuild: the system that ships production web apps in 24 hours. Prince's open-source WhatsApp userbot, BotsApp, earned 5.5k GitHub stars and 1.3k forks during his college years. He later ran a solo freelance engineering practice to $100K in revenue before co-founding Creatr.