尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Financial management for restaurants: daily revenue and cost tracking with prime cost, food cost and margin calculated automatically. Next.js, Prisma, PostgreSQL.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Financial management for restaurants. Owners log the day's revenue and costs; the app calculates prime cost, food cost and net margin against the ranges that actually matter in restaurant operations, so the month's result is known during the month rather than weeks later.
Live: https://rest-finance.bruno-dev.xyz Status: private beta, free. Accounts are created on request.
| Layer | Choice |
|---|---|
| Framework | Next.js 14 (App Router), React 18, TypeScript (strict) |
| Database | PostgreSQL 16 on the VPS, accessed through Prisma 7 (@prisma/adapter-pg) |
| Styling | Tailwind CSS, fully CSS-variable driven (light + dark) |
| Auth | Auth.js (NextAuth v5): email and password, optional Google |
| Payments | Stripe (implemented, dormant during the free beta) |
| Hosting | Hetzner VPS, PM2 + nginx + Let's Encrypt |
| CI/CD | GitHub Actions: verify, then deploy over SSH |
| Tests | Vitest |
npm install
cp .env.example .env.local # then fill in the values
npx prisma migrate dev
npm run dev
Runs on http://localhost:3000.
| Script | Purpose |
|---|---|
npm run dev | Development server |
npm run build | prisma generate + production build |
npm start | Serve a production build |
npm test | Vitest |
npx tsc --noEmit | Typecheck |
| Variable | Purpose |
|---|---|
DATABASE_URL | Postgres connection string (pooled) |
DIRECT_URL | Direct connection, used for migrations |
AUTH_SECRET | Signs session cookies. openssl rand -base64 32 |
AUTH_URL | Public origin for Auth.js callbacks. Required behind nginx. |
NEXT_PUBLIC_APP_URL | Public origin, used for metadata and callbacks |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | Optional. Google sign-in. |
STORAGE_DIR | Optional. Where uploads live; defaults to ./storage. |
STRIPE_SECRET_KEY | Optional while billing is dormant |
STRIPE_WEBHOOK_SECRET | Required if Stripe is enabled |
DOCUMENT_SCANNER_API_URL | Optional. Enables invoice scanning. |
Never commit .env or .env.local; both are gitignored.
app/
page.tsx Landing page
dashboard/ Owner app. Server actions live in *-actions.ts
admin/ Platform admin console
api/ Route handlers (exports, scanning, Stripe webhook)
lib/
kpi.ts Financial calculations. Single source of truth.
auth-helpers.ts requireAuth / requireOwner / requireMember
validations.ts Zod schemas for every mutating input
errors.ts toClientError: log internally, return safe messages
translations.ts PT/EN dictionary
prisma/
schema.prisma Data model
migrations/ Applied with `migrate deploy`, never `migrate dev`
deploy/
nginx.conf Server vhost, versioned here
All financial arithmetic goes through lib/kpi.ts. It previously existed but was unused while four call sites reimplemented the same formulas inline and disagreed with each other. Prime cost was reported one way on the dashboard and another way in the PDF. If you need a derived financial figure, add it to lib/kpi.ts with a test rather than computing it at the call site.
Tenant scoping goes through lib/auth-helpers.ts. requireOwner() and requireMember() return a restaurantId that every query must filter on. Never accept a restaurantId from the client. Mutations follow fetch-then-verify: load the row scoped to the caller's restaurant, confirm it exists, then update by id.
Push to main runs CI (typecheck, tests, build). Only if CI passes does Deploy run, which SSHes to the VPS and executes deploy.sh: fetch, npm ci, prisma migrate deploy, build, pm2 startOrReload, then verify the site returns 200.
Required repository secrets:
| Secret | Value |
|---|---|
VPS_HOST | Server address |
VPS_USER | Deploy user |
VPS_SSH_KEY | Private half of a dedicated ed25519 deploy key |
VPS_KNOWN_HOSTS | Output of ssh-keyscan <host> |
The app runs under PM2 as rest-finance on port 3008, behind the nginx vhost in deploy/nginx.conf.
Two scripts, run once each.
1. GitHub secrets (from your machine, with gh authenticated):
bash deploy/setup-github-secrets.sh
Creates a dedicated deploy key if one does not exist, uploads all four secrets, and prints the public key to authorise on the server.
2. Server provisioning (on the VPS, as root):
bash deploy/provision-vps.sh
Creates the database and role with a generated password, clones the repo, builds, starts PM2, obtains a TLS certificate and installs the nginx vhost. Idempotent.
If a vhost already exists but points at another app, the script refuses to overwrite it and prints the switch command instead.
It also checks that port 3008 is free and that Postgres is not listening beyond localhost.
Private and unlicensed. All rights reserved.