Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Recipe costing and menu pricing for the Caloundra Food Precinct venues (Drift Bar, Chiobu, Greedy Gringo's, Gelato Rumba).
Next.js 14 (app router, TypeScript) + Tailwind + Supabase (magic-link auth, Postgres with RLS). All costing data loads once into the browser and every cost, GP and suggested price is computed in memory, so edits and what-ifs are instant.
Scripts: npm run dev, npm run build, npm start, npm run lint, npm test (vitest: costing maths, quantity parser, GP↔price solver, search).檢視完整 README ↗Recipe costing and menu pricing for the Caloundra Food Precinct venues (Drift Bar, Chiobu, Greedy Gringo's, Gelato Rumba).
Next.js 14 (app router, TypeScript) + Tailwind + Supabase (magic-link auth, Postgres with RLS). All costing data loads once into the browser and every cost, GP and suggested price is computed in memory, so edits and what-ifs are instant.
npm install
cp .env.example .env.local # fill in the two values below
npm run dev # http://localhost:3000
| Variable | Where to find it |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | Supabase → Project Settings → API → Project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase → Project Settings → API → anon / public key |
Scripts: npm run dev, npm run build, npm start, npm run lint, npm test (vitest: costing maths, quantity parser, GP↔price solver, search).
Sign-in is by email magic link (signInWithOtp). The link returns to /auth/callback, which exchanges the code for a session and redirects to the page the user was heading to.
In Supabase → Authentication → URL Configuration:
https://<vercel-domain>https://<vercel-domain>/auth/callbackhttp://localhost:3000/auth/callback (for local dev)https://*-<team>.vercel.app/auth/callback works with wildcards)Without the redirect URL entry the magic link will land on the Site URL without a code and the user stays logged out.
middleware.ts requires a Supabase session for every route except /login and /auth/callback.cost_* table only allows users whose email is in cost_allowed_users (see supabase/schema.sql for the policy pattern). A signed-in user who is not on the list sees "Your email isn't on the access list — ask SPORK".The app is built against the cost_* tables in the public schema. supabase/schema.sql is a reference copy of the shape (tables, price-log trigger, RLS policies) — the production project already has these, so treat the file as documentation rather than a migration to run.
Important behaviours the app relies on:
cost_ingredients writes to cost_price_log and sets previous_price / last_price_update whenever pack_price changes. The app never inserts log rows itself; it only updates pack_price (and optionally source as the note for that change).cost_portal_prices is read-only reference data scraped from supplier portals. The app shows the latest batch per supplier and can pre-fill a new ingredient from a row.All in lib/costing.ts (pure functions, tested in tests/costing.test.ts):
pack_price if GST-free; pack_price / (1 + gst) if priced inc GST; otherwise pack_price.(exGST − rebate) / pack_size / yield_pct.ceil(cost / (1 − target) × (1 + gst) / round_to) × round_to (rounds up to the nearest 50c by default).Apple-HIG style UI (system font, grouped inset lists, sheets, light/dark via prefers-color-scheme). The accent colour follows the selected venue (CSS variables set from <html data-venue>; see app/globals.css). Phones get a bottom tab bar (Home · Recipes · Ingredients · Search · More); ≥1024px gets a sidebar and a ⌘K / Ctrl+K (or /) command palette.
| Route | What it does |
|---|---|
/ | Home: average GP (simple mean of active priced items) with Food · Drinks split, a card per venue, and at most two "Needs attention" rows. |
/recipes | Menu items / Preps, venue chips, fuzzy search, category chips, sort menu. /items and /preps redirect here. |
/items/[id], /preps/[id] | One-screen recipe editor with autosave (debounced ~700 ms), smart "Add ingredient — 180g chicken thigh" entry (parser in lib/parse-qty.ts), linked sell price ↔ GP (lib/solver.ts), undo on line removal. |
/ingredients, /ingredients/[id] | List with 30-day price movement; detail with big "Update price" sheet that shows the GP impact on every recipe using it, price history, Advanced fields. |
/search | Global typo-tolerant search (lib/search.ts) across recipes, preps, ingredients and the supplier catalogue; recent items when empty. |
/alerts, /specials, /portal-prices, /settings, /more | Full alert lists, specials calculator cards, supplier catalogue browse ("Add as ingredient"), settings and targets, More menu. |
The venue choice is kept in ?venue=slug and localStorage. The last full dataset is cached in localStorage (precinct-cache-v1) and painted instantly on open, then refreshed from Supabase in the background.
NEXT_PUBLIC_DEMO=1 swaps the Supabase client for an in-memory stand-in (lib/supabase/demo-client.ts) fed by /api/demo-data, which reads .demo/data.json from disk and returns 404 unless the flag is set. Middleware skips auth in demo mode. .demo/ is gitignored, .vercelignored and excluded from output tracing — it holds client pricing data and must never be deployed. Never set NEXT_PUBLIC_DEMO on Vercel.
NEXT_PUBLIC_DEMO=1 npm run build && NEXT_PUBLIC_DEMO=1 npm start -- -p 3100
node .demo/shoot.mjs # Playwright screenshots → .demo/shots/
node .demo/flow.mjs # smoke test of the new-recipe / autosave / undo flows
/auth/callback URLs to Supabase as described above.