Commit 1

​# Moving ;Prompt-it Off Replit

## Migration

Yesterday was the first major step in turning ;Prompt-it from a Replit-hosted build into a real production-style web app.

Before this migration, Replit was doing a lot of hidden work for me. It held the code, ran the app, managed some environment behavior, and made the project feel like one contained system. That was useful while building, but it also meant I did not fully control the deployment stack.

The goal of this migration was to separate the project into the pieces it actually needs to run:

  • a frontend users can visit
  • a backend API that handles app logic
  • a database that stores users and content
  • custom domains for the app and API
  • production environment variables for external services

The biggest shift was moving from “Replit runs my app” to “I understand how my app is deployed.”

That meant moving the web app to app.wepromptit.com, connecting the API to api.wepromptit.com, setting up the database through Neon, rotating secrets, and making sure login, password reset, and core app routes still worked after the move.

This was not a simple copy-and-paste migration. The app had to be rebuilt, redeployed, reconnected, and debugged piece by piece.


Migrated project structure in VS Code.
This screenshot shows the post-Replit workspace organized into a local monorepo-style project with separate folders for the app artifacts, shared libraries, scripts, environment files, and migration notes.

### Tech Stack

The current production setup now looks like this:

Layer

Tool

Frontend

Vercel

Backend API

Render

Database

Neon Postgres

Domain

wepromptit.com

App Subdomain

app.wepromptit.com

API Subdomain

api.wepromptit.com

Package Manager

pnpm

Frontend Framework

Expo / React Native Web

Backend

Node / Express

Database ORM

Drizzle

Email

Resend

SMS

Twilio

Payments

Stripe

Version Control

Git / GitHub

One of the biggest things I learned here is that a full-stack app is not just “frontend and backend.” It is a chain of systems that all have to agree with each other.

The frontend needs the correct API URL.
The API needs the correct database URL.
The database needs the correct schema and user data.
The deployment platforms need the correct build commands.
The environment variables need to be formatted correctly.
The domain records need to point to the right services.

If any one of those pieces is wrong, the whole app can look broken.

## Bugs and Fixes

### 01: Environment (complete)

The migration surfaced a lot of issues that were hidden while the app lived on Replit.

The first major bug was with environment variables. I accidentally entered some values in the wrong format, including values like PORT=8080 instead of just 8080. The deployment platform already knows the key name, so the value field should only contain the value. That caused the API to fail because it was reading the full string instead of the actual port number.

Another issue was missing credentials. The API failed when OPENAI_API_KEY, Resend, Twilio, Stripe, and other production secrets were not available in the Render environment. The code expected those variables to exist, but the new host did not automatically know about anything from Replit.

The frontend had its own issue. At one point, the app was making requests to:

app.wepromptit.com/api/...

instead of:

api.wepromptit.com/api/...

That caused 404 errors because Vercel was receiving API requests that belonged to Render. The backend routes were not missing. The frontend was simply asking the wrong server.

#### The Fix:

I corrected the values so Render and Vercel received only the raw values they expected. After that, the API was able to read the port, secrets, database connection, and service credentials correctly.

I rotated and re-added important production secrets, including:

  • OpenAI
  • Resend
  • Stripe
  • Twilio
  • database credentials

Then I verified the API by checking the health route:

api.wepromptit.com/api/healthz

Once that worked, I knew the backend was live and reachable.

For the frontend API issue, I made sure the build used:

EXPO_PUBLIC_API_URL=https://api.wepromptit.com/api

That allowed the frontend to call the real backend instead of trying to call API routes on the Vercel domain.

Frontend API client cleanup. This section of the API helper handles refresh tokens, retrying authenticated requests, and keeping users logged in after the migration. Fixing this helped stabilize login behavior across the deployed web app.

## 02: Blank Page (complete)

There was also a blank-page issue caused by static build files. The built index.html was pointing to an old JavaScript bundle that no longer existed. That meant the app loaded the page shell, but the actual JavaScript needed to run the app returned a 404.

#### The Fix:

For the static build issue, I learned to check the generated build files and avoid committing stale static-build output unless it was intentionally part of the deployment process. This helped prevent mismatches between index.html and the generated JavaScript entry files.

## 03: Database Migration (complete)

The database migration was another major challenge. The first restored database appeared to include content, but the login data was not what I expected. I had to inspect the tables, identify where the real usernames and password hashes were stored, separate test accounts from actual accounts, and make sure the production API was pointing at the correct Neon database.

The password reset flow also took longer than expected. The endpoint existed, but local testing showed that reset codes were not being written to the database when email or SMS delivery failed first. That made it look like a database issue when the real failure was happening earlier in the reset flow.

