Skip to content
enzihubPublic

About

Slack overload in, a morning brief out: reads the last 24 hours of your Slack channels and emails a short executive brief at the hour you choose.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Why

Executives join a dozen Slack channels and read none of them. FocusGate reads the last 24 hours of every channel a person can see and emails them one short brief at the hour they pick: what happened, what is blocked, what is due and who owns it.

See it work

Animated walkthrough: the dashboard's 'Send me FocusGate' button, the Profile page where the delivery time is changed to 6 AM and saved, and the morning brief email.
The real web app, recorded headless on 127.0.0.1 with a local Postgres. Clerk, Slack and Gemini are stubbed. Every person, company and address is invented (.test and .example domains).

Three real screenshots: the morning brief email, the Profile page with the delivery time, and the dashboard with the send-now button.

Features

The morning brief

The core service pulls every message from the last 24 hours, swaps Slack user IDs for real names and sends the chat log to Gemini with one structured prompt. The answer becomes an HTML email with fixed sections: executive summary, key achievements, blockers, incidents, upcoming deadlines, team updates, recommendations and action items.

The morning brief for an invented team: executive summary, achievements, blockers with owners, an incident, deadlines, team updates, recommendations and action items.

Rendered by the real pipeline (generate_newsletter_content and core/templates/newsletter.html) from five invented Slack channels. Only Slack and the model reply were stubbed.

Pick your hour

Each person chooses when the brief arrives. The browser's time zone is saved with the choice, and a Postgres function (core/sql/get_scheduled_users.sql) works out who is due in the next window.

The Profile page for a fictional user, Dana Whitfield: profile details and a newsletter card with the delivery time set to 7:00 AM, America/New_York.

Send one now

New users do not have to wait until tomorrow. The dashboard button asks the core API to build and send a brief straight away.

The dashboard after sign-up with the 'Send me FocusGate' button.

Also in the box

  • Add to Slack OAuth with read-only history scopes. The user token is saved per user in Postgres, so FocusGate only reads what that person can already read.
  • A team brief: set TEAM_SLACK_CHANNEL_ID and a Celery job posts a brief for the whole team to that channel every morning at 05:00 UTC.
  • A /focusgate slash command that posts a brief into the current Slack channel on demand.
  • Stripe billing (optional): pricing page, checkout, customer portal and a webhook that syncs subscriptions into Postgres.
  • Clerk sign-in with a webhook that creates the user row in Postgres.

How it works

Flow: Add to Slack and pick a time, an hourly scheduler (or the send-now button) queues the user, Gemini reads and summarises the last 24 hours, and the morning brief goes out by email or to a Slack channel.
web/   Next.js 14 (App Router) + Clerk + Drizzle + Stripe   sign-in, Add to Slack, delivery time, billing
core/  FastAPI + Celery + Redis                              Slack fetch, Gemini summary, email send
       ├─ app/integrations/slack   read 24 h of history, resolve names, build the brief
       ├─ app/core/ai              the morning brief prompt
       ├─ app/core/scheduler       Celery beat: produce every hour, consume every minute
       ├─ app/core/emailing        Mailtrap sending API
       └─ sql/                     get_scheduled_users() for the shared Postgres

Both apps share one Postgres database. The web app owns the schema (Drizzle migrations in web/src/db/migrations/). Every hour, Celery beat calls get_scheduled_users() and puts the users who are due in a Redis queue. A second job runs every minute and sends whatever is ready.

Quick start

You need Node 18+, Python 3.12 (the 2025 lockfile does not install on 3.14), Poetry, Docker (for Postgres and Redis), and accounts for Clerk, a Slack app, Google AI Studio (Gemini) and Mailtrap. Stripe is optional.

git clone https://github.com/enzihub/focusgate && cd focusgate

1. Database. Start Postgres and the local Neon HTTP proxy that the web app's driver talks to, then run the migrations and the scheduler function:

