he2.ai · Developer Standards

Build with
consistency.

Mandatory coding standards, workflows, and best practices every developer on the Helium team must follow. Non-compliance results in PR rejection.

Last updated April 22, 2026
Sections 10 standards
Compliance SOC 2 · GDPR
01

Git & Branch Standards

All branches must follow a strict naming convention to ensure traceability and consistency across the codebase.

Branch Naming Format

Every branch name must follow this exact pattern — no exceptions:

format
<prefix>/<ticket>-<description>
Use kebab-case (lowercase, hyphens only). Always include the ticket/issue number when one exists.

Allowed Prefixes

PrefixUse When
feature/Adding new functionality
bugfix/Fixing a bug
hotfix/Urgent production fix
release/Preparing a release
chore/Maintenance, dependency updates
docs/Documentation changes only
refactor/Code restructuring without behavior change

Examples

Valid
feature/HE2-142-add-team-invite-flow
bugfix/HE2-305-fix-thread-pagination
hotfix/HE2-410-patch-auth-redirect
chore/HE2-99-upgrade-nextjs
refactor/HE2-200-simplify-billing-service
Not Allowed
myfix                    # No prefix, no ticket
Feature/add-stuff        # Wrong case
feature/addTeamInviteFlow # camelCase not allowed
fix_something_quick      # Underscores not allowed
john/testing             # Names are not prefixes

Main Branch Rules

Never push directly to main
All changes must go through a Pull Request. Direct pushes are blocked by branch protection rules.
Squash-and-merge only
All feature branches are merged via squash-and-merge to keep a clean, linear history on main.
Delete branches immediately after merge
Enable "Delete branch after merge" in GitHub settings. Branches inactive for 2+ weeks without an open PR will be deleted automatically.
02

Commit Message Standards

All commits must follow the Conventional Commits specification for automated changelogs and clear history.

Format

format
<type>(<scope>): <subject>
Subject Imperative mood · max 72 chars · no trailing period
Scope Domain or area affected (e.g. auth, billing, agent)
Body Optional — explain why, not what. The diff shows what changed.

Allowed Types

TypeWhen to Use
featNew feature or functionality
fixBug fix
docsDocumentation only
refactorCode change that neither fixes a bug nor adds a feature
testAdding or updating tests
choreBuild process, tooling, dependency updates
ciCI/CD pipeline changes
perfPerformance improvement

Examples

Valid
feat(agent): add retry logic for failed sandbox executions
fix(billing): prevent duplicate Stripe webhook processing
refactor(knowledge-base): extract chunking into dedicated service
test(auth): add integration tests for phone auth flow
chore(deps): upgrade @tanstack/react-query to v5
ci(deploy): add staging environment to GitHub Actions
perf(redis): batch cache invalidation for thread updates
Not Allowed
fixed stuff              # No type, vague
feat: Add New Feature.   # Trailing period, wrong case
update                   # No type, no scope
WIP                      # Never commit WIP to shared branches
Do not add Co-Authored-By lines for Anthropic or Claude in commit messages.
03

Pull Request Standards

PRs are the primary quality gate. Every PR must be reviewable, well-described, and appropriately sized.

PR Size Limits

Under 400 lines Target
400–1000 lines Needs justification
1000+ lines Not allowed

If your PR is growing large, split it into logical, independently reviewable chunks. Each chunk should be functional on its own.

PR Title

Follow the same Conventional Commits format as commit messages:

example
feat(agent): add retry logic for failed sandbox executions

Required PR Description

Every PR must include all of the following sections:

markdown
## Summary

- Added retry logic for sandbox execution failures
- Implements exponential backoff with max 3 retries
- Addresses intermittent timeout issues reported in #142

## Related Issue
Fixes #142

## Type of Change
- [ ] New feature
- [ ] Bug fix
- [ ] Refactor
- [ ] Documentation
- [ ] CI/CD
- [ ] Other (describe)

## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing performed (describe steps)
- [ ] Feature flag verified in staging

## Self-Review Checklist
- [ ] Code follows project conventions
- [ ] No secrets, API keys, or tokens committed
- [ ] No console.log or debug statements left in
- [ ] No any types in TypeScript
- [ ] Feature flag wraps new functionality
- [ ] Database migrations are backward-compatible
- [ ] Error handling follows project patterns
- [ ] Accessibility checked (if UI change)

Review Rules

