# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Layout

This directory holds two independently deployed repositories for Trieu An Hospital's website/patient-portal system — not a single app. Read the CLAUDE.md inside whichever one you're actually working on for commands, architecture, and code style; this file only covers what spans both.

- `trieuan-frontend/` — Next.js 14 public site + patient portal. See `trieuan-frontend/CLAUDE.md`.
- `trieuan-headless/` — Laravel 11 API + Livewire admin + HIS/payment/SMS integrations. See `trieuan-headless/CLAUDE.md`.

They communicate over HTTP only (frontend calls the backend's `/api/v1` REST API via `libs/trieuan-api`) — there is no shared code, shared types are duplicated by hand (Laravel API Resources on one side, `libs/shared-constants` TS types on the other).

## Before fixing anything

**Before changing code to fix a reported behavior, check whether it's actually a "setting" — i.e. a value the hospital's admin can already change themselves through the admin panel UI, with no code/deploy needed.** These live in `trieuan-headless`'s `spatie/laravel-settings` classes (`GeneralSettings`, `AppointmentSettings`, `ArticleSettings`, `IntegrateSettings` — see `trieuan-headless/CLAUDE.md`), each editable from its Livewire admin screen. Check the relevant settings class, and what's currently configured there, before touching component/controller code — otherwise you risk "fixing" something that's actually just a wrong toggle/value in the admin panel, or hardcoding something that's supposed to stay admin-editable.

**Whenever you confirm a value is admin-editable (a setting, a Livewire-managed field, a translation string, etc.), add/update an entry for it in `HD.md`.** `HD.md` is a plain-language, customer-facing guide (Vietnamese) the repo owner hands to the hospital's admin staff, listing what they can change themselves and how — keep entries in that same style (short numbered steps, no code/technical jargon, no mention of the underlying settings class or DB field name).

## Local full-stack dev setup

To run both together locally (e.g. for UI work that needs real data):

1. **Backend** (`trieuan-headless/`): point `.env` `DB_*` at a local MySQL, `APP_URL` at whatever port you serve it on (8000 is often already taken by other local Laravel projects on this machine — 8010 was used previously), `FRONTEND_URL` at wherever the frontend is running (`http://localhost:3000`). Run `composer install`, `php artisan key:generate`, import/migrate the DB, `php artisan storage:link` (media won't load without it), `php artisan settings:discover`, then `php artisan serve --port=<port>`.
2. **Frontend** (`trieuan-frontend/`): set `NEXT_PUBLIC_BASE_URL` in `.env` to `http://localhost:<backend-port>/api/v1`, add that host to `images.remotePatterns` in `apps/trieuan/next.config.js` if it isn't already there (otherwise `next/image` 404s on local media), then `pnpm install` and `nx run trieuan:dev`.
3. Each repo's original `.env` (pointing at real staging/production) should be preserved as `.env.production.bak` before overwriting — don't discard real credentials when switching to local values.

A production DB dump imported locally may have an empty/stale `migrations` table even though the actual tables already reflect a recent schema — check `php artisan migrate:status` before blindly running `migrate`; you may need to mark existing migrations (and `database/settings/*` migrations) as already-run instead of re-running `CREATE TABLE`s that already exist.
