The landing page: drop, paste or pick a screenshot.
The Replit console after the fix: PostgreSQL through DATABASE_URL and Object Storage on the default bucket.
Published on Replit as an Autoscale deployment.
Redline: design feedback, pinned to the pixel
Redline is a small tool for freelancers. Drop in a screenshot of your work, send your client one link, and they click anywhere on the design to leave a numbered comment. No accounts on either side. It's live at https://redline--ergiinnk.replit.app
Built and running on Replit
React and TypeScript in the browser, Express on the server, one npm project. The .replit file sets Node 22, PostgreSQL 16, the run command and the Autoscale deployment, so the workspace and the deployment start the same way.
Replit PostgreSQL holds boards and comments. The app creates its tables on first boot and seeds a demo board, so a fresh deployment works without a manual migration.
Replit App Storage holds the screenshots, through the official @replit/object-storage client. The server checks each file's first bytes, so a text file renamed to .png is turned away, and it serves images with long cache headers.
Two links per board. The client link can only comment. The owner link can also resolve and delete, and only a hash of its key is stored.
Comments show up for both sides within a few seconds, and polling pauses while the tab is hidden.
Debugging it on Replit
On the first run in the Replit workspace, the database connected but the screenshots were going to the container's own disk, because the Repl had no storage bucket yet. Files there would be gone after the next deploy. I'd built the storage layer to fall back loudly instead of crashing, so the console said exactly what was missing.
I created the bucket in App Storage and restarted the app. On boot, the seed saw that the demo image wasn't in the bucket and uploaded it again. The health check on the published app now reports Object Storage and PostgreSQL, and the deployment passed Replit's security checks before it went live.