Minimum 1 approval required
All CI checks must pass. Do not merge your own PR without at least one review.
Resolve all review comments before merging
Use "Request Changes" for blocking issues, "Comment" for non-blocking suggestions.
04

Feature Flags

Every new feature, UI change, or behavioral modification must be wrapped in a feature flag. No exceptions.

Safe Rollback
Revert without redeployment
Gradual Rollout
10% → 50% → 100% of users
A/B Testing
Validate before full release
Decouple Deploy
Ship code, release separately

Implementation

typescript
// Use the feature flag hook
const { isEnabled } = useFeatureFlag('new-thread-ui');

if (isEnabled) {
  return <NewThreadUI />;
}
return <LegacyThreadUI />;
python
from utils.feature_flags import is_feature_enabled

async def process_request(team_id: str):
    if await is_feature_enabled("new-billing-logic", team_id):
        return await new_billing_flow()
    return await legacy_billing_flow()

Feature Flag Lifecycle

1
Create
Add the flag before starting development. Default: OFF
2
Develop
All new code lives behind the flag
3
Test
Enable in staging, run full test suite
4
Release
Gradually enable: 10% → 50% → 100%
5
Cleanup
Stable 2+ weeks at 100%? Remove flag and dead code

Naming Convention

format
<domain>-<feature-description>

Examples:
agent-retry-logic
billing-new-checkout
thread-markdown-preview
05

Security & Secrets

Committing secrets is a zero-tolerance policy. In regulated environments, this is a terminable offense.

Zero Tolerance. Committing API keys, tokens, passwords, or credentials to source code is a terminable offense in regulated environments. If you accidentally commit a secret, notify the team immediately — the secret must be rotated, not just removed from history.

Banned from Source Code

API keys (Anthropic, Gemini, Stripe, Tavily, Daytona, etc.)
Database connection strings
JWT secrets or signing keys
OAuth client secrets
AWS credentials or access keys
Any .env or .env.local file contents
Private keys, certificates, or PEM files

Where Secrets Belong

EnvironmentMethod
Local development.env / .env.local files (already in .gitignore)
CI/CDGitHub Actions secrets or environment variables
Staging / ProductionAWS Secrets Manager / environment variables

Pre-Commit Checks

Do not bypass the pre-commit hook
A hook scans for potential secrets before allowing commits. Never use --no-verify to bypass it.

Frontend-Specific Security

Never expose server-side keys via NEXT_PUBLIC_ prefix
Never use dangerouslySetInnerHTML without DOMPurify sanitization
Set auth cookies as HttpOnly, Secure, SameSite=Strict
Never return raw exception details to the client

Backend-Specific Security

Use secrets module for OTP/token generation — never random
Use hmac.compare_digest for secret comparison — never ==
Never log PII in plaintext — always mask emails, phone numbers, names
Encrypt PII fields at rest. Use verified SSL for all DB and API connections.
06

Environment & Tooling

All developers must use the exact versions specified in mise.toml. Use mise to manage tool versions automatically.

Required Tool Versions

Node.js
20
🐍
Python
3.11.10
UV
0.6.5

Running Commands in the Right Directory

Running npm install from the project root creates a rogue node_modules/ and package-lock.json in the root — this breaks the build and pollutes the repo.
CommandRun FromNot From
npm installfrontend/Never from project root
npm run devfrontend/Never from project root
npm run buildfrontend/Never from project root
uv syncbackend/Never from project root
uv run api.pybackend/Never from project root
uv run pytestbackend/Never from project root
docker compose upProject root (he2-beta/)Not from subdirectories
python setup.pyProject root (he2-beta/)Not from subdirectories

Local Development Setup

bash
# 1. Clone and enter the repo
git clone <repo-url> && cd he2-beta

# 2. Run the setup wizard
python setup.py

# 3. Install frontend dependencies
cd frontend && npm install

# 4. Install backend dependencies
cd ../backend && uv sync

# 5. Start Redis (required for backend)
docker compose up redis

# 6. Start backend (new terminal, from backend/)
cd backend && source .venv/bin/activate && uv run api.py

# 7. Start frontend (new terminal, from frontend/)
cd frontend && npm run dev

Environment Variables

env
REDIS_HOST=localhost          # use 'redis' inside Docker
ANTHROPIC_API_KEY=...          # LLM provider
GEMINI_API_KEY=...             # LLM provider
DAYTONA_API_KEY=...            # Sandbox provider
TAVILY_API_KEY=...             # Web search
env
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000/api
NEXT_PUBLIC_ENV_MODE=development
07

