预约受付魔法

把时间选择、内容录入、确认、变更与取消当成同一套受理结构

Prototype

预约、会谈、施术、访问、课程、咨询等受理,可以从时间选择到变更与取消都放在同一条结构里。

预约受付魔法

分类
基盤魔法
对应的抽象魔法
予約受付魔法フォーム生成魔法カレンダー連携魔法

预约、会谈、施术、访问、课程、咨询等受理,可以从时间选择到变更与取消都放在同一条结构里。

它让受理、空位判断、变更记录与通知留在同一结构里,而不是散落在电话、聊天和手工跟进中。

你是 Codex。请在 Cloudflare 上构建一个名为 “予約受付魔法 / Booking Intake Spell” 的 production-shaped prototype。

你的任务不是写概念页。你的任务是实现一个真正可运行的 reservation intake system prototype,把 booking、confirmation、rescheduling、cancellation 视为同一条统一的 intake flow。

不要提出澄清问题。自行做出合理决定,并端到端实现完整原型,保证代码清晰、注释清楚、具备类型安全、输入校验以及可部署性。

重要执行约束:
- 不要停在 scaffolding
- 不要只输出计划
- 不要把 core routes 留空
- 不要用 mock JSON 代替主 booking flow 的真实逻辑
- 不要跳过 D1 migrations
- 不要跳过 tests
- 不要重复询问上面已经明确写出的需求
- 如果出现 tradeoff,选择最简单但仍满足 acceptance criteria 的实现路径
- 完成后,简要总结 architecture、routes、env vars、以及 local run/deploy steps

Project goal

构建一个可复用的 booking intake system,用于 reservations、interviews、visits、consultations、lessons、treatments 以及类似的 appointment-based workflows。

系统必须支持:
1. public intake page
2. date/time selection
3. input form
4. availability check
5. provisional acceptance or confirmation
6. modification flow
7. cancellation flow
8. notification abstraction
9. optional waitlist-ready architecture
10. staff-only admin view

Core product concept

把 booking、interview scheduling、treatment booking、lesson booking、visit booking、consultation intake 视为同一种 parent structure:
- 选择 date/time
- 输入 intake details
- 根据 rules 做 validate
- 创建 booking record
- 后续允许 reschedule/cancel
- 所有 actions 保留在同一条 history thread 中
- 在概念上不要把 notification 与 record history 拆开

如有帮助,可在代码注释与命名中使用以下 framing:
- Intake Familiar = validates input and intake rules
- Schedule Familiar = checks time, duration, staff/resource constraints
- Notification Familiar = sends confirmation, reschedule, cancellation messages

Fixed stack

除非绝对不可能,否则严格使用以下技术栈:
- Frontend: React + Vite + TypeScript
- Styling: simple clean CSS or CSS Modules, no UI library required
- Backend API: Cloudflare Workers
- Database: Cloudflare D1
- Async jobs: Cloudflare Queues-ready abstraction。这个 prototype 可以先实现 synchronous fallback,但结构上必须允许后续接入 async delivery
- Auth for admin: simple Cloudflare Access compatible header-based stub 或 lightweight password gate abstraction,让 admin route 明确具备 staff-only ready 结构
- Email delivery abstraction: 实现 provider interface,默认使用 development log provider
- Calendar integration abstraction: 实现 provider interface,默认使用 no-op/mock provider
- Validation: Zod
- Testing: 至少使用 Vitest 覆盖 logic 与 validation
- Dates/times: 使用稳健方案,timestamp 以 UTC 存储,展示层支持 local timezone

Architecture

在一个 repository 内使用 monorepo 或清晰的 two-app structure:
- apps/web = React public UI and admin UI
- apps/api = Cloudflare Worker API
- packages/shared = shared types, validation schemas, utilities

如果选择更简单的 layout 也可以,但 UI、API、shared domain logic 的边界必须清晰。

Functional requirements

