# ALZAR FZE Website — Migration Brief (Manus → Railway + TiDB)

**Goal:** Take the existing Manus-built site and deploy it as a standalone service on
Railway, backed by a dedicated database on our existing TiDB cluster, then point
`alzarfze.com` and `alzarfze.org` at it. Manus is fully decommissioned at the end.

This is its OWN repo and its OWN chat — it must not touch the CRM build.

---

## 1. What this app is

Full-stack TypeScript monorepo (single package.json):

- **Client:** React 19 + Vite + Tailwind v4 + Radix UI + wouter (routing) + tRPC client.
- **Server:** Express + tRPC + Drizzle ORM (MySQL dialect → works on TiDB).
- **DB tables:** `users` (admin auth) and `contact_submissions` (contact form).
- **Features:** marketing pages (Home, About, 4 industry pages, Partners, Contact,
  landing pages, legal pages), contact form with server-side CAPTCHA + owner
  notification, and an admin dashboard to read/triage submissions.
- **Package manager:** pnpm (see `packageManager` field; honor it).

Build/run scripts already defined:
- `pnpm dev`   → tsx watch server/_core/index.ts
- `pnpm build` → `vite build && esbuild server/_core/index.ts ... --outdir=dist`
- `pnpm start` → `NODE_ENV=production node dist/index.js`
- `pnpm db:push` → drizzle-kit generate && migrate

---

## 2. Do this FIRST: prove a green baseline

Before removing anything, confirm the app installs and builds as-is:

```
pnpm install
pnpm build
```

Fix only what's needed to get a clean build. Commit that as the baseline. Every
Manus removal after this should be a small, reviewable diff against a working tree.

---

## 3. Manus dependencies to remove/replace

### 3a. HARD couplings (must handle before production)

**OAuth login (Manus identity provider)** — files: `server/_core/oauth.ts`,
`server/_core/sdk.ts`, `server/_core/env.ts` (`oAuthServerUrl`, `appId`,
`ownerOpenId`), `client/src/_core/hooks/useAuth.ts`, `client/src/const.ts`
(`getLoginUrl`), and the `auth.me` / `auth.logout` tRPC routes in `server/routers.ts`.

- This gates the **admin dashboard only**; the public site needs no login.
- Replace Manus OAuth with a **single-admin auth**: email+password (hash with
  bcrypt/argon2) OR a signed-cookie admin token derived from an env var.
- KEEP the generic JWT session helpers in `sdk.ts` (`signSession`, `verifySession`,
  cookie handling — these are plain `jose`, not Manus-specific).
- The `users` table has an `openId unique NOT NULL` column tied to Manus. Repurpose
  it (e.g. store the admin email there) or migrate the schema to an `email`-keyed
  admin. Keep the `role` enum (`user`/`admin`) — `adminProcedure` depends on it.

**Owner notification** — file: `server/_core/notification.ts` (Manus "forge"
endpoint via `BUILT_IN_FORGE_API_URL` / `BUILT_IN_FORGE_API_KEY`).

- Replace with SMTP email (Resend / Nodemailer / SendGrid) to the owner inbox.
- NON-BLOCKING: submissions are already persisted to `contact_submissions` and
  visible in the admin dashboard even if notification is disabled. If email isn't
  ready at launch, stub `notifyOwner` to a no-op that logs, and ship.

**File storage** — file: `server/storage.ts` (Manus storage proxy;
`BUILT_IN_FORGE_API_URL/KEY`; pulls in `@aws-sdk/*`).

- Grep the codebase for actual callers of `storagePut` / `storageGet`. Current
  audit found NONE in the public site path. If confirmed unused, DELETE
  `server/storage.ts` and remove the `@aws-sdk/client-s3` and
  `@aws-sdk/s3-request-presigner` deps. Only re-implement (S3/R2) if a live caller exists.

### 3b. Dev-only cruft to strip (no effect on production render)

- `vite.config.ts`: remove `vitePluginManusRuntime()` import+use, remove the whole
  `vitePluginManusDebugCollector` plugin, and remove `.manus*.computer` from
  `server.allowedHosts`.
- Remove `vite-plugin-manus-runtime` from devDependencies.
- Delete `client/public/__manus__/` (debug-collector.js, version.json) and the
  top-level `.manus/` folder.
- `client/src/_core/hooks/useAuth.ts`: remove the
  `localStorage.setItem("manus-runtime-user-info", ...)` side-effect.
- `client/src/components/ManusDialog.tsx`: review; likely removable — check `App.tsx`
  for usage and delete if orphaned.
- The word "Manus" appearing in page content/comments (Footer, Hero, industry
  pages, etc.) is cosmetic — leave unless it's user-visible copy that shouldn't ship.

---

## 4. Database on TiDB

- Create a dedicated schema (e.g. `alzar_website`) on the existing TiDB cluster —
  separate from the CRM's database.
- Drizzle uses the MySQL dialect (`drizzle-orm/mysql2`); TiDB is MySQL-compatible.
- Set `DATABASE_URL` to the TiDB connection string (include TLS params TiDB requires).
- Run `pnpm db:push` to create `users` and `contact_submissions`.
- Verify: submit the contact form on a preview URL, confirm the row lands in TiDB,
  confirm it appears in the admin dashboard.

---

## 5. Railway deployment

- New Railway **service** (not shared with the CRM), pointed at this repo.
- Build command: `pnpm install && pnpm build`. Start command: `pnpm start`.
- Server reads `PORT` from env (already handled in `server/_core/index.ts`) — let
  Railway inject it.
- Env vars to set:
  - `DATABASE_URL` (TiDB, alzar_website schema)
  - `JWT_SECRET` (strong random; used by session signing)
  - `NODE_ENV=production`
  - Admin auth vars (per whatever scheme you chose in 3a)
  - Email/SMTP vars (if implementing notifications)
  - Remove/ignore: `OAUTH_SERVER_URL`, `VITE_APP_ID`, `OWNER_OPEN_ID`,
    `BUILT_IN_FORGE_API_URL`, `BUILT_IN_FORGE_API_KEY`.
- Confirm the Railway-provided URL renders the full site (all pages, images, contact
  form, admin login) BEFORE any DNS change.

---

## 6. DNS cutover (LAST — zero downtime)

- Keep Manus serving `.com`/`.org` until the Railway URL is verified good.
- Point both `alzarfze.com` and `alzarfze.org` at the Railway service
  (CNAME/A per Railway's custom-domain instructions; add both domains in Railway).
- Verify TLS certs issue for both domains, both resolve, contact form works in prod.
- Only then decommission Manus.

---

## 7. Known content issues to verify (from prior Manus audit)

Two images were reported broken on the Glass industry page and should be re-checked
after build: "Bucher Automation Controls" and the Pennekamp hot-end equipment image
(were showing alt text). Confirm all industry-page and partner images resolve.

---

## 8. Definition of done

- [ ] `pnpm build` clean; `pnpm start` serves the full site locally.
- [ ] No Manus runtime imports remain; `grep -ri manus src server` is cosmetic-only.
- [ ] Contact form → row in TiDB → visible in admin dashboard.
- [ ] Admin login works with the new (non-Manus) auth.
- [ ] Owner notified of submissions (or notification cleanly stubbed & logged).
- [ ] Deployed on its own Railway service + own TiDB schema.
- [ ] `.com` and `.org` both resolve to Railway with valid TLS.
- [ ] Manus decommissioned.
