Skip to main content
Thanks for your interest in contributing to ThinkEx! We welcome bug reports, feature suggestions, and pull requests from the community.

Before You Start

ThinkEx is a production application, not a demo or template. Contributions should prioritize:
  • Reliability: Changes should not introduce bugs or break existing functionality
  • Maintainability: Code should be clean, well-documented, and follow existing patterns
  • User Value: Features should solve real user problems, not just be “nice to have”
Please read our Code of Conduct and Security Policy before contributing.

Development Setup

Prerequisites

Make sure you have the following installed:

Node.js 20+

Required for Next.js 16. Download from nodejs.org

pnpm

Fast package manager. Install: npm install -g pnpm

PostgreSQL 12+

Local installation or Docker. See setup below.

Git

Version control. Download from git-scm.com
The easiest way to get started is using our interactive setup script:
# Clone the repository
git clone https://github.com/ThinkEx-OSS/thinkex.git
cd thinkex

# Run setup script
./setup.sh
  1. Checks prerequisites (Node.js, pnpm, Docker)
  2. Creates .env file from template
  3. Generates BETTER_AUTH_SECRET automatically
  4. Starts PostgreSQL in Docker (or uses local if Docker unavailable)
  5. Configures database connection
  6. Installs dependencies with pnpm install
  7. Initializes database schema with pnpm db:push
  8. Starts development server with pnpm dev

Manual Setup

If you prefer to set up manually: 1. Clone and install dependencies
git clone https://github.com/ThinkEx-OSS/thinkex.git
cd thinkex
pnpm install
2. Start PostgreSQL
If you have PostgreSQL installed locally:
CREATE DATABASE thinkex;
CREATE USER thinkex WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE thinkex TO thinkex;
3. Configure environment variables
cp .env.example .env
Edit .env and configure:
# Database
DATABASE_URL=postgresql://thinkex:thinkex_password_change_me@localhost:5432/thinkex

# Better Auth (generate with: openssl rand -base64 32)
BETTER_AUTH_SECRET=your_random_secret_here

# Google AI (get from https://aistudio.google.com/app/apikey)
GOOGLE_GENERATIVE_AI_API_KEY=your_api_key

# Assistant UI (get from https://cloud.assistant-ui.com/)
NEXT_PUBLIC_ASSISTANT_BASE_URL=https://api.assistant-ui.com
ASSISTANT_API_KEY=your_api_key

# Storage (local or supabase)
STORAGE_TYPE=local

# Optional: Google OAuth
GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret
Required API Keys:Optional API Keys:
  • GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET - For OAuth login
  • Supabase credentials - If using Supabase storage instead of local
4. Initialize database
pnpm db:push
This applies all migrations to create tables and indexes. 5. Start development server
pnpm dev
Open http://localhost:3000 in your browser.

Development Workflow

Project Structure

thinkex/
├── src/
│   ├── app/                 # Next.js app router
│   │   ├── api/            # API routes
│   │   ├── dashboard/      # Dashboard pages
│   │   └── workspace/      # Workspace pages
│   ├── components/         # React components
│   │   ├── ui/            # Shadcn UI components
│   │   ├── editor/        # BlockNote editor
│   │   └── cards/         # Card components
│   ├── lib/               # Utilities and logic
│   │   ├── db/           # Database schema and client
│   │   ├── workspace/    # Workspace event sourcing
│   │   ├── workspace-state/ # State types and helpers
│   │   └── ai/           # AI integrations
│   ├── hooks/            # React hooks
│   └── types/            # TypeScript types
├── drizzle/              # Database migrations
├── public/               # Static assets
└── package.json

Making Changes

1. Create a feature branch
git checkout -b feature/your-feature-name
Use descriptive branch names:
  • feature/ - New features
  • fix/ - Bug fixes
  • docs/ - Documentation updates
  • refactor/ - Code refactoring
2. Make your changes Follow these guidelines:
  • Use TypeScript for all new code
  • Follow existing naming conventions (camelCase for variables, PascalCase for components)
  • Use Prettier for formatting: pnpm format
  • Use ESLint for linting: pnpm lint
  • Add JSDoc comments for complex functions
  • Prefer server components by default
  • Use client components only when needed (interactivity, hooks, browser APIs)
  • Co-locate component files (MyComponent.tsx, MyComponent.module.css)
  • Use Shadcn UI components for consistency
  • Keep components small and focused (< 200 lines)
  • Edit src/lib/db/schema.ts to modify schema
  • Generate migration: pnpm db:generate
  • Apply migration: pnpm db:push
  • Test migration on fresh database
  • Add RLS policies for new tables
  • Add new event types to src/lib/workspace/events.ts
  • Update reducer in src/lib/workspace/event-reducer.ts
  • Ensure reducer is pure (no side effects)
  • Test event replay with sample data