cd web
export POSTGRES_PASSWORD=choose-a-local-password
export PG_CONNECTION_STRING="postgres://postgres:$POSTGRES_PASSWORD@postgres:5432/main"
docker compose -f src/db/docker-compose.yml up -d
cp .env.example .env.local        # fill it in (see Configuration)
npm ci
npm run db:migrate
psql "postgres://postgres:$POSTGRES_PASSWORD@localhost:5432/main" -f ../core/sql/get_scheduled_users.sql

2. Web app on http://localhost:3000:

npm run dev

3. Core service. Copy core/.env.example to core/.env.development and fill it in, then run each of these in its own terminal:

cd ../core
poetry install --no-root
poetry run uvicorn main:app --port 8000
poetry run celery -A app.core.scheduler.job_tasks worker --loglevel=info
poetry run celery -A app.core.scheduler.job_tasks beat --loglevel=info

Or run the API, worker, beat and Redis together with docker compose up in core/.

The email template test needs no services: cd core && poetry run pytest tests/test_newsletter_template.py.

Note

In your Slack app, set the OAuth redirect URL to <SITE_URL>/auth/slack/callback and add the user scopes channels:history, groups:history, mpim:history, im:history, channels:read, groups:read, mpim:read, im:read and users:read.

Configuration

Every value in the example files is empty. Nothing personal ships with the repo.

Variable Where What it is
SITE_URL, NEXT_PUBLIC_SITE_URL web Public URL of the web app (Slack OAuth redirect)
DATABASE_URL web, core The shared Postgres database
FOCUSGATE_CORE_API_URL, FOCUSGATE_CORE_API_KEY web Where the core runs, and the key it expects in X-API-Key
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, SIGNING_SECRET web Clerk sign-in and its user webhook
NEXT_PUBLIC_SLACK_CLIENT_ID, SLACK_CLIENT_SECRET web The Slack app used for "Add to Slack"
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, NEXT_PUBLIC_STRIPE_PAYMENT_LINK1 web Optional billing
NEXT_PUBLIC_SUPPORT_EMAIL, NEXT_PUBLIC_DEMO_BOOKING_URL web Optional footer contact and booking link
NEXT_PUBLIC_AUTHORIZED_EMAILS web Optional allow-list for internal tools
NEXT_PUBLIC_GA_ID, NEXT_PUBLIC_GTM_ID web Optional analytics. Off when empty
API_KEY core Shared secret the web app sends in X-API-Key
REDIS_URL, CELERY_BROKER_URL, CELERY_RESULT_BACKEND core Redis for Celery and the send queue
PRODUCE_INTERVAL_SECONDS, CONSUME_INTERVAL_SECONDS core Scheduler timing (defaults 3600 and 60)
GEMINI_API_KEY core Writes the brief
OPENAI_API_KEY core Optional, not used by the default pipeline
CLERK_SECRET_KEY core Optional Clerk lookups
SLACK_SIGNING_SECRET, SLACK_BOT_TOKEN, TEAM_SLACK_CHANNEL_ID core Slash commands and the optional team brief
MAILTRAP_API_TOKEN, FROM_EMAIL, FROM_NAME, EMAIL_SUBJECT core Email sending
LOGO_URL, APP_URL core Logo and links inside the email
SENTRY_DSN core Optional error tracking

Status

FocusGate was built by Enzi Studio in 2025 and is shared as-is. It is not maintained and it is not a hosted service, so expect to update dependencies before you deploy it. The google-generativeai package it uses has since been deprecated in favour of google-genai. The old marketing site was a Framer export full of tracking scripts, so it is not included. docs/ is a new page made for this release.

Credits

Built by Enzi Studio. Contributors to the original repositories: @RukshanJS · @sun2ii · @bb-xops · @harrythentrepreneur · @kavishkanimsara · @ZainAli104

The web app, website and images use the Geist typeface (SIL Open Font License 1.1).

Licence

MIT © 2025-2026 Enzi Studio (Harry Edwards)

About

Slack overload in, a morning brief out: reads the last 24 hours of your Slack channels and emails a short executive brief at the hour you choose.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages