{
"$type": "site.standard.document",
"description": "Someone on Reddit asked about deploying a custom vibe-coded app for work, installed on a local server. They could not code their way through problems,",
"path": "/if-you-vibe-code-an-app-for-work-put-the-backend-in-charge/",
"publishedAt": "2026-05-01T03:29:00.000Z",
"site": "at://did:plc:bryys25pc2fnagnyxqgsglhd/site.standard.publication/3mn26bjkkmh23",
"tags": [
"AI",
"Web"
],
"textContent": "Someone on Reddit asked about deploying a custom vibe-coded app for work, installed on a local server. They could not code their way through problems, but figured Claude could fix things when they broke.\n\nI have been programming for 30 years. Beyond the obvious \"does it work?\", these are the two things I would check first:\n\n * the backend must not blindly trust the frontend\n * secrets must not leak into the frontend\n\nTHE BACKEND MUST NOT TRUST THE FRONTEND\n\nAssume a website frontend talking to a server-side backend. Same idea applies to mobile apps, desktop apps, browser extensions, internal dashboards, whatever. If there is a client and a server, the client is not trusted.\n\nIt is easy to build as if only your frontend will ever talk to your backend. Maybe the button is hidden. Maybe the form validates the email address. Maybe the frontend only sends role: \"user\".\n\nBut none of that matters if the backend accepts bad requests directly.\n\nAnyone who can reach your backend can call it directly:\n\ncurl -X POST https://your-app.example.com/api/generate \\\n -H \"Content-Type: application/json\" \\\n -d '{\"prompt\":\"do expensive AI work for me\"}'\n\nThey do not need to use your UI.\n\nThey can try:\n\n * login attempts\n * account creation\n * password reset flows\n * free trial limits\n * free AI calls\n * alt text generation\n * file uploads\n * admin-looking payloads\n * object IDs that belong to other users\n * prices changed to 0\n * isAdmin: true\n * plan: \"enterprise\"\n\nIf the backend accepts it, it happened.\n\nFRONTEND VALIDATION IS FOR USER EXPERIENCE\n\nFrontend validation is useful. It makes the app feel better. It catches mistakes before a request goes over the network.\n\nBut it is not security.\n\nIf your frontend checks that a file is smaller than 10 MB, the backend still has to check that the file is smaller than 10 MB.\n\nIf your frontend hides the \"delete project\" button from non-admins, the backend still has to check that the current user is allowed to delete the project.\n\nIf your frontend disables the \"generate\" button after 10 free AI calls, the backend still has to count the calls.\n\nThe frontend can help honest users avoid mistakes. The backend decides what is allowed.\n\nASK THE AGENT TO CHECK THIS DIRECTLY\n\nIf I were vibe-coding an internal app and did not trust myself to catch this, I would ask the agent to review the backend directly.\n\nSomething like:\n\nReview this app for places where the backend trusts the frontend too much.\n\nCheck all API routes. For each route, verify:\n- authentication is required where needed\n- authorization checks happen on the backend\n- users can only access their own records\n- request body fields cannot override server-owned fields\n- paid or limited features are enforced server-side\n- rate limits exist for expensive operations\n- file upload limits are enforced server-side\n\nReturn concrete file paths and fixes.\n\nThe exact prompt does not matter. The important part is asking about the class of bug directly.\n\nCoding agents are good at fixing things when you point them at the right problem. \"Is this app secure?\" is too vague.\n\nYou still have to decide whether the agent's answer is good enough. For a work app with real data, real users, or real money involved, I would get a human programmer to check it too.\n\nRATE LIMIT ANYTHING EXPENSIVE\n\nAI calls make this worse because the attack can cost you money immediately.\n\nIf your app has a free feature that calls OpenAI, Anthropic, Gemini, or any other paid API, assume someone will try to call it directly.\n\nEven on a local server, ask what \"local\" means.\n\nIs it only bound to localhost? Is it exposed on the office Wi-Fi? Is it behind a tunnel? Is it reachable through VPN?\n\nRate limit these endpoints:\n\n * login\n * signup\n * password reset\n * email sending\n * AI generation\n * file uploads\n * anything that hits a paid third-party API\n\nAlso set billing limits on the provider side. Do not rely only on your own app code for this.\n\nFor an internal tool, the rate limits can be simple. You do not need a giant abuse prevention system on day one. But you need something.\n\nDO NOT PUT SECRETS IN THE FRONTEND\n\nThe second thing I mentioned was leaking API keys or secrets in the frontend.\n\nFrontend code is sent to users. For web apps, that is literal JavaScript in the browser. For mobile and desktop apps, it is still code running on a device you do not control.\n\nAssume an attacker can inspect it.\n\nAt minimum, they can search the downloaded code for strings that look like secrets:\n\nsk-...\neyJ...\nAKIA...\n-----BEGIN PRIVATE KEY-----\n\nSome keys are meant to be public. Analytics keys are commonly public. Stripe publishable keys are public. Supabase anon keys can be used from the frontend if your row-level security is correct.\n\nBut secrets belong on the backend:\n\n * OpenAI API keys\n * Anthropic API keys\n * Stripe secret keys\n * database URLs\n * private signing keys\n * webhook secrets\n * admin tokens\n * service account credentials\n\nIf the frontend needs to do something that requires a secret, it should call your backend. The backend uses the secret. The frontend gets the result.\n\nENVIRONMENT VARIABLES DO NOT AUTOMATICALLY MAKE SECRETS SAFE\n\nOne common mistake: putting a secret in an environment variable and assuming that makes it safe.\n\nIt depends where that environment variable is used.\n\nIn many frontend frameworks, variables with certain prefixes are intentionally bundled into the client. For example, PUBLIC_, NEXT_PUBLIC_, VITE_, or similar names usually mean \"make this available to browser code.\"\n\nThat is fine for public values. It is wrong for private secrets.\n\nI would ask the agent to check this too:\n\nReview all environment variables and config usage.\n\nIdentify any secrets that are imported or referenced by frontend code.\nCheck framework-specific public env prefixes.\nList which variables are safe to expose and which must move server-side.\n\nThen verify the built frontend bundle if the app matters. Search the output. Search the network requests. Search the browser source.\n\nDo not just trust the .env file layout.\n\nLOCAL SERVER DOES NOT MEAN SAFE\n\n\"Installed on a local server\" can mean many things.\n\nIt might mean a machine under your desk only reachable from your laptop. It might mean an office server reachable by everyone on Wi-Fi. It might mean a NAS. It might mean a Cloudflare tunnel. It might mean \"temporarily exposed for testing\" that stays exposed forever.\n\nI would still treat it as a real deployed app:\n\n * require login if the data matters\n * use HTTPS if it crosses a network\n * restrict network access where possible\n * keep secrets on the server\n * back up important data\n * log errors without logging secrets\n * set billing limits for paid APIs\n\nInternal tools are still tools. They still delete data, send emails, upload files, and call paid APIs.\n\nMY MINIMUM CHECKLIST\n\nFor a small vibe-coded work app, my checklist would be:\n\n * Can an unauthenticated user call any API route?\n * Can one user read or modify another user's data by changing an ID?\n * Are admin actions checked on the backend?\n * Are usage limits enforced on the backend?\n * Are expensive operations rate limited?\n * Are all secrets server-only?\n * Are API billing limits configured?\n * Are backups configured if the data matters?\n * Is the app reachable only by the people who should reach it?\n * Can I restore it if Claude \"fixes\" it into a worse state?\n\nThat last one matters.\n\nIf you cannot code your way out of a bad change, make sure the project is in git and committed before asking an agent to make changes. Then you can get back to a known working version.\n\ngit status\ngit add .\ngit commit -m \"Working version before changes\"\n\nUse the agent. Let it help. But give yourself a way back.\n\nI am not against vibe-coded internal tools. I use coding agents heavily. They are useful, and small custom tools can save a lot of time.\n\nBut if the app has a backend, the backend is the authority. The frontend is just a client.\n\nAnd if a value is secret, it does not go into the frontend.\n\nGood luck building.",
"title": "If You Vibe Code an App for Work, Put the Backend in Charge"
}