shouldivibecodeit

Should I vibe codeSoftr?

No-code portals and internal apps on Airtable/Google Sheets and databases

A client portal is multi-tenant software. If the filter is a URL parameter, so is everyone else's data.

?

Their verdict, the Basic price and the build-time estimate come from their entry, MIT-licensed. Checked 2026-08-04.

Can you build it?asked by canivibecodeit.com ↗KINDAweekend project · multi-day
?

Our verdict, the regret score and everything below it. Editorial and unsponsored — nobody can pay to be moved.

Should you ship it?asked by usYOUR FUNERALit’ll work. then it’ll get you.

The honest answer

why the verdict is what it is

A client portal is a multi-tenant application wearing a table. Every screen is the same query with a different WHERE clause, and the entire product is the guarantee that the clause is correct and cannot be influenced by the person reading it — which is exactly the guarantee a generated app does not make. The shape that comes out of an agent is astonishingly consistent: an Airtable personal access token with read access to the whole base, held by something that serves the browser, and a filter expressed as a parameter the client can see. Sometimes the filter runs on the server and can be edited in the URL. Sometimes the front end fetches every row and hides the wrong ones with CSS. Both look identical when you demo it to the customer whose data it is, and both are one open network tab away from being an incident report. It works. It demos beautifully. That is the problem.

What actually breaks

not "if". the specific failures.

  • The tenant filter, in the two ways it always breaks: a filter parameter the client controls, or a client-side fetch of the whole table with the other rows hidden in the render
  • The upstream API key. One Airtable PAT with access to the base, living wherever your app can reach it, which in a static-plus-serverless build often means the bundle or an unauthenticated function
  • Auth you generated. Magic links with no expiry, tokens signed with a secret in the repository, a password reset that returns a different error for unknown addresses and enumerates your entire client list
  • File attachments, because Airtable attachment URLs are unauthenticated and shareable. Rendering one in a portal hands out a link that works for anyone, forever, with no session behind it
  • Rate limits — Airtable's REST API is roughly five requests per second per base, so a portal that fetches on every page view starts 429ing the day it becomes popular
  • Roles, once a client asks for a read-only teammate. Two tiers is a flag, three is a permission system, and the migration between them happens live
  • The webhook or automation that writes back, which is the point at which a read-only portal becomes something that can change your source of truth
  • Cost and quota, because "app users" is the unit the paid product bills on and the number your own version has no reason to track until it matters
and then, at 3am

The portal had been live for seven months without a complaint, which is why nobody had looked at it. Then a client's operations manager, doing something entirely reasonable, changed the account ID in the address bar to see whether it was a typo — and it was not, and the page rendered. Different company, same layout: invoices, contract dates, the contact list, the notes field where your team writes things about clients that were never meant to leave the building. She screenshotted it, because of course she did, and sent it to her legal team before she sent it to you. By the time you had the tab open the interesting question was no longer how the bug happened. It was how many of the other four hundred logins had already tried the same thing, and you could not answer, because the access log recorded requests to a serverless function and never recorded which record ID it returned.

Is that you?

the verdict is a default, not a law

ship it if
  • Every user is inside your own company and the data has no tenant boundary in it at all
  • It is genuinely read-only, the source table contains nothing personal, and you would be relaxed about the whole thing being public
  • It is a prototype with a deadline you have written down, shown to one friendly customer, and switched off afterwards
  • There is exactly one tenant, because the class of bug this entry is about does not exist yet
don’t ship it if
  • Two customers who must not see each other's records log into the same deployment
  • The upstream token can read more than the requesting user is allowed to see, which is true of every base-scoped Airtable key
  • You wrote the authentication yourself instead of using a provider, or the magic links do not expire
  • The portal shows Airtable attachments, and you have not checked that those URLs require a session
  • You cannot produce, for the last ninety days, which user fetched which record

If you build it anyway

the checklist, then the prompt that enforces it

  1. Derive the tenant from the session on the server, every request, and never accept it from a parameter, a header, a cookie value or the request body. This one rule is most of the entry.
  2. Keep the upstream API key server-side only, and put a thin API of your own in front of the base. The browser must never hold a credential that can read more than the person holding it.
  3. Use a real identity provider. Auth0, Clerk, Supabase Auth, WorkOS — whatever you like, as long as sessions, expiry, reset and enumeration protection are somebody else's tested code.
  4. Write the negative test before the feature: authenticate as tenant A, request tenant B's record ID, assert 403 or 404 on the API response body. Run it in CI. That is the test that would have caught every real version of this.
  5. Proxy attachments through your own endpoint with a short-lived signed URL. Never surface a raw Airtable attachment link to a portal user.
  6. Log every record access with user, record ID and timestamp, and keep it. Without it you cannot answer the only question that matters after a leak.
  7. Cache reads and honour the upstream rate limit, or the portal that works for ten clients will start returning 429 to all of them at once.
  8. If the portal writes back, make writes a separate, minimally-scoped credential and require server-side re-validation of both the tenant and the field being changed.
