# app-run

> Converts an approved (level 4) prototype into a real React app per https://skills.thisaan.cloud/standards/APP-STACK.md — real stored data (SQLite via Prisma), a real login, running on the owner's own machine across several browsers, starting from an empty database — then installs and starts it for them. This is the optional fourth owner-side command, a branch off the end of /app-show, taken instead of (or before) sending the work to a developer. Use when the user says "อยากลองใช้จริง" (want to actually try using it), "ทำเป็นแอปจริง" (make it a real app), "ใช้เองก่อน" (use it myself first), "ยังไม่ส่ง dev" (not sending to a developer yet), "อยากมีล็อกอิน" (want a real login), "เก็บข้อมูลจริง" (store real data), "อยากลองใช้บนเครื่องตัวเอง" (want to try it on my own machine). Requires LEVEL.md to already show level=4 approved=yes — if not, send the user back to /app-show first.

**วิธีใช้:** วางข้อความทั้งหมดนี้เป็นข้อความแรกของแชท แล้วบอกงานที่ต้องการต่อท้าย

**มาตรฐานที่ต้องทำตาม:** ลิงก์มาตรฐานในไฟล์นี้เปิดได้จริง ถ้า AI ดึง URL เองได้ ให้เปิดอ่านตามลิงก์
ถ้าดึงไม่ได้ (แชทเว็บทั่วไป) ให้วาง `https://skills.thisaan.cloud/md/standards.md` เป็นข้อความแรกก่อน แล้วค่อยวางไฟล์นี้ตาม

---

**สำหรับ:** เจ้าของงาน · **ถัดไป:** /app-send

**Output language:** always reply to the user in simple, short Thai. Never reply in English.
No jargon unless you explain it in one clause. Short sentences. Never refer to yourself with
a pronoun ("หนู", "ผม", "ฉัน", "เรา") — write sentences that don't need a self-reference.
No emoji anywhere, including chat replies. Multiple-choice options are NUMBERED 1. 2. 3. 4.,
each on its OWN LINE, never run together in one paragraph, no skipped number, at most 4 options. This applies to every question you ask, every
report you write, and every document you produce.

This is the fourth and last owner-side command, and it is **optional**. After level 4 of `/app-show` is approved, the owner picks one of two paths: hand the prototype to a developer now (`/app-send`), or first turn it into a real working app on their own machine and actually use it — that second path is this skill. It follows the stack fixed in `https://skills.thisaan.cloud/standards/APP-STACK.md` exactly; do not restate that document's content here, only cite its section numbers.

## 1) The gate — check before anything else

Same contract as `/app-send`: open `LEVEL.md` in the prototype folder and read **only its first line**, the machine-readable `<!-- STATUS: level=4 approved=yes updated=YYYY-MM-DD -->` comment. Pass only if both `level=4` and `approved=yes` are present there. **Never string-match the Thai history lines below it** — those vary in wording and are for people, not machines. Missing/older `LEVEL.md` with no STATUS line = not approved.

If the gate fails: stop immediately, build nothing, and tell the user plainly in Thai that level 4 needs the owner's approval first, sending them back to `/app-show`.

## 1b) Read the whole invoking message before doing anything else

The message that triggered this skill often carries more than the command. **Never act on the command and stay silent about the rest.** Two things to look for, both in the same pass:

- **Extra instructions** (a fix to make, something to change first). Acknowledge every one of them out loud before starting. Do the ones that belong before the build — an edit to `data/mock-data.json` or the prototype screens must happen *before* step 3, because the schema and the seed are derived from those files and redoing it later means wiping the database. Park anything that genuinely belongs after the build in `LEVEL.md`'s `## ค้างไว้ (ยังไม่ได้ทำ)` section, quoting the owner's own words with the date (format in `PROJECT-STRUCTURE.md` section 3), and raise it again in the completion report. An item leaves the list only once actually done, logged in `HISTORY.md`.
- **Answers to step 2's questions, given up front.** An owner who has done this before often answers before being asked.

