Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未收集仓库信息。
尚未检测到更新。GitHub 发布版本后会显示在这里。
A simple, focused booking management system for restaurants, bars, cafes and more. Set up multiple restaurants per instance, and use your own email address to communicate with your customers. Customers get a simple, cross platform, mobile friendly UI to book tables securely. Self host and cloud friendly.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A self-hosted, zero-dependency restaurant booking system. Customers browse restaurants, hold tables in real-time, and book instantly. Admins manage reservations, tables, floor sections, branding, and booking pauses from a dedicated dashboard - all from a single Docker Compose command with no external services required beyond optional SMTP.
Documentation · Live Demo - admin: [email protected] / password · resets every 2 hours, feel free to play around and change anything
The Restaurant business has changed. Indie restaurants run on razor thin margins, and the cost of SaaS booking platforms only adds to the burden. Users don't want to install another app, give up their phone number to the cloud, or create another account to remember. OpenResto was designed to be as simple as possible for both customers and restaurant owners, while still being fully self-hosted, secure and customisable. Owners can manage bookings easily without friction. Customers book instantly without giving up any personal information, and can easily save their reservations to their calendar. Nothing in between.
Everything below is the real app, recorded with Playwright against the live demo and its seed dataset. The first set frames each flow with step captions; the plain recordings follow underneath.
Browse the locations, pick a party size, a date and a time, and the table is held while the guest types their details. Confirming lands on a page with calendar export, reminders and directions.
Sign in to the dashboard, open the day's timetable and a booking's details, switch to the service view, scroll a location's policies, hours and tables, then edit the brand with the live preview updating as you type.
The same site on a phone, nothing to install.
Desktop
Phone and tablet
| Layer | Technology |
|---|---|
| Backend | ASP.NET Core 10, C#, Entity Framework Core, SQLite |
| Frontend | React Native (Expo Router) — web + mobile from one codebase |
| Auth | JWT Bearer Tokens (HS256), encrypted HttpOnly cookies |
| Image gen | Magick.NET-Q8-AnyCPU (cross-platform, no native deps) |
| MailKit (SMTP) | |
| Infra | Docker Compose, Nginx reverse proxy |
| Security CI | OWASP ZAP API scan on every push (OpenAPI-driven, rules in .github/.zap-rules.tsv) |
| Code mappers | Mapperly (source-gen, zero reflection) |
Download the docker-compose.yml from the latest release, create a .env file based on .env.example, then:
docker compose up -d
Pre-built linux/amd64 and linux/arm64 images are pulled from GHCR — no build step, works on Pi/NAS boxes out of the box. The backend applies any pending database migrations automatically before accepting traffic.
The full self-hosting guide (install, configuration, HTTPS, email, upgrading, troubleshooting) is at docs.openres.to. For backup and restore, see the backup and restore guide. To drive the admin API from your own scripts with an API key, see API guide. To publish the guest booking app to the Play Store or App Store under your own developer account, see native app guide.
For local development:
docker compose up
Prerequisites: .NET 10 SDK, Node.js 20+
# run from the repo root
npm run dev
The SQLite database is created automatically on first run. Since this is not running via docker, Images and other media will not work, however HMR is enabled.
Set via environment variables or appsettings.json:
| Variable | Description | Default |
|---|---|---|
JWT_KEY | JWT signing key (min 32 chars) | Dev key in appsettings |
CONNECTION_STRING | SQLite connection string | Data Source=./openresto.db |
CORS_ORIGINS | Comma-separated allowed origins | localhost ports |
Admin:Email | Default admin email | Set in appsettings |
Admin:Password | Default admin password | Set in appsettings |
Optional integrations are configured the same way and stay switched off until they are: Apple
and Google Wallet passes (Wallet__Apple__*, Wallet__Google__*) and guest booking reminders
(Vapid__* on the web, an EAS project on native) each hide their own button while unset.
Running from a clone, put them in OpenRestoApi/appsettings.Local.json, which the backend
loads when present and .gitignore keeps out of commits — see
native app guide for the issuer setup either needs.
The API Keys settings screen links out to the CLI package, the HTTP API guide and the source
repository. Those three URLs default to this project's and are overridable per deployment with
OPENRESTO_CLI_PACKAGE_URL, OPENRESTO_API_DOCS_URL and OPENRESTO_REPOSITORY_URL (or the
Links:CliPackage, Links:ApiDocs and Links:Repository configuration keys) — useful if you
run a fork with its own client or docs.
| Variable | Description | Default |
|---|---|---|
EXPO_PUBLIC_API_URL | Backend API base URL | http://localhost:5062 |
The VAPID key variables are also required for push notification support, but are optional for developing.
# Backend tests
dotnet test
# Frontend tests (100% coverage target)
cd openresto-frontend && npm test
# Full frontend coverage report
cd openresto-frontend && npm test -- --coverage
Note: VSCode may not pick up on the Jest config, unless you use the command palette to activate all the test runners.
ConcurrentDictionary. The holdId must be echoed back at booking time, preventing any other customer from snatching the same table during checkout. Holds auto-expire and are released atomically if the customer changes their selection.Lunch, Dinner, or Off-Peak using restaurant industry data (Toast/Square/Yelp benchmarks). The frontend groups available slots into labelled pill tabs so customers can quickly jump to the time period they want.BookingsPausedUntil before returning slots.DateTime values are stored in UTC. Restaurant-local open/close hours and slot generation are computed using the restaurant's IANA timezone (America/New_York, Europe/London, …), so the availability calendar is always correct regardless of where the server runs.bookings, locations, tables, brand, users, audit, guests) — a key without the guests scope reads bookings with customer identity redacted, so a POS or marketing integration never sees guest contact info. openresto-cli drives the same admin API from scripts and cron jobs: named profiles, --json on every command, and confirmation gates on destructive operations. Every key request lands in the activity trail under the key's name.BrandContext.GET /api/brand/pwa-icon.svg returns an SVG with the brand-colored background and white icon on the fly. GET /api/brand/pwa-icon-{192|512}.png rasterizes it with Magick.NET (cross-platform, no ImageMagick apt package needed) for PWA manifest compliance./openapi/v1.json) to discover all endpoints automatically. Ignored rules are tracked in .github/.zap-rules.tsv.BookingRef code; no email verification loop.npm run native:init reads your brand, eas build does the rest (native app guide).npm run dev starts the .NET backend (hot reload) and Expo frontend concurrently.Database.Migrate() before accepting traffic; upgrading is docker compose pull && docker compose up -d.linux/amd64 and linux/arm64 images published to GHCR on every semver tag; Pi/NAS users get native binaries.Update CHANGELOG.md — add a ## [x.y.z] - YYYY-MM-DD section at the top of the file.
Merge to main — all CI must be green before tagging.
Tag and push:
git tag v1.0.0
git push origin v1.0.0
That's it. The release.yml workflow triggers automatically and:
linux/amd64 + linux/arm64 Docker images for the backend, frontend, and nginx proxyghcr.io/karanshukla/openresto-{backend,frontend,nginx}:v1.0.0 (and :latest)[x.y.z] section from CHANGELOG.md as the release notesdocker-compose.yml (with the exact image tag baked in) as a downloadable release asset — this is what self-hosters downloadMIT, do what you want with it