the guardrail prompt
I am building a client portal over an Airtable base: customers log in and see
only their own records. Assume every logged-in user will eventually edit the URL
and the request body. Follow this order and refuse to skip step one.

1. The tenant identifier comes from the server-side session and nowhere else.
   Never from a query parameter, path segment, header, cookie value or request
   body. If I write code that does, stop and tell me why it is wrong.
2. There is exactly one function that reads records, it takes the authenticated
   user, and it applies the tenant filter itself. Every route calls it.
3. The Airtable token lives only on the server with the narrowest scope the API
   offers. Never bundled, never sent to the browser, never logged.
4. Do not write authentication. Wire up an established provider for signup,
   login, session, expiry, reset and verification. If I insist on magic links:
   fifteen-minute expiry, single use, and an identical response for known and
   unknown addresses.
5. Before any UI, write the authorisation tests: as tenant A, attempt to read,
   update and delete tenant B's record by ID and assert the response body is
   empty; assert a list endpoint returns only A's rows. Put them in CI.
6. Never fetch a whole table and filter in the browser. If you catch yourself
   doing it for convenience, say so out loud.
7. Attachments are proxied through my server behind an auth check with
   short-lived signed URLs. Raw Airtable attachment links are public.
8. Log every record read and write with user ID, record ID and timestamp before
   launch. After a leak it is the only thing that answers "who saw what".
9. Respect the upstream rate limit with server-side caching and backoff — assume
   about five requests per second per base.
10. If the portal writes back, use a separate credential and re-validate tenant
    ownership and the specific fields being changed.
11. Out of scope until I ask: multiple roles per tenant, uploads, billing and
    white-label domains. And be honest — if real customers are logging in next
    month, $59 for someone else's attacked authorisation model is cheaper.
paste this before you build — not after something breaks31 lines · 2146 chars

That one keeps you out of trouble. For the prompt that actually builds it, canivibecodeit.com has one.

their build prompt ↗

Or don’t build it

the boring option, and the way back out

just pay for it

Before the second customer logs in, honestly. $59 a month is not buying page layouts, it is buying the authorisation model — a tenant boundary that other people have already tried to break, session handling, roles, and attachment access control — plus a company that fields the disclosure email instead of you. Check the app-user caps against your real client count while you are there: 20 on Basic and 100 on Professional is the number that decides the price, not the features.

$59/mo is cheaper than your weekend.

your exit plan, if you already built it

The good news is that the data was never in your app. Airtable or Postgres remains the source of truth, so shutting the portal down means turning off a deployment and rotating the token it used. Do rotate it — a key that has sat in a serverless environment for a year is not a key you can assume is still private. What you lose is everything that lived only in the portal: accounts, roles, invitations, activity history. Export the user table and the access log before you delete anything, because if a question about who saw what arrives after the shutdown, the log is the only answer you have. And migrating to the commercial version is mostly a data-mapping exercise, which is worth knowing before you build a schema nobody else can read.

prior art · someone already did this
Budibase

Actively developed open-source low-code platform for internal tools and portals, with a real role and permission model.

Appsmith

Open-source internal-tool builder with server-side datasource credentials and granular access control, which is the part worth copying.

Questions

My filter runs on the server. Isn't that enough?

Only if the value it filters on comes from the session. The common generated pattern is a server-side query whose tenant value arrives in the request — a path segment, a query string, a hidden field — which is server-side and still completely broken, because the client chooses it. The test is simple: log in as one customer, change the identifier, and see what comes back. If you have never run that test, you do not know.

Are Airtable attachment URLs really public?

The URLs the API returns are not behind your app's session. If you render one in a portal page, anyone who obtains that link can fetch the file without logging in, and links get forwarded, cached and indexed. Proxy them through an endpoint of your own that checks the session and issues a short-lived signed URL instead.

Why is this rated worse than a project tracker that is harder to build?

Because difficulty is not the axis. A tracker for your own team fails inward: a colleague sees something early. A client portal fails outward, across a boundary that has a contract on either side of it, and the people harmed never agreed to your code. An easy build with an external blast radius beats a hard build with an internal one every time.

What is the honest safe version?

One tenant. A portal for a single client, with their data in its own base and its own deployment, has no cross-tenant bug available to it. It scales terribly and it is completely fine for two or three clients, which is more than most people building this actually have.

sources
  • GDPR Art. 5 — principles relating to processing of personal data
  • GDPR Art. 32 — security of processing
did you build it?

Every week, someone ships something they shouldn’t have.

New verdicts, the worst thing that landed in the trap, and the occasional incident report. No other email, ever.

also on the regret index
GlideDEMO ONLY

A spreadsheet-backed app is a lovely afternoon and a permanent support obligation.

BubbleDEMO ONLY

A no-code platform is a programming language with a GUI. You are writing a compiler.

ZapierYOUR FUNERAL

Retries are the feature. A loop without them silently drops work; a loop with them sends it twice.

last reviewed 2026-08-04 · verdict is editorial and unsponsored · shared entry data from canivibecodeit under MIT · not legal advice