Thank you for your interest in contributing to Pawboard! This guide explains our development workflow and how to submit changes.
| Environment | Database | Realtime | When Used |
|---|---|---|---|
| Local | Docker (your machine) | Docker | Day-to-day development |
| Preview | pawboard-dev (shared) | pawboard-dev | PR testing on Vercel |
| Production | pawboard (prod) | pawboard | Live site |
main (production)
|
+-- feature/your-feature (PR branch)
mainis the production branch- Create feature branches for all changes
- PRs are required for merging to main
Follow the Local Development Guide to set up your environment.
git checkout -b feature/your-feature-name- Follow the coding conventions in AGENTS.md
- Test locally with
bun dev - If changing the database schema, see Schema Changes below
git add .
git commit -m "feat: add new feature description"Follow Conventional Commits:
feat:- New featurefix:- Bug fixdocs:- Documentationrefactor:- Code refactoringchore:- Maintenance tasks
git push -u origin feature/your-feature-nameThen create a Pull Request on GitHub.
Database schema changes require special attention because they affect shared environments.
- Edit
db/schema.ts - Generate a migration:
bun db:generate:local
- Review the generated SQL file in
drizzle/ - Apply the migration:
bun db:migrate:local
- Test thoroughly
When your PR includes schema changes:
- Include both files: Commit
db/schema.tsAND the new migration file indrizzle/ - For team members: After PR approval, a maintainer will trigger the migration to the dev environment
- For external contributors: Schema changes require extra review. A maintainer will manually apply migrations after thorough review
Security Note: Migrations are NOT automatically applied to prevent malicious PRs from modifying the shared dev database. A team member must approve and trigger the migration.
- Migration file generated and included in commit
- Migration SQL reviewed for correctness
- Migration is idempotent (see safety patterns below)
- Schema changes are backward compatible (or migration plan documented)
- No data loss in existing tables
- Indexes added for frequently queried columns
- Foreign key constraints are appropriate
- Default values set where needed
Migrations should be idempotent - safe to run multiple times without errors. This is critical because:
- Migrations may run against databases in different states
- Failed partial migrations should be retryable
- Preview environments share a database across PRs
For CREATE TABLE statements:
CREATE TABLE IF NOT EXISTS "table_name" (
-- columns
);For ADD COLUMN statements:
ALTER TABLE "table_name" ADD COLUMN IF NOT EXISTS "column_name" type;For DROP TABLE statements:
DROP TABLE IF EXISTS "table_name";For DROP COLUMN statements:
ALTER TABLE "table_name" DROP COLUMN IF EXISTS "column_name";For constraints (foreign keys, unique, etc.):
DO $$ BEGIN
ALTER TABLE "table_name" ADD CONSTRAINT "constraint_name"
FOREIGN KEY ("column") REFERENCES "other_table"("id");
EXCEPTION
WHEN duplicate_object THEN NULL;
END $$;For indexes:
CREATE INDEX IF NOT EXISTS "index_name" ON "table_name" ("column");Drizzle Kit generates safe migrations by default for most operations. However, always review generated SQL to verify:
CREATE TABLEhasIF NOT EXISTSADD COLUMNhasIF NOT EXISTS- Constraints use the
DO $$ BEGIN ... EXCEPTIONpattern - Drop operations have
IF EXISTS
If a generated migration is missing these patterns, manually edit the SQL file before committing.
Drizzle Kit does not have built-in rollback functionality. The drizzle-kit drop command only removes migration files locally - it does not undo changes in the database.
To fully rollback a migration, you must manually:
Run SQL to reverse the migration. For example, if you added a column:
ALTER TABLE "cards" DROP COLUMN IF EXISTS "hidden";Drizzle tracks applied migrations in drizzle.__drizzle_migrations. You must delete the record:
-- First, find the migration hash
SELECT id, hash, created_at FROM drizzle.__drizzle_migrations ORDER BY created_at DESC;
-- Then delete the record (replace with actual hash)
DELETE FROM drizzle.__drizzle_migrations WHERE hash = 'your_migration_hash_here';Delete the migration file from drizzle/ folder, or run:
bunx drizzle-kit dropRemove or undo the changes in db/schema.ts to match the database state.
| Step | Action |
|---|---|
| 1 | Run SQL to undo schema changes (DROP COLUMN, DROP TABLE, etc.) |
| 2 | Delete record from drizzle.__drizzle_migrations |
| 3 | Delete migration file from drizzle/ |
| 4 | Revert changes in db/schema.ts |
Tip: When creating migrations, document the rollback SQL in your PR description for easy reference later.
- Create PR from your feature branch
- Wait for CI checks to pass
- Request review from a team member
- After approval:
- If schema changes: Maintainer triggers schema sync via workflow dispatch
- Vercel preview deployment uses updated dev database
- Test in preview environment
- Merge to main
- Fork the repository
- Create your feature branch
- Make changes following our guidelines
- Submit PR with clear description
- Wait for review
- Address any feedback
- A maintainer will merge after approval
- Clear description of changes
- Tests pass locally
- No linting errors (
bun check) - Documentation updated if needed
- Screenshots for UI changes
# Run the dev server
bun dev
# Check for linting issues
bun check
# Format code
bun formatAfter your PR is created:
- Vercel automatically creates a preview deployment
- The preview uses the shared dev Supabase project
- Test your changes at the preview URL
- Realtime features work in preview (shared with other PRs)
Note: Since all preview deployments share the same dev database, avoid creating test data that might conflict with others. Use unique session IDs.
- Keep PRs focused and small when possible
- Respond to feedback promptly
- Update your branch with main if needed:
git fetch origin git rebase origin/main
- Be constructive and specific
- Approve once concerns are addressed
- For schema changes, verify backward compatibility
- Check existing issues
- Ask questions in PR comments
- Reach out to maintainers
By contributing, you agree that your contributions will be licensed under the same license as the project.