ClassHub is a small Next.js app for a private class/community:
- News feed with likes and comments
- Petitions with voting
- User profile (name, username, avatar upload)
- Telegram-bot login flow (token-based) with access requests + admin approval
- Next.js (App Router) + React
- PostgreSQL (
postgresdriver) - Supabase Storage (avatars + admin image uploads)
- Telegram Bot webhook for authentication / access requests
Requirements:
- Node.js 18+
- A PostgreSQL database (Supabase recommended)
Install deps and run dev:
npm install
npm run devApp will be available at http://localhost:3000.
Create .env.local (or copy from .env.example) and set the values.
Server-side:
DATABASE_URL(required): Postgres connection stringDATABASE_SSL(optional): set totrueif your provider requires SSLADMIN_KEY(required): protects/api/admin/*routesTELEGRAM_BOT_USERNAME(optional): used for generating login links; defaults toClassHub10BBotTELEGRAM_BOT_TOKEN(required): Telegram bot token for sending messagesTELEGRAM_WEBHOOK_SECRET(optional): validates Telegram webhook requests viax-telegram-bot-api-secret-tokenSUPABASE_URL(required for uploads):https://<project-ref>.storage.supabase.coSUPABASE_SERVICE_ROLE_KEY(required for uploads): Supabaseservice_roleJWTSUPABASE_STORAGE_BUCKET(optional): defaults toavatarsSUPABASE_STORAGE_PUBLIC(optional): defaults totrue
Client-side:
NEXT_PUBLIC_API_BASE(optional): keep empty for same-origin; set only if UI and API are on different hostsNEXT_PUBLIC_ADMIN_KEY(optional): admin UI uses this to call admin routes (note: this is exposed in the browser)
Security note:
- Do not commit real secrets. If you ever committed them, rotate tokens/keys and remove them from git history.
The app expects these tables to exist:
allowed_users(whitelist of users + role + profile)auth_tokens(login tokens generated by UI and confirmed via Telegram webhook)access_requests(Telegram users requesting access)
Seedb/access_requests.sql.news,news_likes,news_commentspetitions,petition_votes
- User clicks "Через Telegram бота" in the login modal.
- App calls
POST /api/auth/generate_linkand gets at.me/<bot>?start=auth_<token>link. - User opens the bot via the link.
- Telegram webhook (
POST /api/telegram/webhook) confirms the token if the user is already allowed. - The site automatically polls
POST /api/auth/verifyuntil the token is confirmed and then logs the user in. - If the user is not in
allowed_users, the webhook creates/updates a row inaccess_requestswithstatus=pending.
Webhook URL:
https://<your-domain>/api/telegram/webhook
If you set TELEGRAM_WEBHOOK_SECRET, also set Telegram webhook secret_token to the same value.
UI:
/admin?tab=newscreate news posts (optionally upload an image)/admin?tab=petitioncreate petitions/admin?tab=usersmanage allowed users and access requests
API routes (protected by ADMIN_KEY):
GET/POST /api/admin/access_requestsGET/POST /api/admin/allowed_usersDELETE /api/admin/allowed_users/:telegramIdPOST /api/admin/upload/image(Supabase Storage upload)
GET /api/healthGET /health
Windows next build EPERM on .next:
- Stop
next dev(and any node processes using the repo) - Delete
.next - Run
npm run buildagain