Development Guide
This guide covers coding conventions, project structure, and development workflows.
Project Structure
tutornexus/
├── apps/
│ ├── api/ # Cloudflare Workers API (Hono + OpenAPI)
│ └── web/ # React frontend
├── services/
│ ├── mcp/ # Go MCP server
│ └── adapters/ # TypeScript adapter Workers
├── tools/
│ └── cli/ # Rust CLI
├── packages/ # Shared TypeScript packages
├── docs/ # Docusaurus documentation
├── d1/ # Database migrations
└── scripts/ # Utility scripts
Coding Conventions
TypeScript
// Use explicit types for function parameters and returns
function getUserById(id: string): User | null {
return db.users.find(u => u.id === id);
}
// Use interfaces for object shapes
interface Session {
id: string;
userId: string;
title: string;
status: SessionStatus;
createdAt: Date;
updatedAt: Date;
}
// Prefer const assertions for readonly data
const ADAPTERS = ['sfu', 'bcit', 'ubc'] as const;
Go
// Use error handling consistently
func (s *Server) HandleRequest(ctx context.Context, req Request) (*Response, error) {
if err := req.Validate(); err != nil {
return nil, fmt.Errorf("validation failed: %w", err)
}
result, err := s.service.Process(ctx, req)
if err != nil {
return nil, err
}
return &Response{Data: result}, nil
}
// Use structured logging
log.Info("processing request",
zap.String("request_id", req.ID),
zap.String("user_id", req.UserID),
)
Rust
// Use Result types for fallible operations
fn parse_config(path: &Path) -> Result<Config, ConfigError> {
let file = File::open(path)
.context("failed to open config file")?;
let config: Config = serde_yaml::from_reader(file)
.context("failed to parse config YAML")?;
Ok(config)
}
// Use anyhow for application errors
use anyhow::{Context, Result, bail};
Git Workflow
Commit Messages
We follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code style (formatting, no logic)refactor- Code restructuringperf- Performance improvementstest- Adding or modifying testschore- Build, CI, toolingbreaking- Breaking change
Examples:
feat(api): add tn_transfer_resolve tool
fix(mcp): handle missing course references
docs(adr): update ADR-012 with error conventions
refactor(cli): simplify REPL input handling
Branch Naming
feature/<issue-number>-<short-description>
bugfix/<issue-number>-<short-description>
docs/<short-description>
chore/<short-description>
Pull Requests
- Create a feature branch from
main - Make changes following conventions
- Run linting and tests locally
- Open PR with description
- Get required approvals
- Squash and merge
Testing
TypeScript Tests
# Run all tests
pnpm test
# Run with coverage
pnpm test:coverage
# Watch mode
pnpm test:watch
Go Tests
go test ./... -v
go test ./... -coverprofile=coverage.out
Rust Tests
cargo test
cargo test --doc
Linting
# TypeScript
pnpm lint
pnpm lint:fix
# Markdown
pnpm lint:markdown
# Commit messages
npx commitlint --from=main --to=HEAD
Building
# Build all packages
pnpm build
# Build individual packages
pnpm build:api
pnpm build:web
pnpm build:cli
pnpm build:docs
Development Tools
Database Management
# Setup local database
pnpm db:setup
# Run migrations
pnpm db:migrate
# Push schema changes
pnpm db:push
# Open D1 console
pnpm db:console
API Documentation
# Generate OpenAPI spec
pnpm api:generate
# Serve Swagger UI locally
pnpm api:docs
Debugging
Workers
# View logs
wrangler tail
# Viewtail in real-time
wrangler tail --project-name=tutor-nexus-api
Database
# Query local database
wrangler d1 execute tutor-nexus-api --local --command="SELECT * FROM users LIMIT 10"
Best Practices
Performance
- Use Cloudflare Durable Objects for real-time state
- Cache expensive operations with KV
- Batch database queries where possible
- Use pagination for list endpoints
Security
- Never commit secrets or API keys
- Use environment variables for credentials
- Validate all input with Zod schemas
- Use parameterized queries
- Implement rate limiting
Documentation
- Document all public APIs
- Write docstrings for complex functions
- Keep ADRs up to date
- Add code comments for non-obvious logic