## 2) Collect what's still missing — one numbered list, one turn

The prototype deliberately left real-world details unanswered. **First check what the invoking message (and `BRIEF.md`) already answers** — ask only for what is genuinely still missing, and say once which items were taken from what the owner already wrote. **If every item is already answered, ask nothing and go straight to step 3.** Re-asking a question the owner just answered reads as not having read them.

Ask whatever remains as **one** numbered list (per `https://skills.thisaan.cloud/standards/CONVENTIONS.md` section 4 — numbers, own line each), each item carrying a stated default so a partial answer is enough to keep moving:

1. ชื่อจริงของแอป (default: ชื่อชั่วคราวที่ตั้งไว้ตอนทำ prototype)
2. ชื่อบริษัทหรือร้านที่จะแสดงในแอป (default: ใช้ชื่อแอปแทนไปก่อน)
3. โลโก้ — มีไฟล์ไหม ถ้ายังไม่มี ใช้ไอคอน Lucide คู่กับชื่อแทนได้ ไม่ต้องรอ (default: ไอคอน Lucide + ชื่อ)
4. ใครจะเป็นคนล็อกอินใช้งาน — คนเดียวหรือมีทีมงานหลายคน ระบุชื่อทุกคน และมีใครที่ควรเห็น/ใช้ได้แค่บางส่วนของระบบไหม (default: เจ้าของงานคนเดียว เห็นทุกส่วน) — **ทุกบัญชีจะถูกสร้างให้เสร็จตอนสร้างแอป พร้อมชื่อผู้ใช้และรหัสผ่านครบ ไม่ต้องมาตั้งเองทีหลัง**
5. ข้อมูลที่จะกรอกเข้าไปเป็นข้อมูลบุคคลจริงไหม เช่น ลูกค้าจริง (default: ยังไม่ใช่ ใช้ทดลองก่อน)

**Take whatever is given.** Anything skipped gets the stated default, said out loud once, and recorded in `REAL-APP.md`. Never block the build on a missing logo — item 3 always has a fallback. Item 5's answer changes how firmly the warning in step 4 gets stated — read it carefully, don't skip it.

## 3) Build

Scaffold and code per `https://skills.thisaan.cloud/standards/APP-STACK.md` sections 4 (file layout) and 5 (standing up the project); follow its code rules (section 6) without exception. Detailed how-to for each piece lives in `references/`, read the one that matches what's being done right now:

- **Scaffolding, installing dependencies, running it** -> `references/setup.md`
- **Turning each prototype screen into a React route/component** -> `references/convert-screens.md`
- **Deriving the Prisma schema from `data/mock-data.json` and seeding** -> `references/data.md`
- **Login, the first account, session security** -> `references/auth.md`

Carry over every UI rule already satisfied by the prototype — fixed frame, dialogs, confirm tiers, toasts, the four-band table screen, skeleton behavior — using the library each maps to per `https://skills.thisaan.cloud/standards/APP-STACK.md` section 8. Do not hand-roll something that section already assigns to a library.

Keep the same `data-testid` values from the prototype on the matching elements in the real app — nothing has to be re-learned by anyone testing it.

## 3b) Prove the login works before handing over a single credential

**A password that has never been used to log in is a guess, not a credential.** Handing the owner a table of
usernames and passwords that turn out not to work is worse than handing them nothing — they will assume they
typed it wrong and keep retrying. So the credentials get tested by whoever generated them, against the running
app, before they are shown to anyone.

Run every one of these against the actual running server, and only then write the report:

1. **Each account logs in.** Not one sample — every row of the table that is about to be shown. Use the exact
   string that will be printed, copied from the same variable, so a trailing space or a mangled character
   cannot survive.
2. **A wrong password is rejected.** Same username, altered password -> refused. This proves step 1 succeeded
   because the credential was right, not because the check is broken and accepts anything.
3. **The forced password change actually gates.** Log in with a generated password, then try to reach a normal
   data route while `must_change_password` is still true -> refused. Then change the password and confirm the
   same route now works, and that the old password no longer logs in.
