Every screen in a client portal app has to ask whose data this is.
A client portal app does one thing that is harder than it looks. It shows each customer their own files, their own invoices and their own status, and nothing belonging to anyone else. The screens are simple. The rule underneath them is where portals go wrong, and it decides whether the app is safe to hand to a client at all. If the same app also has to take questions and replies, the overlap with customer service apps is large.
This page covers what clients actually open a portal for, where per client scoping has to be enforced, what the App Store expects from an app that creates accounts, and where a portal stops being a portal and quietly becomes your operations system.
See what scoping actually blocksThe short version
The screens are the easy part, the scoping rule is the product.
A portal is a list, a detail page and a download button. Any tool can draw those. What makes it a portal is that the same code, running for a different signed-in person, returns a different set of records. Whether you call it a client portal app or a customer portal app, that is the whole shape of it.
Almost every real failure in this category is the same failure: the rule lives in the app instead of in the data. It looks identical on screen until somebody changes an id in a request and gets back a document that was never theirs.
A filter in the app is not a rule
There are two places the rule can live. In the query your app sends, or in the database as a policy the database applies to every request that account makes. A secure client portal is defined by which of those two you chose. The first one produces a list that happens to look right; the second one produces a list that cannot be wrong.
Supabase writes the mechanics down plainly, and the wording is worth reading before you design anything. A table in an exposed schema without row level security is readable and writable by any role that holds a grant on it. Once row level security is switched on, nothing is accessible through the API with a publishable key until you write policies. A policy then compares a column on the row, usually an owner id, against the id of the user making the request, which Supabase exposes as auth.uid(). One detail catches people out: adding policies does not take back grants that already exist, so a table protected only by policies can still leave an anonymous role an insert path.
The test for your own portal is not whether the list looks right. It is whether you can sign in as one client, take the request the app just made, swap the record id for one belonging to another client, and get nothing back. Run that as a written test, not as a one off check. The exact shape of sessions, tokens and policies is a subject of its own, and the login and per-client data rules go further into it than this page will.
Supabase docs, row level security
Try it
What the signed-in client can reach
The list on screen always looks right. The question is what comes back when the request skips the screen.
On screen: 2 of 5 records.
5 records this account can fetch
3 records belonging to other clients are still reachable. The screen hides them by filtering. The account can ask for them by id and get them.
What clients actually open a portal for
Ask ten customers what they want from a portal and you get four answers. Where is my invoice, where is my document, what is the status, and who do I talk to. The fifth answer is usually irritation at having to ask a person for any of them.
That shapes the data model more than any diagram. You need documents with a client owner and a date they become visible, invoices with a state the client can act on, a status field written by your team rather than typed by the client, and messages attached to one of those records rather than floating free in a general inbox. Every one of those objects carries the owner column the policy will check.
Invoices are the part people underestimate. A portal that displays a number is a statement of account. A portal that takes a payment is a payment system, with its own rules about receipts, refunds, failed cards and tax. If billing is the main thing you want in front of clients, an invoice app for small business is a smaller and more honest project than a full portal, and it can grow into one later.
Accounts, invites and the day someone leaves
Client accounts are not the same as user accounts, and confusing the two is expensive. The person signing in works for the client. People change jobs, get promoted and get let go. So the login belongs to a person, the records belong to the company, and the link between them is a membership with a start date and an end date. Model that on day one, because adding it later means revisiting every query in the app.
Invites matter more than sign up. Nobody searches the App Store for your portal, so a client portal mobile app lives or dies on the invite. Somebody on your side enters an email address, the client gets a link, the link works once and then expires. That is a small piece of work with an outsized effect on whether anyone ever opens the thing.
Two App Store rules apply before you ship. If the app supports account creation, Apple requires you to offer account deletion inside the app, which for a portal means deciding in advance what deletion means when your company still has to keep the invoices. And guideline 4.2 asks for features and interface that go beyond a repackaged website, so a login screen wrapped around your existing web portal is the classic rejection in this category. Plan for a real app or plan for a review cycle.
Where the portal stops and your operations start
A portal is a window onto work that happens somewhere else. The trap is that the window slowly becomes the building. A client asks for a job status, then a schedule, then a way to request a visit, then approvals, and now the portal is your whole field system with a customer login bolted to the side of it.
The line worth drawing is that the portal shows records and accepts a short list of client actions. It is not where work gets created or assigned. When a business needs both sides properly, the internal side usually deserves its own app: a property management app for landlords and the tenant portal that goes with it are two apps over one database, not one app with a permission flag.
The other reason to hold that line is disputes. A portal is the thing a client points at when the two of you disagree about what was agreed. Every visible record wants a timestamp and an author, and an edit wants to be visible as an edit rather than a silent overwrite. That is a few extra columns at the start and a rewrite in the middle of an argument if you leave it out.
What each way of giving clients access actually gives them
| Option | Each client sees only their own records | Push when something changes | Your own fields and workflow | Stands on its own in the App Store |
|---|---|---|---|---|
| Email attachments and a shared folder | by hand | No | Yes | not an app |
| A web portal in a browser | Yes | limited | Yes | not an app |
| Portal module in industry software | Yes | Yes | its fields | Yes |
| A webview wrapper of your web portal | Yes | No | Yes | No |
| A portal app you build | if you ask for it | Yes | Yes | Yes |
Building a portal around your own clients
Portal features inside industry software are shaped by the businesses that software was written for. If your clients need three fields it does not have, or your process has a step that is not in the menu, you either change how you work or pay for a customisation. For a firm with thirty clients, both of those cost more than they look like they should.
Newly is an AI app builder. You describe the app in plain English and it writes a real React Native and Expo project you own, runs it on a cloud simulator while it builds, and uploads iOS builds to TestFlight. Plans start at $25 a month and there is no free plan. On the question that matters most here, the documentation is clear and the answer is no: per client isolation is not automatic. A new app keeps its data on the phone, with no accounts, no server and no sign in at all. A backend, with a sign-in service and a Postgres database, is added only once you ask for accounts or for data shared between people, and the documented example prompt spells the privacy requirement out in the sentence itself. So write the rule into your first message, then test it rather than assume it.
Two other things to check before you commit. Password reset and verification emails do not send themselves: the backend needs an email provider connected, which matters more for a portal than for most apps, because clients will forget passwords and will not ask you politely. And Android goes to Google Play internal testing from the Deploy tab, or out as a standalone APK, so a client base split across both phones is covered.
Questions people ask about client portal apps
It is an app where each customer signs in and sees only the records that belong to them: their documents, their invoices, the status of their work and a way to ask a question. The screens are ordinary lists and detail pages. What makes it a portal is that the same code returns different records for different people, and that the rule is enforced rather than drawn.
Describe the portal your clients would actually sign in to
Write down who each record belongs to, what a client is allowed to do with it, and who gets to invite the next person. Then build the portal around those rules.
Start building