A decentralized governance platform for managing proposals and grants on the Mina Protocol blockchain. Built with Next.js 14, TypeScript, and Prisma.
- π Multi-source authentication (Discord, Telegram, Wallet)
- π Account linking across auth providers
- π Proposal creation and management
- π¨ Modern UI with shadcn/ui components
- π Server-side rendering with Next.js
- π Type-safe database operations with Prisma
- π³ Docker support for development
- Framework: Next.js 14 (App Router)
- Language: TypeScript
- Database: PostgreSQL 17
- ORM: Prisma
- UI: shadcn/ui + Tailwind CSS
- Authentication: Custom JWT implementation
- Container: Docker + Docker Compose
- Node.js 18+
- Docker and Docker Compose
- npm
Create a .env
file in the root directory:
# Authentication
JWT_PRIVATE_KEY_RS512="-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----"
JWT_PUBLIC_KEY_RS512="-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----"
# Discord Bot Configuration
DISCORD_TOKEN="your-bot-token" # Bot token from Discord Developer Portal
CLIENT_ID="your-client-id" # Application ID from Developer Portal
GUILD_ID="your-guild-id" # Server ID where bot will operate
PUBLIC_KEY="your-public-key" # Application public key from Developer Portal
# Application URL
NEXT_APP_URL="http://localhost:3000" # Used for Discord embed links
# PGAdmin Configuration
PGADMIN_EMAIL=[email protected]
PGADMIN_PASSWORD=pgadmin_password
# Database Configuration
POSTGRES_DB=govbot
POSTGRES_PASSWORD=your_secure_password_here
DATABASE_URL="postgresql://postgres:your_secure_password_here@db:5432/govbot?schema=public"
# OCV API, a.k.a. 'Granola OCV'
NEXT_PUBLIC_OCV_API_BASE_URL=http://on-chain-voting-server:8080
CONSIDERATION_REVIEWER_APPROVAL_THRESHOLD=2 # Minimum number of reviewer approvals needed for a proposal to move to deliberation. Default: 2
CONSIDERATION_REVIEWER_APPROVAL_THRESHOLD
(default: 2)- Defines the minimum number of reviewer approvals required for a proposal to move from consideration to deliberation phase
- Must be a positive integer (>= 1)
- If invalid value is provided, defaults to 2
- Example values:
CONSIDERATION_REVIEWER_APPROVAL_THRESHOLD=2
(default, requires 2 approvals)CONSIDERATION_REVIEWER_APPROVAL_THRESHOLD=3
(requires 3 approvals)
- Start the development environment:
docker-compose up
This will start:
- Next.js development server at http://localhost:3000
- PostgreSQL database at localhost:5432
- PgAdmin at http://localhost:5050
- Access the application:
- Frontend: http://localhost:3000
- PgAdmin: http://localhost:5050
- Install dependencies:
npm install
- Start PostgreSQL:
docker-compose up db
- Run migrations:
npx prisma migrate dev
- Start development server:
npm run dev
OR
docker compose up --build
The platform supports multiple authentication sources:
-
Auth Sources:
- Discord (via bot)
- Telegram (via bot)
- Mina Protocol Wallet
-
JWT Implementation:
- Short-lived access tokens (15 minutes)
- Refresh tokens (7 days)
- Secure httpOnly cookies
- Token rotation on refresh
-
User Resolution:
// User ID derivation userId = UUIDv5(authSource.type + authSource.id);
Users can link multiple authentication sources:
-
Linking Process:
- Each user has a
linkId
- Linked accounts share the same
linkId
- All linked accounts can access shared resources
- Each user has a
-
Implementation:
interface User { id: string; // Derived from auth source linkId: string; // Shared between linked accounts metadata: Json; // Auth source info }
Bree.js is for running background tasks in separate threads:
-
Worker Structure:
src/ tasks/ # TypeScript worker files discord-notify-proposal-submission.ts scripts/ build-workers.ts dist/ tasks/ # Compiled JavaScript workers
-
Build Process:
- Workers are compiled from TypeScript to JavaScript
- ESM compatibility layer is added for module support
- Dependencies are bundled with the worker
- Output is placed in
dist/tasks/
-
Available Scripts:
# Build workers only npm run build:workers # Build everything (Next.js + workers) npm run build
-
Implementation:
- Workers are initialized in API routes
- Each worker runs in isolation
- Communication via worker_threads
- Proper error handling and recovery
-
Development Flow:
- Workers are automatically built in development
- Hot reload of workers NOT supported via
npm run dev
- Production builds include worker compilation
POST /api/auth/exchange
- Exchange initial token for access/refresh tokens
POST /api/auth/refresh
- Refresh access token
POST /api/auth/logout
- Clear auth tokens
GET /api/proposals
- List user's proposals
POST /api/proposals
- Create new proposal
GET /api/proposals/:id
- Get proposal details
PUT /api/proposals/:id
- Update proposal
DELETE /api/proposals/:id
- Delete draft proposal
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
-
TypeScript:
- Enable strict mode
- Use proper type inference
- Define clear interfaces
-
Components:
- Use Server Components by default
- Implement proper error boundaries
- Follow accessibility guidelines
-
Styling:
- Use Tailwind CSS classes
- Follow shadcn/ui patterns
- Maintain consistent theming
- Production Build:
npm run build
- Docker Production:
docker-compose -f docker-compose.prod.yml up
To contribute, follow these steps:
- Make an issue that includes details about the feature or bug or something else.
- Get that issue tested by: Cristina Echeverry.
- Get that issue approved by the product owners: Cristina Echeverry (CristinaEche) & Illya Gerasymchuk (iluxonchik)
- Write a PR and get it approved by the code owners and Mina devops: Illya Gerasymchuk (developer & code-owner), johnmarcou (Mina devops). Each PR must correspond to an approved issue. By default, PRs should be merged by the PR submitter, though in some cases if changes are needed, they can be merged by code owners.