4. **Role restrictions hold server-side.** If any account was limited to part of the system, call the
   restricted route directly as that account — not by clicking the hidden button, by calling the route — and
   confirm it is refused. Passing only because the menu item is hidden is a failure.
5. **Logging out ends the session.** After logout, a request replaying the old cookie is refused.

If a test needs a browser and the browser tooling is unavailable, drive the API directly instead — the point is
that a real request is made and a real answer comes back. **"Could not test it" is a blocked build, never a
line in the report asking the owner to check it themselves.** The owner is not the tester; being handed
untested credentials is exactly the failure this section exists to prevent.

Anything that fails: fix it and run the whole list again from the top. Report only what actually ran.

## 4) Be honest about what this is

Once it's running, state all of the following clearly, in Thai, in the completion report — this is not optional boilerplate, per `https://skills.thisaan.cloud/standards/APP-STACK.md` section 7:

- It runs on this machine only — nobody else can reach it over the network.
- What's deliberately still missing at this stage (HTTPS, backups, monitoring, audit trail, single-trusted-user model — the exact list in section 7).
- **It must not hold real customer data until a developer has run `/security-review`.** If the answer to collection item 5 was "yes, real people's data," say this more firmly here, and repeat it in `REAL-APP.md` as well — don't say it once and move on.
- Where the database file lives, and that backing it up means copying that one file.

## 5) Output

A running app, reachable at a clickable local link, plus these files at the project root:

- **`REAL-APP.md`**, in Thai — what was built, how to start and stop it, where the database file is and how to back it up, who can log in (**usernames and roles only — never a password**, per `references/auth.md`), and what is not ready yet (the section-4 honesty list).
- **`HISTORY.md`** — append one entry recording that the real app was built and exactly what was answered (or defaulted) in step 2.
- **`LEVEL.md`** — add a line recording that the real-app branch was taken. **Do not touch its STATUS line** — that line belongs to the prototype's own level/approval state, not to this branch.

Then tell the user the next step is `/app-send`, and that because this already uses the team's standard stack, a developer continuing from here reads it and builds on top — never rebuilds it from scratch.

## Checklist before calling it done

- [ ] Gate checked first — `LEVEL.md` STATUS line parsed, not the Thai prose; build never started before it passed
- [ ] Every instruction in the invoking message acknowledged out loud — done before the build, or parked in `LEVEL.md` and raised again in the report; none silently dropped
- [ ] Collection items the owner already answered were not re-asked; whatever remained was asked as one numbered list, each with a default; nothing left silently unanswered
- [ ] Build follows `https://skills.thisaan.cloud/standards/APP-STACK.md` sections 4-6 exactly — no substituted library, no skipped code rule
- [ ] Every checklist item in `https://skills.thisaan.cloud/standards/APP-STACK.md` section 9 passes before calling the app real-ready
- [ ] Every account from collection item 4 exists and works the instant the build finishes — no setup wizard left for the owner, no login form with no account behind it
- [ ] Username + password + role for every account listed once in the chat reply as a table, and written nowhere else; each generated password forces a change at first login
- [ ] All five login proofs in step 3b actually ran against the running app and passed — every credential in the table was used to log in, a wrong password was refused, the forced change gated, role limits held server-side, logout ended the session. Nothing in this list was delegated to the owner
- [ ] App starts from an empty database; mock data is an optional, clearable seed, never the default state
- [ ] The app was installed and started, and a clickable link was given — or, if the user declined install, the project files exist and the commands to run it were given instead
- [ ] The honesty report (step 4) was said in the chat reply, in Thai, and also written into `REAL-APP.md`
- [ ] `HISTORY.md` has a new entry; `LEVEL.md` has the real-app-branch line; `LEVEL.md`'s STATUS line is unchanged
- [ ] User was told the next step is `/app-send`
- [ ] No emoji anywhere in code, documents, or chat replies