1. Public booking flow

构建一个 public page,让用户可以:
- 选择 service type 或 intake category
- 选择 date
- 查看 available time slots
- 选择 time slot
- 填写 required fields
- 可选填写 attendee count
- 如果 service 允许 variable duration,则可选填写 duration
- 提交 booking

intake form 需要支持以下字段:
- name
- email
- phone optional
- booking type/category
- date
- start time
- duration minutes
- party size or attendee count
- note/message
- optional staff preference
- optional location or mode field such as in-person / phone / online
- consent checkbox if needed

2. Unified booking lifecycle

每个 booking 必须具备如下 lifecycle status:
- pending
- confirmed
- cancelled

每个 booking 还必须保留如下 event history:
- created
- availability_checked
- confirmed
- rescheduled
- cancelled
- notification_sent
- notification_failed

Reschedule 与 cancel 必须作用在同一条 booking identity/history chain 上,不能通过静默替换 rows 来实现。

3. Availability model

实现一个 availability model,支持:
- opening hours or bookable windows
- slot duration
- buffer before/after
- max concurrent bookings
- optional staff/resource constraint
- blackout/unavailable times
- lead time rules
- cutoff rules for same-day or late bookings

在这个 prototype 中:
- 定义一个或多个 bookable services
- 定义 weekly availability rules
- 定义 blackout support
- 定义 capacity support
- 实现真实的 slot generation
- 在 API level 拒绝 invalid 或 conflicting bookings

4. Modification and cancellation

每个 booking 必须获得:
- a public booking reference
- a secure management token

通过 management token,让 guest 可以:
- 查看 booking details
- reschedule booking
- cancel booking

构建如下 pages:
- /manage/:reference?token=...
或类似结构

Reschedule flow 必须:
- 重新检查 availability
- 保留 history
- 通过 abstraction 发送 notification

Cancellation flow 必须:
- 将 booking 标记为 cancelled
- 保留 history
- 通过 abstraction 发送 notification

5. Notifications

实现带 provider interface 的 notification abstraction:
- sendBookingCreated
- sendBookingConfirmed
- sendBookingRescheduled
- sendBookingCancelled

在 development mode 中:
- 实现一个 logging provider,把 payload 写到 console,并可选将 notification log row 存入 D1

不要把某个 email vendor 深度硬编码到 domain logic 中。
保持 provider 可替换。

6. Calendar integration abstraction

实现 calendar provider interface,方法包括:
- checkConflicts
- createEvent
- updateEvent
- cancelEvent

对于这个 prototype:
- 默认使用 mock/no-op provider
- 结构上允许以后接入 Google Calendar 或其他 provider,而不需要重写 domain

7. Admin UI

构建一个 staff-only admin area,可以:
- list bookings
- 按 date/status/category 过滤
- inspect booking details
- inspect booking history
- 必要时手动 confirm pending bookings
- 查看 notification log status
- 查看 availability configuration summary

不要过度构建。保持 usable、clean。

8. Waitlist-ready design

你不需要完整实现 waitlist behavior,但 schema 与 domain design 必须允许未来支持:
- no slot available -> waitlist request
- slot opens later -> re-notify candidate

在合适位置加入 TODO markers。

Domain rules

使用合理默认规则:
- bookings must be in the future
- bookings cannot be created inside cutoff window
- duration must match service constraints
- attendee count must be within service constraints
- selected slot must still be available at commit time
- reschedule cannot move cancelled booking
- cancel cannot cancel already cancelled booking
- public manage token must be required for guest self-service actions

至少创建 2 个 example services:
1. interview
2. consultation

Example defaults:
- interview: fixed 30 minutes, attendee count 1, weekdays only, morning-heavy slots
- consultation: fixed 60 minutes, attendee count 1 to 4, broader availability

如有帮助,可以加入第三个 example,例如 visit 或 lesson。

Data model

设计并实现 D1 schema,至少包含以下 tables:

