Skip to content

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:

ComponentStackPortRole
Symfony backendPHP 8.2, Symfony 78001REST API, SQLite, Notion sync, AI summaries
Slack botNode.js 18+, TypeScript, Bolt SDK4000 (Socket Mode), 4001 (Express API)Slack UI, events, digest delivery endpoint
Notion4 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:

SoftwareVersionCheck
PHP8.2+php -v
ComposerLatestcomposer -V
Node.js18+node -v
npmLatestnpm -v
SQLite33.xsqlite3 --version
GitAny recentgit --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 ​

bash
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):

bash
npm install

3. Notion setup ​

3.1 Create the integration ​

  1. Open notion.so/my-integrations
  2. Click "+ New integration"
  3. Name: Yappa Knowledge Hub (or YapHub)
  4. Capabilities: Read content, Update content, Insert content
  5. Type: Internal integration
  6. 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 ​

PropertyTypeNotes
TitleTitle
ContentText (rich text)Main body
StatusStatusNot started / In progress / Done
TagsMulti-select
CategoriesRelation → CategoriesBidirectional
Source URLURL
Slack User IDText
TimestampText
ChannelText
AI SummaryText (rich text)Legacy/alternate field
HighlightTextAI-generated 2–3 sentence summary
DateDate
LOCAL_IDNumberMaps to SQLite primary key

Database 2: Categories ​

PropertyTypeNotes
TitleTitle
DescriptionText (rich text)
Default Target GroupsMulti-selectAudience labels
Knowledge ItemsRelation → Knowledge ItemsBidirectional
ColorText
Is ActiveCheckbox
Sort OrderNumber
Digest FrequencySelectweekly / biweekly / monthly / quarterly
Last Digest AtDate
LOCAL_IDNumber

Database 3: Digest Reports ​

PropertyTypeNotes
TitleTitle
StatusStatus
ContentText (rich text)Full digest markdown
Knowledge ItemsRelation → Knowledge Items
CategoryRelation → Categories
CategoriesRelation → Categories
Period StartDate
Period EndDate
Generated AtDate
Generated ByTextSlack user ID
RecipientsText
DistributedCheckbox
LOCAL_IDNumber

Database 4: Subscriptions ​

PropertyTypeNotes
Slack User IDText
Slack UserTextDisplay name
CategoryRelation → Categories
Is ActiveCheckbox
Subscribed AtDate
Unsubscribed AtDate
LOCAL_IDNumber

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):

bash
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 ​

ErrorFix
object_not_foundDatabase not shared with integration — use Add connections
unauthorizedWrong NOTION_API_KEY or integration deleted
Sync works one way onlyCheck 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 ​

  1. Go to api.slack.com/apps
  2. Create New App → From an app manifest
  3. Select your workspace
  4. Paste the contents of slack/slack-app-manifest.yaml from this repo
  5. 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 ​

  1. Settings → Socket Mode → toggle ON
  2. Settings → Basic Information → App-Level Tokens
  3. Generate Token and Scopes
  4. Name: Socket Mode Token, scope: connections:write
  5. Copy token — starts with xapp-

Save as SLACK_APP_TOKEN in slack/.env.

4.3 Install to workspace ​

  1. Install App → Install to Workspace → Allow
  2. Copy Bot User OAuth Token — starts with xoxb-
  3. Save as SLACK_BOT_TOKEN in slack/.env

4.4 Signing secret ​

  1. Settings → Basic Information → App Credentials
  2. Copy Signing Secret
  3. Save as SLACK_SIGNING_SECRET in slack/.env

4.5 Token reference ​

TokenPrefixWhere to find
Bot OAuth Tokenxoxb-Install App page
Signing Secrethex stringBasic Information → App Credentials
App-Level Tokenxapp-Basic Information → App-Level Tokens

5. Backend configuration (backend/.env) ​

Copy the example file and fill in values:

bash
cp backend/.env.example backend/.env

5.1 Full variable reference ​

env
# ─── 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):

bash
cd backend
php bin/console doctrine:database:create
php bin/console doctrine:schema:create
php bin/console doctrine:schema:validate

Expected: [Mapping] OK and [Database] OK.

5.4 Optional: seed development data ​

Only if the database is empty:

bash
./scripts/seed-dev-data.sh