#### The Fix:

I created a test import database in Neon, restored the old dump, inspected the available tables, and confirmed which table contained the actual user credentials. I also checked user counts, test users, premium users, and whether imported accounts matched what I expected.


Safe local database startup logging. I added a development-only log that prints the active database host and database path without exposing credentials. This helped confirm whether the API was pointing at the correct Neon database during password reset testing.

For password reset, I manually traced the flow:

  1. Find the user.
  2. Request reset.
  3. Confirm whether delivery succeeds.
  4. Confirm whether a reset code is created.
  5. Reset the password.
  6. Log in with the new password.

Eventually, I was able to reset my password and log back in successfully.

For TypeScript and build errors, I fixed issues one at a time instead of trying to silence everything globally. Some fixes were related to dependencies, some were related to React Native Web style limitations, and some were caused by config values that TypeScript no longer accepted.

## 04: UI (in progress)

After migration, some UI bugs also became more visible on mobile web. The app could detect device type, but the layout was not fully responsive. Some screens had too much top or bottom spacing, the bottom navigation sat too high, headers needed to move up, and some content did not automatically scale to the screen size.

There was also an avatar display issue where text appeared over the avatar in some parts of the app. The profile version of the bug was fixed, but another instance later appeared in the feed.

## What I Learned

The biggest thing I learned is that a full-stack app is not just code. It is an ecosystem.

Before this migration, I understood the app mostly as screens, routes, components, and features. After the migration, I understand it more as a product system. A working product needs code, hosting, domains, secrets, databases, build scripts, deployment logs, monitoring, and recovery plans.

I also learned how much hidden work Replit was doing for me. Moving away from Replit forced me to understand the actual structure of the app. That was frustrating in the moment, but it made me a better developer because I had to understand what each piece was responsible for.

I learned that environment variables are fragile. A small formatting mistake can crash a deployment. Something as simple as putting KEY=value into a value field instead of just value can break the app.

I learned that a successful API response does not always mean the full feature works. Password reset was the best example of that. The endpoint could respond, but I still had to verify database writes, email/SMS delivery, code expiration, reset behavior, and login afterward.


Live API health check. The API returned {"status":"ok"}, confirming that the deployed backend was reachable and responding after the migration.

I learned that “it builds locally” and “it deploys correctly” are not the same thing. Local builds helped confirm the code could compile, but production introduced separate issues with environment variables, hostnames, domains, and deployment settings.

I learned that responsive mobile web is harder than it looks. It is not enough for an app to know the device type. The content has to fit the actual visible screen, account for browser bars, handle bottom navigation, avoid unsafe spacing, and still feel natural across screens.

I also learned why teams exist.

A project like ;Prompt-it needs the work of a frontend developer, backend developer, database admin, DevOps engineer, QA tester, UX designer, product manager, and support person. As a solo builder, I had to wear all of those hats in one day.

That was exhausting, but it also made the project feel more real. 



TypeScript verification after fixes. After making layout, API, and configuration changes, I ran the Looplet typecheck to confirm the frontend compiled cleanly without TypeScript errors.

## Next Steps

The next phase should not be broad growth yet. The next phase should be controlled testing.

Before inviting a large audience, I need to stabilize the user experience enough that testers can use the app without getting blocked by layout issues, login issues, or confusing flows.

The next technical priorities are:

  1. Fix mobile web layout screen by screen.
  2. Lower the navigation bar where needed.
  3. Move headers up where needed.
  4. Make the profile header and inline buttons fixed while the rest of the profile scrolls underneath.
  5. Fix the feed avatar text overlay.
  6. Add the official ;Prompt-it welcome message thread.
  7. Make sure users can archive that official thread but not delete it.
  8. Adjust the daily card so it matches the height of its sister cards.
  9. Continue testing login, password reset, posting, feed, shop, profile, and messages.

After those fixes, the next product step is a small closed tester round.

I would start with 5–10 testers and ask them to:

  • create an account
  • log in
  • reset their password
  • reveal the daily prompt
  • submit a response
  • browse the feed
  • visit their profile
  • open the shop
  • test messages
  • send screenshots of anything broken, confusing, cramped, or awkward

The goal is not to grow fast yet. The goal is to learn where the app breaks, where users get confused, and what makes them want to come back.

Once a small group can use ;Prompt-it comfortably, then I can move toward growth with more confidence.

For now, this commit marks a major turning point:

;Prompt-it is no longer just a Replit project.
It is becoming a real deployed product.

Comments