WallpaperMachine
당신이 사랑하는 배경화면, 맥에서 새롭게 만나보세요
Platform for interactive city tours via quests
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Quest City Tour is a mobile-first web app for guided city quests. An admin describes landmarks, games and teams in YAML files. Each team gets a private link. Teams open the link on a phone and work through a series of riddles:
Teammates on several phones share one run: if one phone solves a task, the others move on and show a "teammate" toast.
The backend is FastAPI + SQLAlchemy (PostgreSQL, or SQLite for a quick local run) with blob storage
for photos and pictures (Azure Blob / Azurite, or plain files). The frontend is a React + Vite SPA.
The specs are in specs/, the design mocks in frontend-mocks/, and the look-and-feel proposals
(directions, variants, self-hosted fonts) in design/ — open design/index.html in a browser.
uv (Python package and interpreter manager)uv installs it for you). If no 3.12 interpreter can run on your machine, use
Python 3.13 instead: uv sync --python 3.13 (the code stays 3.12-compatible)../scripts/dev.sh
Runs the no-Docker fallback end to end in one foreground
terminal: it writes backend/.env (SQLite + local file storage, with a seeded
[email protected]) on first run, installs dependencies,
migrates, runs sync-config (which prints the team game links), then starts
uvicorn and the Vite dev server together. The startup summary also prints the
admin panel URL and how to sign in for the active admin auth mode. Ctrl-C stops
both; every output line is tagged [backend] or [frontend] so the interleaved
logs stay readable.
Each run starts from a fresh SQLite database; --keep-db keeps the existing one.
--auth password runs the admin panel with e-mail and password sign-in for this
run (ADMIN_AUTH_PROVIDER=password). Unless you set ADMIN_BOOTSTRAP_EMAIL and
ADMIN_BOOTSTRAP_PASSWORD yourself, it seeds [email protected] with the
throwaway password dev-password-123. --auth entra also needs the
ADMIN_ENTRA_* settings. Without --auth, the mode comes from the environment or
backend/.env (the default is the dev magic link). The script checks the
required settings before the setup steps run.
Start PostgreSQL 16 and Azurite from the repo root:
docker compose up -d
Set up and start the backend:
cd backend
cp .env.example .env
uv sync
uv run alembic upgrade head
uv run sync-config
uv run uvicorn questtour.main:create_app --factory --reload
sync-config reads CONFIG_DIR (default config, relative to backend/; the sample files live in
backend/config/).
sync-config validates the YAML files, writes new tokens into teams.yaml, loads everything into the
database and prints one game link per team, e.g.
Game links:
The Explorers — Sofia Old Town Quest: http://localhost:5173/play/<token> (new)
Start the frontend in a second terminal:
cd frontend
npm install
npm run dev
Open the printed link (the Vite dev server runs on port 5173 and proxies /api to the backend on
port 8000; set DEV_API_TARGET to proxy somewhere else).
Build the SPA and let FastAPI serve it:
cd frontend
npm run build # creates frontend/dist
cd ../backend
Set these in backend/.env (or as environment variables):
STATIC_DIR=../frontend/dist
PUBLIC_BASE_URL=http://localhost:8000
Re-run uv run sync-config so the printed links use the new base URL, then start the server:
uv run uvicorn questtour.main:create_app --factory --port 8000
Open http://localhost:8000/play/<token>.
Without Docker, use SQLite and local file storage. Put this in backend/.env:
DATABASE_URL=sqlite:///./dev.db
HOST_ID=default
PUBLIC_BASE_URL=http://localhost:5173
STORAGE_BACKEND=local
LOCAL_STORAGE_DIR=.storage
CONFIG_DIR=config
Then run the same commands as in the Docker path (uv sync, uv run alembic upgrade head,
uv run sync-config, uv run uvicorn ...). Photos and pictures are written under
backend/.storage/. If Python 3.12 is not available, run uv sync --python 3.13 first.
For the production-like variant, also set STATIC_DIR=../frontend/dist and
PUBLIC_BASE_URL=http://localhost:8000.
The admin configuration is three YAML files in the config directory plus an images/ folder.
landmarks.yaml — landmarks: list. Each has id, name, task (riddle text),
accepted_answers, optional hint1, hint2, tourist_info, and optional pictures
task_picture / tourist_info_picture (paths relative to the config directory, e.g.
images/task-domes.svg). accepted_answers[0] is the answer shown when a team reveals it.games.yaml — games: list. Each has id, name, time_zone, max_duration_minutes,
reveal: { attempts, minutes, penalty_minutes } (N attempts / X minutes before reveal unlocks,
P penalty minutes), an intro text and tasks: (ordered landmark ids).teams.yaml — teams: (id, name, participants) and assignments: (team, game,
valid_from, valid_until, exit_message). token fields are added by sync-config. An optional
service: block (team, name) defines the service (test) team: sync-config writes one link per game
under service.tokens.Timestamps (valid_from, valid_until) must be quoted ISO-8601 strings, e.g.
"2026-10-01T00:00:00". Without an offset they are read in the game's time zone.
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