3. Test your changes
# Run type checking
pnpm tc

# Run linter
pnpm lint

# Run formatter check
pnpm format:check

# Build the app
pnpm build
All checks must pass before submitting a PR. CI will automatically run these checks.
4. Commit your changes Use clear, descriptive commit messages:
git add .
git commit -m "feat: add real-time cursor tracking"
Commit message format:
  • feat: - New feature
  • fix: - Bug fix
  • docs: - Documentation
  • style: - Formatting, no code change
  • refactor: - Code refactoring
  • test: - Adding tests
  • chore: - Maintenance tasks
5. Push to your fork
git push origin feature/your-feature-name
6. Open a Pull Request Go to github.com/ThinkEx-OSS/thinkex and click “New Pull Request”.
  • Clear title describing the change
  • Description explaining what and why
  • Screenshots/videos for UI changes
  • All tests passing
  • No merge conflicts
  • Linked to related issue (if applicable)

Development Commands

Common Commands

# Start dev server
pnpm dev

# Build for production
pnpm build

# Start production server
pnpm start

# Run type checking
pnpm tc

# Run linter
pnpm lint

# Fix linting issues
pnpm lint:fix

# Format code
pnpm format

# Check formatting
pnpm format:check

Database Commands

# Generate migration from schema changes
pnpm db:generate

# Apply migrations to database
pnpm db:push

# Launch Drizzle Studio (database GUI)
pnpm db:studio

# Reset database (drop all tables and reapply)
pnpm db:reset

Docker Commands

# Start PostgreSQL
docker-compose up -d postgres

# Stop PostgreSQL
docker-compose down

# View logs
docker-compose logs -f postgres

# Reset PostgreSQL data
docker-compose down -v
docker-compose up -d postgres

Testing Guidelines

Manual Testing

Before submitting a PR, test:

Core Functionality

  • Create/edit/delete workspaces
  • Add different card types
  • Drag and resize cards
  • Chat with AI

Collaboration

  • Open workspace in multiple tabs
  • Verify real-time updates
  • Test conflict resolution
  • Invite collaborators

Edge Cases

  • Slow network conditions
  • Large workspaces (100+ cards)
  • Browser back/forward
  • Page refresh

Browser Support

  • Chrome/Edge (Chromium)
  • Firefox
  • Safari (if available)
  • Mobile browsers

Automated Testing

ThinkEx currently does not have automated tests (contributions welcome!). When adding tests:
  • Use Vitest for unit tests
  • Use Playwright for E2E tests
  • Test event reducers (pure functions)
  • Test API routes with mock data

Architecture Guidelines

Event Sourcing Principles

When working with workspace state:
  1. All changes must be events - Never mutate state directly
  2. Events are immutable - Once created, events cannot be modified
  3. Reducers must be pure - Same events always produce same state
  4. Include user context - Events should track who made the change
  5. Use timestamps - Events must have monotonically increasing timestamps
See System Architecture for details.

State Management Best Practices

  • Use TanStack Query for server state (API data)
  • Use Zustand for client state (UI state)
  • Use event sourcing for workspace state
  • Avoid prop drilling - use context or state management
  • Keep components unaware of how state is persisted

Performance Considerations

  • Move calculations to useMemo/useCallback
  • Virtualize long lists with TanStack Virtual
  • Lazy load components with React.lazy()
  • Use snapshots to reduce replay time
  • Batch multiple events when possible
  • Avoid creating events on every keystroke
  • Use indexes for common queries
  • Paginate large result sets
  • Select only needed columns
  • Use database-level filtering (RLS)

Community & Support

GitHub Discussions

Ask questions and discuss ideas

Issue Tracker

Report bugs and request features

Documentation

Read the full docs

Reporting Issues

When reporting a bug, include:
  • Description: What happened vs. what you expected
  • Steps to Reproduce: Numbered list of steps
  • Environment: OS, browser, Node.js version
  • Screenshots: If UI-related
  • Logs: Console errors or server logs
  • Related Code: Link to relevant code if known
For security vulnerabilities, see our Security Policy.

Feature Requests

When suggesting a feature:
  1. Search existing issues - Someone may have suggested it already
  2. Explain the problem - What user need does this solve?
  3. Describe the solution - How should it work?
  4. Consider alternatives - Are there other ways to solve this?
  5. Show examples - Screenshots or mockups help

Code Review Process

After submitting a PR:
  1. Automated checks run - CI runs linting, type checking, and build
  2. Maintainer review - A maintainer will review your code
  3. Address feedback - Make requested changes
  4. Approval - Once approved, PR is merged
  5. Deployment - Changes deploy to production after merge
Review may take a few days - please be patient!

License

By contributing to ThinkEx, you agree that your contributions will be licensed under the AGPL-3.0 License.

Build docs developers (and LLMs) love