YapHub — Complete Setup Guide
This is the single canonical setup reference for Yappa Knowledge Hub. Use it for local development, onboarding, and copying into Notion.
System overview
YapHub has three runtime components:
| Component | Stack | Port | Role |
|---|---|---|---|
| Symfony backend | PHP 8.2, Symfony 7 | 8001 | REST API, SQLite, Notion sync, AI summaries |
| Slack bot | Node.js 18+, TypeScript, Bolt SDK | 4000 (Socket Mode), 4001 (Express API) | Slack UI, events, digest delivery endpoint |
| Notion | 4 databases via Notion API | — | Collaborative storage and sync target |
Slack users
↓
Slack Bot (:4000 Socket Mode)
↓ HTTP (Bearer token)
Symfony Backend (:8001 /api/*)
↓ ↓
SQLite (local cache) Notion API (4 databases)
Symfony ──POST digest──→ Slack Bot Express (:4001/api/slack/send-digest)1. Prerequisites
Install on your machine:
| Software | Version | Check |
|---|---|---|
| PHP | 8.2+ | php -v |
| Composer | Latest | composer -V |
| Node.js | 18+ | node -v |
| npm | Latest | npm -v |
| SQLite3 | 3.x | sqlite3 --version |
| Git | Any recent | git --version |
Accounts and access you need:
- Slack workspace — admin access to create/install apps
- Notion workspace — admin access to create integrations and databases
- OpenAI API key — for AI summary generation (or compatible provider configured in backend)
2. Clone and install dependencies
git clone <repo-url> yappa-knowledge-hub
cd yappa-knowledge-hub
# Symfony backend
cd backend && composer install && cd ..
# Slack bot
cd slack && npm install && cd ..Optional — root-level npm (docs tooling, scripts):
npm install3. Notion setup
3.1 Create the integration
- Open notion.so/my-integrations
- Click "+ New integration"
- Name:
Yappa Knowledge Hub(orYapHub) - Capabilities: Read content, Update content, Insert content
- Type: Internal integration
- Submit and copy the token — starts with
ntn_
Save this as NOTION_API_KEY in backend/.env.
3.2 Create the four databases
Create all four databases on one Notion page (e.g. "YapHub"). After each database is created, share it with the integration:
"..." menu → Add connections → select your integration
Database 1: Knowledge Items
| Property | Type | Notes |
|---|---|---|
| Title | Title | |
| Content | Text (rich text) | Main body |
| Status | Status | Not started / In progress / Done |
| Tags | Multi-select | |
| Categories | Relation → Categories | Bidirectional |
| Source URL | URL | |
| Slack User ID | Text | |
| Timestamp | Text | |
| Channel | Text | |
| AI Summary | Text (rich text) | Legacy/alternate field |
| Highlight | Text | AI-generated 2–3 sentence summary |
| Date | Date | |
| LOCAL_ID | Number | Maps to SQLite primary key |
Database 2: Categories
| Property | Type | Notes |
|---|---|---|
| Title | Title | |
| Description | Text (rich text) | |
| Default Target Groups | Multi-select | Audience labels |
| Knowledge Items | Relation → Knowledge Items | Bidirectional |
| Color | Text | |
| Is Active | Checkbox | |
| Sort Order | Number | |
| Digest Frequency | Select | weekly / biweekly / monthly / quarterly |
| Last Digest At | Date | |
| LOCAL_ID | Number |
Database 3: Digest Reports
| Property | Type | Notes |
|---|---|---|
| Title | Title | |
| Status | Status | |
| Content | Text (rich text) | Full digest markdown |
| Knowledge Items | Relation → Knowledge Items | |
| Category | Relation → Categories | |
| Categories | Relation → Categories | |
| Period Start | Date | |
| Period End | Date | |
| Generated At | Date | |
| Generated By | Text | Slack user ID |
| Recipients | Text | |
| Distributed | Checkbox | |
| LOCAL_ID | Number |
Database 4: Subscriptions
| Property | Type | Notes |
|---|---|---|
| Slack User ID | Text | |
| Slack User | Text | Display name |
| Category | Relation → Categories | |
| Is Active | Checkbox | |
| Subscribed At | Date | |
| Unsubscribed At | Date | |
| LOCAL_ID | Number |
3.3 Get database IDs
Open each database in Notion. The URL looks like:
https://www.notion.so/workspace/306e292a15d58004a8cbc222dcd48bb2?v=...
└──────── 32-char database ID ────────┘Record all four IDs for backend/.env.
Via API (alternative):
curl -X POST "https://api.notion.com/v1/search" \
-H "Authorization: Bearer ntn_YOUR_TOKEN" \
-H "Notion-Version: 2022-06-28" \
-H "Content-Type: application/json" \
-d '{"filter":{"property":"object","value":"database"}}'3.4 Notion troubleshooting
| Error | Fix |
|---|---|
object_not_found | Database not shared with integration — use Add connections |
unauthorized | Wrong NOTION_API_KEY or integration deleted |
| Sync works one way only | Check all 4 database IDs; verify relation properties match schema |
Set NOTION_MOCK=true in backend/.env to run without Notion API calls (useful for tests).
4. Slack app setup
4.1 Create the app from manifest
- Go to api.slack.com/apps
- Create New App → From an app manifest
- Select your workspace
- Paste the contents of
slack/slack-app-manifest.yamlfrom this repo - Review and Create
The manifest configures:
- App Home (Home tab)
- Bot user with OAuth scopes:
chat:write,chat:write.public, channel/group/im history and read,users:read,files:read, etc. - Shortcuts:
add_to_hub(message shortcut),quick_add_knowledge(global shortcut) - Socket Mode enabled
- Events:
app_home_opened, messages, reactions, file shares, app mentions
4.2 Enable Socket Mode and app-level token
- Settings → Socket Mode → toggle ON
- Settings → Basic Information → App-Level Tokens
- Generate Token and Scopes
- Name:
Socket Mode Token, scope:connections:write - Copy token — starts with
xapp-
Save as SLACK_APP_TOKEN in slack/.env.
4.3 Install to workspace
- Install App → Install to Workspace → Allow
- Copy Bot User OAuth Token — starts with
xoxb- - Save as
SLACK_BOT_TOKENinslack/.env
4.4 Signing secret
- Settings → Basic Information → App Credentials
- Copy Signing Secret
- Save as
SLACK_SIGNING_SECRETinslack/.env
4.5 Token reference
| Token | Prefix | Where to find |
|---|---|---|
| Bot OAuth Token | xoxb- | Install App page |
| Signing Secret | hex string | Basic Information → App Credentials |
| App-Level Token | xapp- | Basic Information → App-Level Tokens |
5. Backend configuration (backend/.env)
Copy the example file and fill in values:
cp backend/.env.example backend/.env5.1 Full variable reference
# ─── Symfony core ───
APP_ENV=dev
APP_SECRET=<random-32-char-string>
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
DEFAULT_URI=http://localhost:8001
# ─── API authentication ───
# Bearer token for ALL /api/* requests (Slack bot → Symfony)
SYNC_API_TOKEN=<shared-secret>
# Token Symfony sends TO the Slack bot Express API (Symfony → Slack bot)
INTERNAL_API_SECRET=<shared-secret-for-bot-callbacks>
# ─── Notion ───
NOTION_API_KEY=ntn_<your-integration-token>
NOTION_VERSION=2022-06-28
NOTION_DATABASE_KNOWLEDGE=<32-char-id>
NOTION_DATABASE_CATEGORIES=<32-char-id>
NOTION_DATABASE_DIGESTS=<32-char-id>
NOTION_DATABASE_SUBSCRIPTIONS=<32-char-id>
NOTION_MOCK=false
# ─── AI ───
OPENAI_API_KEY=sk-<your-key>
OPENAI_MODEL=gpt-4o-mini
# ─── Slack bot callback URL ───
SLACK_API_URL=http://localhost:4001
# ─── Optional ───
SENTRY_DSN=5.2 Authentication model
Slack bot → Symfony (every API call):
Authorization: Bearer <SYNC_API_TOKEN>Set BACKEND_API_TOKEN in slack/.env to the same value as SYNC_API_TOKEN.
Symfony → Slack bot (digest delivery):
Symfony calls POST {SLACK_API_URL}/api/slack/send-digest with:
Authorization: Bearer <INTERNAL_API_SECRET>The Slack bot validates this against BACKEND_API_TOKEN in slack/.env. In practice, use the same shared secret for SYNC_API_TOKEN, INTERNAL_API_SECRET, and BACKEND_API_TOKEN during local dev.
5.3 Initialize the database
The project uses schema:create (no Doctrine migration files in repo):
cd backend
php bin/console doctrine:database:create
php bin/console doctrine:schema:create
php bin/console doctrine:schema:validateExpected: [Mapping] OK and [Database] OK.
5.4 Optional: seed development data
Only if the database is empty:
./scripts/seed-dev-data.shThis script refuses to run if categories or knowledge already exist.
5.5 Start the backend
cd backend
php -S 0.0.0.0:8001 -t public5.6 Verify backend
curl http://localhost:8001/api/categories \
-H "Authorization: Bearer <your-sync-token>"Expected: {"success":true,"data":[...]}
6. Slack bot configuration (slack/.env)
Create slack/.env:
# ─── Slack tokens ───
SLACK_BOT_TOKEN=xoxb-<your-bot-token>
SLACK_SIGNING_SECRET=<your-signing-secret>
SLACK_APP_TOKEN=xapp-<your-app-level-token>
# ─── Ports ───
PORT=4000
API_PORT=4001
NODE_ENV=development
# ─── Backend connection ───
API_BASE_URL=http://localhost:8001/api
BACKEND_API_TOKEN=<must-match-SYNC_API_TOKEN>Critical:
API_BASE_URLmust use port 8001 (matchesstart_servers.shandDEFAULT_URI). The default inslack/.env.examplemay still show8000— override it.
6.1 Start the Slack bot
cd slack
npm run devExpected startup log:
[INFO] [Startup] Successfully fetched N categories from backend
[INFO] ⚡ Slack bot is running (Socket Mode)
[INFO] 🏥 API server running on port 4001
[INFO] Now connected to Slack7. Running everything
Option A — Combined script (background)
./start_servers.sh- Symfony:
http://localhost:8001→logs/backend.log - Slack bot: Socket Mode + API →
logs/slack.log - Kills processes on ports 8000, 8001, 4000, 4001 before starting
Option B — Separate terminals
# Terminal 1
cd backend && php -S 0.0.0.0:8001 -t public
# Terminal 2
cd slack && npm run devPort summary
| Port | Service | Purpose |
|---|---|---|
| 8001 | Symfony | REST API /api/* |
| 4000 | Bolt | Socket Mode WebSocket to Slack |
| 4001 | Express | Digest delivery from backend |
8. End-to-end verification
Run these checks after both services are up:
| # | Test | Command / action | Expected |
|---|---|---|---|
| 1 | Backend API | curl localhost:8001/api/categories -H "Authorization: Bearer $TOKEN" | JSON with categories |
| 2 | Slack bot API | Confirm port 4001 is listening and bot logs show Socket Mode connected | API server running |
| 3 | App Home | Open YapHub in Slack sidebar | Dashboard loads with categories |
| 4 | Message shortcut | Right-click message → "Add to YapHub" | Modal opens |
| 5 | Global shortcut | Lightning bolt → "Quick Add to YapHub" | Modal opens |
| 6 | Notion sync | Add knowledge with URL | Notion page appears with content |
9. Troubleshooting
Slack bot
| Symptom | Cause | Fix |
|---|---|---|
server explicit disconnect | Expired SLACK_APP_TOKEN | Regenerate app-level token with connections:write |
| Bot starts but no events | Socket Mode off or wrong token | Enable Socket Mode; verify xapp- token |
| "Failed to pre-cache categories" | Backend down or wrong URL | Check port 8001, API_BASE_URL, token match |
| "Missing scope" | App needs reinstall | OAuth & Permissions → Reinstall App → update xoxb- token |
Backend
| Symptom | Cause | Fix |
|---|---|---|
| 401 Unauthorized | Token mismatch | Align SYNC_API_TOKEN ↔ BACKEND_API_TOKEN |
| Database errors | Schema not created | Run doctrine:schema:create |
| Notion errors | DB not shared / wrong ID | Re-check integration connection and IDs |
Reset database (destructive)
cd backend
php bin/console doctrine:database:drop --force
php bin/console doctrine:database:create
php bin/console doctrine:schema:create
cd .. && ./scripts/seed-dev-data.sh # optional, empty DB onlyView logs
tail -f logs/backend.log
tail -f logs/slack.log
tail -f backend/var/log/dev.log10. Configuration checklist
backend/.env
| Variable | Required | Description |
|---|---|---|
APP_ENV | Yes | dev or prod |
APP_SECRET | Yes | Random 32-char string |
DATABASE_URL | Yes | SQLite path |
DEFAULT_URI | Yes | http://localhost:8001 |
SYNC_API_TOKEN | Yes | Bearer token for /api/* |
INTERNAL_API_SECRET | Yes | Token for Symfony → Slack bot calls |
NOTION_API_KEY | Yes* | ntn_ integration token |
NOTION_VERSION | Yes | 2022-06-28 |
NOTION_DATABASE_KNOWLEDGE | Yes* | Database ID |
NOTION_DATABASE_CATEGORIES | Yes* | Database ID |
NOTION_DATABASE_DIGESTS | Yes* | Database ID |
NOTION_DATABASE_SUBSCRIPTIONS | Yes* | Database ID |
OPENAI_API_KEY | Yes** | For AI summaries |
OPENAI_MODEL | Yes** | e.g. gpt-4o-mini |
SLACK_API_URL | Yes | http://localhost:4001 |
NOTION_MOCK | No | true skips Notion API |
* Not required when NOTION_MOCK=true
** Required for real AI summaries; use mock mode in tests
slack/.env
| Variable | Required | Description |
|---|---|---|
SLACK_BOT_TOKEN | Yes | xoxb- bot token |
SLACK_SIGNING_SECRET | Yes | From App Credentials |
SLACK_APP_TOKEN | Yes | xapp- Socket Mode token |
PORT | No | Default 4000 |
API_PORT | No | Default 4001 |
API_BASE_URL | Yes | http://localhost:8001/api |
BACKEND_API_TOKEN | Yes | Must match SYNC_API_TOKEN |
NODE_ENV | No | development |
11. Next steps
After setup:
- MVP Presentation — feature walkthroughs with demo videos
- Implementation Guide — daily dev commands and project structure
- Testing Overview — PHPUnit, Jest, Playwright
- Notion Integration Details — sync architecture and troubleshooting
- Slack User Guide — end-user instructions
Last updated: 2026-05-27