Qalbwise lets you type anything on your mind and instantly discover what the Quran says about it — accurately, contextually, and personally.
Frontend (apps/web)
- React 19 + TypeScript
- Vite — build tool
- Tailwind CSS v4 — styling
- shadcn/ui — component library
- TanStack — Router, Query
Backend (apps/api)
- FastAPI — API framework
- Alembic — database migrations
- Celery + Redis — background tasks queue
- Ruff — linter & formatter
- Loguru — logging
- Scalar — API docs
- Quran Foundation OAuth2 — user authentication via OAuth 2.0 Authorization Code + PKCE
Shared (packages/core)
- openapi-typescript — generates TypeScript types from FastAPI's OpenAPI schema
- openapi-fetch — fully typed API client
Monorepo & Tooling
- Moon — task runner & monorepo orchestration
- Proto — toolchain version management
- pnpm — JavaScript package manager
- uv — Python package manager
- Biome — JavaScript/TypeScript linter & formatter (root-level, shared across all JS/TS projects)
- Lefthook — Git hooks
- commitlint — commit message linting
Install Proto — it manages all other tool versions automatically:
curl -fsSL https://moonrepo.dev/install/proto.sh | bashProto will handle Node.js, pnpm, Python, and Moon based on .prototools.
git clone https://github.com/qalbwise/app.git qalbwise
# Or if you have SSH access
git clone git@github.com:qalbwise/app.git qalbwisecd qalbwise# Install JS dependencies
pnpm install
# Install Python dependencies
uv sync --project apps/api# Start the frontend dev server
moon run web:dev
# Start the backend dev server
moon run api:dev
# Start both simultaneously
moon run web:dev api:dev
# Start the Celery worker
moon run api:workerThe frontend runs at http://localhost:3000 and the backend at http://localhost:8000.
API docs are available at http://localhost:8000/scalar.
my-project/
├── .moon/
│ ├── workspace.yml # Project locations & Moon config
│ └── toolchains.yml # Language & tool versions
├── apps/
│ ├── web/ # React frontend
│ │ ├── src/
│ │ │ ├── modules/ # Feature modules (components + hooks)
│ │ │ ├── routes/ # TanStack file-based routes
│ │ │ └── lib/
│ │ │ └── api.ts # Singleton API client (from @repo/core)
│ │ └── moon.yml
│ └── api/ # FastAPI backend
│ ├── app/
│ │ ├── api/ # Routes & serializers (Pydantic schemas)
│ │ ├── modules/ # Business logic (services)
│ │ ├── models/ # SQLAlchemy models
│ │ └── core/ # Settings, logging, celery
│ ├── alembic/ # Database migrations
│ └── moon.yml
├── packages/
│ └── core/ # Shared typed API client
│ └── src/
│ ├── api/ # Feature API methods
│ ├── client.ts # createApi() factory
│ ├── schema.d.ts # Auto-generated from /openapi.json (gitignored)
│ └── index.ts
├── .prototools # Pinned tool versions
├── biome.json # Shared Biome config (root-level)
├── commitlint.config.ts # Commit message rules
├── docker-compose.yml # Local/staging services
├── lefthook.yml # Git hook definitions
├── package.json
└── pnpm-workspace.yaml
moon run web:dev # Dev server
moon run web:build # Production build
moon run web:lint # Lint with Biome
moon run web:format # Format with Biome
moon run web:check # Lint + format + fix with Biome
moon run web:typecheck # TypeScript type checkingmoon run api:dev # Dev server
moon run api:lint # Lint with Ruff
moon run api:format # Format with Ruff
moon run api:migrate # Run Alembic migrations
moon run api:worker # Start Celery workermoon run core:generate # Regenerate TypeScript types from OpenAPI schema
moon run core:typecheck # Type check packages/coremoon run :lint # Lint all projects
moon run :format # Format all projects
moon run :check # Check all JS/TS projectsTypeScript types in packages/core are auto-generated from FastAPI's OpenAPI schema. Run this whenever you change a Pydantic schema:
# API must be running
moon run core:generate# Apply all pending migrations
moon run api:migrate
# Create a new migration (from apps/api)
cd apps/api
uv run alembic revision --autogenerate -m "add users table"Always import new models in alembic/env.py for autogenerate to detect them.
Create a .env file in the project root with the following variables:
| Variable | Description |
|---|---|
VITE_API_URL |
Backend API base URL |
DATABASE_URL |
PostgreSQL connection string |
REDIS_URL |
Redis connection string |
SECRET_KEY |
Application secret key |
POSTGRES_USER |
DB user (used by Docker Compose) |
POSTGRES_PASSWORD |
DB password |
POSTGRES_DB |
DB name |
OPENAI_API_KEY |
OpenAI API key |
OPENAI_BASE_URL |
OpenAI-compatible base URL |
VITE_GOOGLE_CLIENT_ID |
Google OAuth client ID (frontend) |
GOOGLE_CLIENT_ID |
Google OAuth client ID (backend) |
VITE_QF_CLIENT_ID |
Quran Foundation client ID (frontend, feature flag) |
QF_CLIENT_ID |
Quran Foundation OAuth2 client ID |
QF_CLIENT_SECRET |
Quran Foundation OAuth2 client secret (server-side only) |
QF_AUTH_BASE_URL |
QF OAuth2 base URL (https://oauth2.quran.foundation / https://prelive-oauth2.quran.foundation) |
QF_API_BASE_URL |
QF User API base URL (https://apis.quran.foundation / https://apis-prelive.quran.foundation) |
QF_REDIRECT_URI |
Callback URL registered with QF (e.g. https://api.qalbwise.app/auth/qf/callback) |
FRONTEND_URL |
Frontend origin for OAuth callback redirect |
Both the API and frontend load environment variables from the root .env file:
- API:
apps/api/app/core/settings.pyloads fromROOT_DIR / ".env" - Frontend: Vite configured with
envDir: "../../"invite.config.ts
Docker Compose reads from the root .env automatically.
See CONTRIBUTING.md for the full contribution guide — coding standards, development workflow, commit conventions, PR process, and everything you need to contribute effectively.
Quick reference: this project enforces Conventional Commits with type(scope): description. The pre-commit hook automatically lints and formats staged files; the commit-msg hook validates the message format.
MIT — Copyright (c) 2026 Qalbwise