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 APICollaborative 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 AppFrom 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 AppInstall to WorkspaceAllow
  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:8001logs/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_TOKENBACKEND_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