services
- id
- slug
- name
- description
- duration_minutes_default
- duration_minutes_min nullable
- duration_minutes_max nullable
- attendee_min
- attendee_max
- requires_manual_confirmation boolean
- is_active
- created_at
- updated_at

availability_rules
- id
- service_id nullable if global
- weekday
- start_minute
- end_minute
- slot_interval_minutes
- buffer_before_minutes
- buffer_after_minutes
- capacity
- timezone
- is_active
- created_at
- updated_at

blackouts
- id
- service_id nullable
- starts_at
- ends_at
- reason
- created_at

bookings
- id
- reference_code
- manage_token_hash
- service_id
- status
- customer_name
- customer_email
- customer_phone nullable
- attendee_count
- requested_timezone
- starts_at
- ends_at
- note nullable
- preferred_staff nullable
- mode nullable
- created_at
- updated_at
- cancelled_at nullable

booking_events
- id
- booking_id
- event_type
- actor_type
- payload_json
- created_at

notification_logs
- id
- booking_id nullable
- notification_type
- provider
- recipient
- status
- payload_json
- error_message nullable
- created_at

如果以后需要 supporting tables for staff/resources,可以追加,但不要让 first prototype 不必要地膨胀。

Security

实现以下安全实践:
- 所有输入都使用 Zod 校验
- 若能避免,不要公开 raw internal IDs
- 只保存 manage token hash,不保存明文 token
- 安全地 verify manage token
- 用清晰的 auth middleware stub 保护 admin API/routes
- 对所有 string inputs 做 sanitize 与长度边界控制
- 返回清晰但不过度暴露内部细节的 error messages

API design

以 JSON API 形式实现大致如下 endpoints:

Public:
GET /api/services
GET /api/availability?service=...&date=YYYY-MM-DD&timezone=...
POST /api/bookings
GET /api/bookings/manage/:reference?token=...
POST /api/bookings/manage/:reference/reschedule
POST /api/bookings/manage/:reference/cancel

Admin:
GET /api/admin/bookings
GET /api/admin/bookings/:reference
POST /api/admin/bookings/:reference/confirm
GET /api/admin/availability-summary

可以调整命名,但必须保留这些能力。

Frontend pages

至少构建这些页面:
- / = concise landing page for the prototype
- /book = intake entry
- /book/:serviceSlug optional deep-link service booking page
- /manage = management entry page where user pastes reference + token, or redirect helper
- /manage/:reference = booking detail/manage page
- /admin = admin bookings page
- /admin/bookings/:reference = admin booking detail page

UX requirements

UI 必须:
- clean
- responsive
- minimal
- professional
- legible on mobile
- not visually bloated

booking flow 应该呈现为:
Step 1. Choose service
Step 2. Choose date/time
Step 3. Enter details
Step 4. Review and submit
Step 5. Confirmation with management link

reschedule/cancel screens 应该 simple、calm。

文案可以 bilingual-ready,但如果 strings 已经集中管理,则 prototype 只实现 English 也可接受。
如果能在不拖慢开发的前提下干净地支持 Japanese labels,也可以支持。

Seed/demo data

使用以下内容 seed D1:
- at least 2 services
- weekly availability rules
- 1 blackout example
- a few example bookings for admin testing

Developer experience

提供:
- clear README
- local setup instructions
- D1 migration instructions
- Wrangler configuration
- sample .dev.vars or environment variable documentation
- scripts for dev, test, build, and deploy

Environment variables

定义并文档化如下 env vars:
- BOOKING_BASE_URL
- ADMIN_SHARED_SECRET or equivalent stub
- NOTIFICATION_PROVIDER
- CALENDAR_PROVIDER
- DEFAULT_TIMEZONE

如果 provider abstraction 需要,也可加入这些 placeholders:
- RESEND_API_KEY
- GOOGLE_CLIENT_EMAIL
- GOOGLE_PRIVATE_KEY
- GOOGLE_CALENDAR_ID