Frontend Standards

TypeScript strict mode, shadcn/ui components, Tailwind CSS 4, and React Query. These are non-negotiable defaults.

TypeScript

Strict mode — no exceptions
TypeScript strict mode must be enabled in tsconfig.json.
No any types
Use proper typing or unknown if truly needed. any defeats the purpose of TypeScript.
Type all props, API responses, and state
Use TypeScript interfaces or types for everything. No implicit any.

Components

Always use shadcn/ui components from components/ui/
Never use raw HTML elements like <button>, <input>, <select> directly.
Always use Remix Icons via <i className="ri-icon-name-line">
Never import from react-icons. Remix Icons is the only icon library.
Functional components with hooks only
No class components. Keep components focused and small.

State Management

WhatTool
Server state (API data)React Query (@tanstack/react-query)
Global client stateZustand stores (stores/)
Local component stateuseState / useReducer
Form stateReact Hook Form

Styling

Tailwind CSS 4
All styling — no inline style={{}} attributes
shadcn/ui + DaisyUI
Component primitives
CSS Variables
For theming — no hardcoded colors

Code Quality

No console.log in committed code
Use proper logging or remove. Run npm run lint before pushing.
No commented-out code blocks
Delete them. Git has history — you can always recover deleted code.
No unused imports or variables
Run npm run format:check before pushing.
08

Backend Standards

Python with full type annotations, async/await for all I/O, Pydantic models, and domain-driven structure.

Python Rules

All functions must have type annotations
No untyped functions. Use Pydantic models for all request/response schemas.
Use async/await for all I/O operations
Database calls, API calls, file I/O — all must be async.

Domain-Driven Structure

structure
domain/
└── <feature>/
    ├── api/          # Routes
    ├── service/      # Business logic
    ├── repository/   # Data access
    └── models/       # Pydantic models

Database

All database operations use asyncpg (async)
Migrations go in backend/supabase/migrations/ as SQL files
Migrations must be backward-compatible — never drop columns that production code still reads.
Use parameterized queries — never string-concatenate SQL
SQL injection is a critical vulnerability. Always use parameterized queries.
Always add indexes for columns used in WHERE clauses or JOINs

Error Handling

Never expose internal error details to the client
Use structured error responses with appropriate HTTP status codes.
Never catch and silently swallow exceptions
Log errors with context using structlog. Every exception must be handled or re-raised.

LLM Integration

All LLM calls go through the LiteLLM abstraction
Located at infrastructure/llm/. Never call LLM providers directly.
Never hardcode model names — use configuration
Always handle rate limits and timeouts gracefully.
09

Testing Standards

70% minimum coverage threshold. PRs that drop coverage below this will be blocked by CI.

70%min
Minimum Coverage Threshold
PRs that drop backend test coverage below 70% will be automatically blocked by CI. Write tests for all new business logic.

Backend — pytest Markers

MarkerWhen to Use
@pytest.mark.unitNo external dependencies needed
@pytest.mark.integrationRequires DB, Redis, or external services
@pytest.mark.propertyHypothesis property-based tests
@pytest.mark.slowTests that take >5 seconds
bash
# Run unit tests before pushing
uv run pytest -m "not integration"

Frontend Testing

Write tests for utility functions and hooks
Use React Testing Library for component tests
Test user interactions, not implementation details.
Mock external services, not internal ones
bash
# Run tests before pushing
npm test
10

Code Review Checklist

Use this checklist when reviewing or self-reviewing a PR. Every item must be checked before requesting a merge.

General
Code Quality
Security
Architecture
Testing
0 / 23 checked

Quick Reference Card

Everything you need at a glance. Bookmark this section.

Branch
feature/HE2-123-add-widget
Commit
feat(widget): add interactive widget to dashboard
PR Title
feat(widget): add interactive widget to dashboard
PR Size
< 400 lines
Secrets
.env only, never in code
npm
Run from frontend/, NEVER from root
uv
Run from backend/
Feature Flags
All new features behind flags
Branches
Deleted after merge
Tests
Required · 70% coverage minimum
Types
No any in TS · type all Python functions
Compliance
SOC 2 Type 2 · GDPR
SOC 2 Type 2 & GDPR Compliance
Helium is pursuing SOC 2 Type 2 and GDPR compliance. Any code touching authentication, user data, encryption, or access control must follow the policies in compliance/policies/. When in doubt, ask before shipping.