This script refuses to run if categories or knowledge already exist.

5.5 Start the backend ​

bash
cd backend
php -S 0.0.0.0:8001 -t public

5.6 Verify backend ​

bash
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:

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_URL must use port 8001 (matches start_servers.sh and DEFAULT_URI). The default in slack/.env.example may still show 8000 — override it.

6.1 Start the Slack bot ​

bash
cd slack
npm run dev

Expected 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 Slack

7. Running everything ​

Option A — Combined script (background) ​

bash
./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 ​

bash
# Terminal 1
cd backend && php -S 0.0.0.0:8001 -t public

# Terminal 2
cd slack && npm run dev

Port summary ​

PortServicePurpose
8001SymfonyREST API /api/*
4000BoltSocket Mode WebSocket to Slack
4001ExpressDigest delivery from backend

8. End-to-end verification ​

Run these checks after both services are up:

#TestCommand / actionExpected
1Backend APIcurl localhost:8001/api/categories -H "Authorization: Bearer $TOKEN"JSON with categories
2Slack bot APIConfirm port 4001 is listening and bot logs show Socket Mode connectedAPI server running
3App HomeOpen YapHub in Slack sidebarDashboard loads with categories
4Message shortcutRight-click message → "Add to YapHub"Modal opens
5Global shortcutLightning bolt → "Quick Add to YapHub"Modal opens
6Notion syncAdd knowledge with URLNotion page appears with content

9. Troubleshooting ​

Slack bot ​

SymptomCauseFix
server explicit disconnectExpired SLACK_APP_TOKENRegenerate app-level token with connections:write
Bot starts but no eventsSocket Mode off or wrong tokenEnable Socket Mode; verify xapp- token
"Failed to pre-cache categories"Backend down or wrong URLCheck port 8001, API_BASE_URL, token match
"Missing scope"App needs reinstallOAuth & Permissions → Reinstall App → update xoxb- token

Backend ​

SymptomCauseFix
401 UnauthorizedToken mismatchAlign SYNC_API_TOKEN ↔ BACKEND_API_TOKEN
Database errorsSchema not createdRun doctrine:schema:create
Notion errorsDB not shared / wrong IDRe-check integration connection and IDs

Reset database (destructive) ​

bash
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 only

View logs ​

bash
tail -f logs/backend.log
tail -f logs/slack.log
tail -f backend/var/log/dev.log

10. Configuration checklist ​

backend/.env ​

VariableRequiredDescription
APP_ENVYesdev or prod
APP_SECRETYesRandom 32-char string
DATABASE_URLYesSQLite path
DEFAULT_URIYeshttp://localhost:8001
SYNC_API_TOKENYesBearer token for /api/*
INTERNAL_API_SECRETYesToken for Symfony → Slack bot calls
NOTION_API_KEYYes*ntn_ integration token
NOTION_VERSIONYes2022-06-28
NOTION_DATABASE_KNOWLEDGEYes*Database ID
NOTION_DATABASE_CATEGORIESYes*Database ID
NOTION_DATABASE_DIGESTSYes*Database ID
NOTION_DATABASE_SUBSCRIPTIONSYes*Database ID
OPENAI_API_KEYYes**For AI summaries
OPENAI_MODELYes**e.g. gpt-4o-mini
SLACK_API_URLYeshttp://localhost:4001
NOTION_MOCKNotrue skips Notion API

* Not required when NOTION_MOCK=true
** Required for real AI summaries; use mock mode in tests

slack/.env ​

VariableRequiredDescription
SLACK_BOT_TOKENYesxoxb- bot token
SLACK_SIGNING_SECRETYesFrom App Credentials
SLACK_APP_TOKENYesxapp- Socket Mode token
PORTNoDefault 4000
API_PORTNoDefault 4001
API_BASE_URLYeshttp://localhost:8001/api
BACKEND_API_TOKENYesMust match SYNC_API_TOKEN
NODE_ENVNodevelopment

11. Next steps ​

After setup:

  1. MVP Presentation — feature walkthroughs with demo videos
  2. Implementation Guide — daily dev commands and project structure
  3. Testing Overview — PHPUnit, Jest, Playwright
  4. Notion Integration Details — sync architecture and troubleshooting
  5. Slack User Guide — end-user instructions

Last updated: 2026-05-27