但必须保证没有 external providers 时 prototype 也能运行。

Implementation guidance

booking logic 的 correctness 优先于视觉花哨。
slot availability 必须在服务器端生成,而不是只在客户端生成。
在 booking creation 时,必须在 API write path 中执行 final conflict check。
domain logic 应放在 reusable modules 中,而不是直接塞进 route handlers。
代码应保持 readable,避免炫技。

Tests

至少加入以下 tests:
- slot generation
- blackout exclusion
- capacity/conflict rejection
- booking creation validation
- reschedule validation
- cancellation rules
- manage token verification

Acceptance criteria

只有满足以下全部条件时,prototype 才算 complete:
1. A guest can open the public booking page
2. A guest can choose a valid slot
3. A guest can submit a booking
4. A booking record is stored in D1
5. A booking history trail is stored
6. A guest receives a management link/token in the response flow
7. A guest can use the management route to reschedule
8. A guest can use the management route to cancel
9. Availability is revalidated server-side during create/reschedule
10. Admin can list and inspect bookings
11. Notification abstraction exists and logs delivery attempts
12. Codebase is deployable to Cloudflare with documented steps
13. Tests run successfully

Output expectations

产出必须是完整 codebase,而不是 snippets。

同时包括:
- D1 schema/migrations
- seed script or seed SQL
- README
- example screenshots not required
- core flows 不能只留下 placeholder “TODO app” skeletons

Tone and naming

在代码内部可以使用 practical English naming。
在 README 与 landing page 中,把这个系统描述为:
“予約受付魔法 / Booking Intake Spell”

landing page 需要体现以下 product meaning:
- booking, interview, treatment, visit, lesson, and consultation intake handled in one structure
- date selection, input, confirmation, reschedule, and cancellation treated as one reception flow
- can later connect waitlist, reminder, prefill form, and notification extensions

Landing page content guideline

创建一个 concise landing page section structure,可参考以下 ideas:
- What spell it is
- What it can do
- Why it is useful
- Spell structure
- Familiars
- Grimoires
- Reproduction conditions
- Verification status

但不要让它只是装饰页。实际可运行的 booking flow 必须存在,并且要从 landing page 链接进入。

Final instruction

把它实现成一个 reusable parent spell,用于未来派生 vertical-specific booking systems。
优先考虑 extensibility、clarity、operational realism,而不是 hype。
交付一个真正可运行的 Cloudflare-native prototype。

Intake Familiar

角色
接收申请内容,并根据受理规则判断是否可接受。

Schedule Familiar

角色
检查时间、时长、指定资源与容量约束。

Notification Familiar

角色
向相关方返回确认、变更与取消通知。

Frontend

  • 公开受理页面 UI
  • 时间与内容输入表单

Backend

  • 受理 API
  • 空位与规则判定逻辑

DB

  • 受理记录
  • 空位或时间段记录

认证

  • 可选 staff-only 管理端权限

通知

  • 确认通知
  • 变更与取消通知

外部 API

  • calendar integration
  • 邮件发送抽象层

Workers

  • 异步通知或重算任务

Smartphone or PC

供申请人打开受理流程并提交内容。

受理对象定义

需要先定义什么可以预约、哪些字段必填、以及受理条件。

时间与容量模型

需要有日期、时间、时长、指定资源、变更与取消规则。

通知路径

需要 email 或消息渠道来发送确认与变更通知。

验证状态
Prototype

验证说明
这个页面现在是预约受理的抽象父咒文。具体部署可以存在,但这个页面本身只定义可复用的 intake structure。

更新日
2026-04-11

发布日期
2026-04-09

未实证原因

具体使用例与 deployment URL 会作为独立页面单独发布,而不是混在抽象父咒文里。

补充说明

  • 面向诊所、美容、教育、住宿等行业的具体使用例可以后续单独追加。