Local Setup
This walks you from zero to “bot replies to my messages on LINE in dev” in about 15 minutes once accounts from Prerequisites are ready.
1. Clone
git clone https://github.com/einsze/tinadiet.gitcd tinadiet/projectsThe git repository root is projects/ (not the repo top-level). This is
historical; the monorepo lives one level below.
2. Install backend
cd backendnpm installcp .env.example .envOpen .env and fill in (minimum to run):
SESSION_JWT_SECRET= # generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"LINE_CHANNEL_ID= # from LINE Developers ConsoleLINE_CHANNEL_SECRET=LINE_CHANNEL_ACCESS_TOKEN=LINE_LOGIN_CHANNEL_ID=OPENAI_API_KEY= # sk-proj-...Leave OMISE_* and STRIPE_* empty for now — the backend gracefully
returns 503 OMISE_NOT_CONFIGURED / 503 STRIPE_NOT_CONFIGURED when these
are unset.
Run the backend:
npm run devIt listens on http://localhost:3000. Verify with:
curl http://localhost:3000/healthz# {"status":"ok","service":"tinadiet-backend","env":"development",...}3. Install LIFF
In a separate terminal:
cd ../liffnpm installcp .env.example .envFill the LIFF .env:
VITE_API_BASE_URL=http://localhost:3000VITE_LIFF_ID= # from LINE Developers Console (LIFF tab)Run the LIFF dev server:
npm run devVite serves at http://localhost:5173. Note: the LIFF SDK won’t init
correctly when you open localhost:5173 directly in a normal browser
because it expects to run inside LINE’s webview. To actually exercise the
LIFF, you’ll need to point your LIFF channel’s “Endpoint URL” to a public
tunnel URL (next step).
4. Expose backend via tunnel (for LINE webhook)
LINE’s webhook calls your backend by URL. To receive webhooks during dev, use cloudflared:
cloudflared tunnel --url http://localhost:3000This prints a public URL like https://random-name.trycloudflare.com. Take
that URL and:
- In LINE Messaging API channel → set “Webhook URL” to
https://random-name.trycloudflare.com/webhook/line(note/webhook/line, not just/) - Click “Verify” — should return 200
- Toggle “Use webhook” ON
Now send a message to your dev bot from LINE on your phone — the backend log should show the event.
5. Expose LIFF via tunnel (to test in-LINE)
Open another tunnel for the LIFF Vite server:
cloudflared tunnel --url http://localhost:5173Take the URL and in LINE Developers Console → LIFF tab → edit your LIFF
→ set “Endpoint URL” to https://random-name-2.trycloudflare.com.
Vite needs to know the tunnel hostname is allowed; the LIFF config already
has server.allowedHosts: true for dev.
Now opening LIFF from inside LINE will load your local Vite server. Hot module reload works through the tunnel.
6. Run database migrations
Migrations run automatically when the backend starts (see
backend/src/db/migrate.ts). First run creates backend/data/app.db with
schema versions 0001 through 0007. Verify:
ls -la backend/data/app.dbIf the file isn’t created, check backend logs for migration errors — the
most common cause is a missing parent directory (backend/data/ must
exist; it’s created via .gitkeep).
7. Test the full loop
In LINE on your phone:
- Add your dev bot as a friend
- Open the LIFF (via Rich Menu if set up, or directly via LIFF URL)
- Complete the onboarding profile
- Send a message to the bot like “ผัดกะเพราไก่”
- Bot should reply with parsed food log in Thai
If anything breaks at this stage, check:
- Backend logs (
tsx watchshows all output in real-time) - LINE Messaging API channel “Webhook” tab → “Last delivery” shows status per recent webhook attempt
- Browser DevTools in LIFF (in LINE app: tap ”︙” → “Webview tools”)
8. Optional: enable Omise TEST mode for payment testing
Add to backend/.env:
OMISE_PUBLIC_KEY=pkey_test_...OMISE_SECRET_KEY=skey_test_...OMISE_WEBHOOK_SECRET= # base64 secret from dashboard "Roll secret"Get keys at dashboard.omise.co/test/keys. See
Omise integration for the full setup
including webhook registration.
Restart the backend after editing .env.
Common gotchas
- Backend says
OMISE_NOT_CONFIGURED— that’s fine, expected whenOMISE_SECRET_KEYis empty. Skip if you’re not testing payments. - LIFF blank screen — likely LIFF SDK init failed because endpoint URL doesn’t match tunnel. Re-check LINE Developers Console LIFF endpoint URL.
- Migration errors at startup — usually means an old
app.dbfrom a previous version. Deletebackend/data/app.dband restart to apply fresh. - better-sqlite3 build fails — needs Node 22; check
node -v. If still failing,npm rebuild better-sqlite3.