Contributing Guide
Contentrain Studio welcomes community contributions to the AGPL core. This guide covers everything you need to set up a development environment, follow project conventions, and submit quality pull requests.
What We Accept
| Accepted | Not Accepted |
|---|---|
| Bug fixes | Proprietary ee/ contributions (unless coordinated with maintainers) |
| Tests | Changes that violate architecture rules |
| Documentation | Hardcoded strings (use Contentrain dictionary) |
| Developer tooling improvements | Supabase imports outside server/providers/ |
| Accessibility and UX improvements | Raw Tailwind colors (use semantic palette) |
| Performance and maintainability | Breaking changes without discussion |
Development Setup
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| Node.js | 22+ | Runtime |
| pnpm | 10+ | Package manager |
| Supabase CLI | Latest | Local database |
| Git | Latest | Version control |
Local Setup
git clone https://github.com/Contentrain/studio.git
cd studio
pnpm install
cp .env.example .env
pnpm db:start
pnpm db:migrate
npx contentrain generate
pnpm devThe app starts at http://localhost:3000.
Available Commands
# Development
pnpm dev # Start dev server
# Code Quality
pnpm lint # Run ESLint
pnpm lint:fix # Auto-fix ESLint issues
pnpm typecheck # TypeScript type checking
# Testing
pnpm test:unit # Pure logic and route handler tests
pnpm test:integration # Route integration and server wiring
pnpm test:nuxt # Composables and Nuxt runtime behavior
pnpm test:rls # Row-Level Security behavior
pnpm test:e2e # Browser and user-flow regressions
pnpm test:ci # Full CI test suite
# Build
pnpm build # Production build
# Release
pnpm release:check # Pre-release validation (lint + typecheck + build)
pnpm release # Full release gate + changelog + version + tagCode Style
ESLint + Stylistic
Studio uses @nuxt/eslint with Stylistic rules. There is no Prettier -- ESLint handles both linting and formatting.
pnpm lint:fix # Always run before committingKey Style Rules
- No semicolons (Stylistic enforced)
- Single quotes for strings
- 2-space indentation
- Trailing commas in multi-line
- No
as anytype assertions -- fix the actual type issue - No
@deprecatedmarkers -- the project is in active development, remove things directly
Architecture Rules
These are non-negotiable -- PRs that violate them will not be merged.
Provider Pattern
NEVER import @supabase/supabase-js outside server/providers/
NEVER use provider-specific composables in routes, pages, or components
NEVER leak vendor details into application logic
NEVER hardcode plan checks -- use hasFeature()All application code depends on provider interfaces and factories in server/utils/providers.ts.
UI and Design
- Use the semantic color system (
primary-*,secondary-*,success-*,warning-*,danger-*,info-*), never raw Tailwind colors (gray-*,red-*, etc.) - Follow atomic component structure: atoms, molecules, organisms
- Use
NuxtImgfor all images (not<img>) - All
<button>elements must have explicittypeattribute - All interactive elements must have
focus-visiblestyles
No Hardcoded Strings
All user-facing text comes from Contentrain dictionaries:
const { t } = useContent()
t('auth.sign_in_title') // => "Sign in to your account"When adding new UI text:
- Add the key/value to the relevant dictionary model
- Run
npx contentrain generate - Use
useContent().t('key')in the component
Enterprise Boundary
- Never copy enterprise-only behavior into core
- Never make core depend on
ee/implementation details - Core must work without
ee/present - Graceful degradation: features become unavailable, not broken
Workspace Scoping
Every database query MUST scope by workspace_id, not just project_id. This prevents cross-workspace data leaks.
Conventional Commits
Commits must follow the Conventional Commits specification. This is enforced by commitlint + husky.
Format
type(scope): description
[optional body]
[optional footer]Types
| Type | When to Use |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation only |
style | Formatting, no code change |
refactor | Code change that neither fixes nor adds |
perf | Performance improvement |
test | Adding or updating tests |
chore | Build process, tooling, dependencies |
ci | CI configuration |
Examples
feat(chat): add context pin system for media assets
fix(auth): handle expired refresh token gracefully
docs(api): document CDN delivery endpoint
test(rls): add workspace member isolation tests
chore(deps): update @contentrain/types to v0.3.0Developer Certificate of Origin
Studio uses the DCO (not a CLA). Sign off each commit:
git commit -s -m "feat(chat): add context pin system"This appends Signed-off-by: Your Name <[email protected]> to the commit message.
Testing Expectations
Choose the smallest relevant test set, but always cover behavioral changes:
| Test Suite | When to Run |
|---|---|
test:unit | Changed pure logic, utilities, route handlers |
test:integration | Changed route wiring, middleware, provider interaction |
test:nuxt | Changed composables, Nuxt runtime behavior |
test:rls | Changed auth, permissions, database queries |
test:e2e | Changed user-facing workflows, UI components |
Before opening a PR:
pnpm lint
pnpm typecheck
pnpm test:ciAlso run pnpm test:rls and pnpm test:e2e when your change touches auth, permissions, delivery, forms, media, or end-user workflows.
Pull Request Process
Before Opening
- [ ] Link the relevant issue or discussion
- [ ] Run
pnpm lint && pnpm typecheck && pnpm test:ci - [ ] Run
pnpm test:rlsandpnpm test:e2eif applicable - [ ] Update documentation when behavior or contracts change
PR Description
- Explain the change and the user-facing impact
- Add or update tests for regressions
- Keep architectural boundaries intact
- Keep changes focused -- do not mix refactors, docs, and features in one PR
Large Changes
Large or risky changes should start as an issue or discussion before implementation. This avoids wasted effort on approaches that do not align with the project direction.
Reporting Issues
- Bugs: Use GitHub issue templates with reproduction steps
- Features: Use GitHub issue templates with concrete proposals
- Questions: Use GitHub Discussions
- Security: Report privately to [email protected]
WARNING
Security vulnerabilities must be reported privately, not through public issues.
Related Pages
- Architecture -- system design rules
- Enterprise Edition -- open-core model
- Changelog -- version history