Your Code DR AI Results
What we looked at
We ran a full diagnostic on this public Next.js playground, covering five dimensions:
- How the code is organized
- How secure it is
- How well it's tested
- How ready it is to deploy
- How maintainable it is day-to-day
We also reviewed runtime performance (image-generation cost and wait time) and drew architecture diagrams of how the app talks to OpenAI and stores images.
The short version
This is a well-typed, well-documented personal playground that does what it says on a laptop. The thing that needs urgent attention is the opposite of a leaky API key: there is no leaked secret in the repo, but a one-click public deploy leaves the image-generation button open to anyone on the internet — and they spend your OpenAI credits. There are also no automated tests and no safety check before a deploy, so a bad change can ship unnoticed.
Overall grade: D
What's working
- The TypeScript compiler is in strict mode, the linter is clean, and the code does not paper over problems with
any or leftover TODOs.
- The README is unusually honest: it already warns that a production deploy is world-reachable, and it documents every environment variable.
- Hosting awareness is real — on Vercel the app stores images in the browser instead of writing to a disk that would disappear.
- The only third-party dependency that matters is OpenAI. There is no tangled payments, email, or analytics stack to unwind.
Architecture at a glance
One Next.js app in the middle: the browser UI on one side, the OpenAI Images API on the other. Images live either on the machine’s disk (local mode) or in the browser (cloud/serverless mode). History stays in the browser. There is no server database.
C4Context
title System Context — image-playground
Person(user, "Playground User", "Generates and edits images in the browser")
Enterprise_Boundary(b0, "Browser image playground") {
System(app, "Browser image playground", "Next.js 16 App Router — UI and /api/images, /api/image, /api/image-delete, /api/auth-status")
SystemDb(fs, "Local filesystem", "./generated-images — fs storage mode only")
SystemDb(browser, "Browser storage", "Dexie IndexedDB for image blobs; localStorage for history and password hash")
}
System_Ext(openai, "OpenAI Images API", "images.generate / images.edit; optional OPENAI_API_BASE_URL override")
Rel(user, app, "Uses", "HTTPS")
Rel(app, openai, "Generate and edit images", "HTTPS")
Rel(app, fs, "Read/write image files", "fs mode")
Rel(app, browser, "Persist blobs and history", "indexeddb / localStorage")
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
What needs attention
Urgent
- Anyone with the URL can spend your image budget — unless you set a shared password, the generate/edit API is open. The default setup and the “Deploy to Vercel” path leave that password off. Combined with no usage cap, a stranger can request large, expensive images in batches.
- The optional password is easy to steal and does not protect saved images — the app stores a hash of the password in the browser and sends it on every request. Anyone who can read that storage can reuse it. Images served from disk are not password-checked at all.
- Nothing automatically checks a change before it goes live — there are no tests and no deploy pipeline. The paid image path and the password gate have never been exercised by an automated check. A broken comparison could lock you out or leave the door open.
- A failed generation can hang with no explanation, and nobody gets paged — stream errors are swallowed in the UI, and production has no error-tracking service. You find out when a user (or you) stares at a spinner.
Worth fixing soon
- Requests are not validated on the server the way they are in the form, so a crafted call can pick expensive sizes and models the UI would refuse.
- The main page and the generate/edit forms are each enormous single files. The next feature will be slower and riskier than it should be.
- History loads every saved image into memory. A long session of high-resolution images will make the tab crawl or crash.
- The default model is the most expensive, highest-resolution option. First-time clicks cost more and wait longer than a playground needs.
- Environment variables are documented in the README but not checked at startup — a missing API key only fails on the first generate.
Polish
- Diagnostic output under
.code-dr/ is not gitignored yet.
- A few files are out of format, and an unused CSS toolchain package is still listed.
- History thumbnails re-download full originals instead of cached, smaller previews.
Recommended next steps
We've prepared a pull request description (see .code-dr/PR_TEMPLATE.md) that addresses the items marked Urgent above. It includes:
- A production fail-safe so a public deploy cannot run without a password, plus a request limit on generate.
- Password checks on image download, and a move away from storing the password hash in the browser.
- A starter test suite and a pull-request check that runs lint, types, tests, and build.
- A fix for the silent hang on failed streams, plus timeouts so a stuck OpenAI call cannot sit forever.
- Startup checks for the API key and an example env file so a new clone fails clearly.
For the items marked Worth fixing soon and Polish, we've left an itemized plan at .code-dr/DIAGNOSIS.md in your repo. You can tackle them as bandwidth allows, or book a follow-up.
Generated with the CodeDR.AI Skill Pack — codedr.ai.
Questions? Reply to this email and a human will get back to you.