forked from cardosofelipe/fast-next-template
- Create docs/development/WORKFLOW.md with branch strategy, issue management, testing requirements, and code review process - Create docs/development/CODING_STANDARDS.md with technical patterns, auth DI pattern, testing patterns, and security guidelines - Streamline CLAUDE.md to link to detailed documentation instead of embedding all content - Add branch/issue workflow rules: single branch per feature for both design and implementation phases 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
7.6 KiB
7.6 KiB
Coding Standards
Technical coding standards and patterns for Syndarix development.
Table of Contents
Backend Standards
Dependency Management
- Use uv (modern Python package manager), not pip
- Always use
uv runprefix for commands - Add dependencies:
uv add <package>oruv add --dev <package>
# Running tests
IS_TEST=True uv run pytest
# Or use Makefile
make test
make install-dev
Database Migrations
- Use the
migrate.pyhelper script, not Alembic directly - Never commit migrations without testing them first
# Generate and apply migration
python migrate.py auto "message"
# Check current state
python migrate.py current
Authentication Testing Fixtures
Backend fixtures in tests/conftest.py:
| Fixture | Purpose |
|---|---|
async_test_db |
Fresh SQLite per test |
async_test_user |
Pre-created regular user |
async_test_superuser |
Pre-created admin user |
user_token |
Access token for regular user |
superuser_token |
Access token for admin |
# Always use these decorators for async tests
@pytest.mark.asyncio
async def test_something():
pass
# Use for async fixtures
@pytest_asyncio.fixture
async def my_fixture():
pass
Database Exception Mocking
from unittest.mock import patch, AsyncMock
async def mock_commit():
raise OperationalError("Connection lost", {}, Exception())
with patch.object(session, 'commit', side_effect=mock_commit):
with patch.object(session, 'rollback', new_callable=AsyncMock) as mock_rollback:
with pytest.raises(OperationalError):
await crud_method(session, obj_in=data)
mock_rollback.assert_called_once()
Security Considerations
- Backend has comprehensive security tests (JWT attacks, session hijacking)
- Never skip security headers in production
- Rate limiting:
@limiter.limit("10/minute") - Session revocation is database-backed, not just JWT expiry
Frontend Standards
Auth Store Dependency Injection
CRITICAL: ALWAYS use useAuth() from AuthContext, NEVER import useAuthStore directly!
// ❌ WRONG - Bypasses dependency injection
import { useAuthStore } from '@/lib/stores/authStore';
const { user, isAuthenticated } = useAuthStore();
// ✅ CORRECT - Uses dependency injection
import { useAuth } from '@/lib/auth/AuthContext';
const { user, isAuthenticated } = useAuth();
Why This Matters:
- E2E tests inject mock stores via
window.__TEST_AUTH_STORE__ - Unit tests inject via
<AuthProvider store={mockStore}> - Direct
useAuthStoreimports bypass this injection → tests fail - ESLint will catch violations
Exceptions:
AuthContext.tsx- DI boundary, legitimately needs real storeclient.ts- Non-React context, uses dynamic import +__TEST_AUTH_STORE__check
API Client Generation
# After backend schema changes
npm run generate:api
- Client is auto-generated from OpenAPI spec
- Located in
frontend/src/lib/api/generated/ - NEVER manually edit generated files
Component Development
- Follow design system docs in
frontend/docs/design-system/ - Read
08-ai-guidelines.mdfor AI code generation rules - Use parent-controlled spacing (see
04-spacing-philosophy.md) - WCAG AA compliance required (see
07-accessibility.md)
Route Groups Structure
src/app/[locale]/
├── (auth)/ # Public auth pages (login, register, password reset)
│ # Uses AuthLayoutClient - redirects authenticated users
├── (authenticated)/ # Protected app pages
│ # Uses AuthGuard + Header/Footer
├── admin/ # Admin pages with sidebar
│ # Uses AuthGuard requireAdmin
├── dev/ # Design system documentation
└── prototypes/ # UI prototypes for approval
Testing Patterns
Frontend Unit Tests
// Mock useAuth correctly
jest.mock('@/lib/auth/AuthContext', () => ({
useAuth: () => ({
user: { id: '1', email: 'test@example.com' },
isAuthenticated: true,
}),
}));
E2E Test Best Practices (Playwright)
Navigation Pattern:
// ✅ CORRECT - Use Promise.all for Next.js Link clicks
await Promise.all([
page.waitForURL('/target', { timeout: 10000 }),
link.click()
]);
Selectors:
- Use ID-based selectors for validation errors:
#email-error - Error IDs use dashes not underscores:
#new-password-error - Target
.border-destructive[role="alert"]to avoid Next.js route announcer conflicts - Avoid generic
[role="alert"]which matches multiple elements
URL Assertions:
// ✅ Use regex to handle query params
await expect(page).toHaveURL(/\/auth\/login/);
// ❌ Don't use exact strings (fails with query params)
await expect(page).toHaveURL('/auth/login');
Configuration:
- Uses 12 workers in non-CI mode
- Reduces to 2 workers in CI for stability
Backend E2E Testing
Requires Docker for Testcontainers.
# Install deps
make install-e2e
# Run all E2E tests
make test-e2e
# Run schema tests only
make test-e2e-schema
# Run all tests (unit + E2E)
make test-all
Uses:
- Testcontainers (real PostgreSQL)
- Schemathesis (OpenAPI contract testing)
Markers:
@pytest.mark.e2e@pytest.mark.postgres@pytest.mark.schemathesis
See: backend/docs/E2E_TESTING.md for complete guide.
Security Guidelines
OWASP Top 10 Compliance
All code must be reviewed for:
- Injection vulnerabilities (SQL, command, XSS)
- Broken authentication
- Sensitive data exposure
- Security misconfiguration
- Insecure deserialization
Rate Limiting
from app.core.limiter import limiter
@router.post("/endpoint")
@limiter.limit("10/minute")
async def endpoint():
pass
JWT Security
- Tokens stored securely (httpOnly cookies preferred)
- Short expiration times
- Refresh token rotation
- Database-backed session revocation
Common Workflows
Adding a New Feature
- Start with backend schema and CRUD
- Implement API route with proper authorization
- Write backend tests (aim for >90% coverage)
- Generate frontend API client:
npm run generate:api - Implement frontend components
- Write frontend unit tests
- Add E2E tests for critical flows
- Update relevant documentation
Fixing Tests
| Layer | Check |
|---|---|
| Backend | Test database isolation, async fixture usage |
| Frontend unit | Mock useAuth() not useAuthStore |
| E2E | Use Promise.all() pattern, regex URL assertions |
Debugging
| Layer | Action |
|---|---|
| Backend | Check IS_TEST=True environment variable |
| Frontend | Run npm run type-check first |
| E2E | Use npm run test:e2e:debug for step-by-step |
| All | Check logs - backend has detailed error logging |
Demo Mode
Frontend-only showcase mode for demos without backend.
# Enable
echo "NEXT_PUBLIC_DEMO_MODE=true" > frontend/.env.local
- Uses MSW (Mock Service Worker) to intercept API calls
- Zero backend required - perfect for Vercel deployments
- MSW handlers auto-generated from OpenAPI spec
- Run
npm run generate:api→ updates both API client AND MSW handlers
Demo Credentials:
- User:
demo@example.com/DemoPass123 - Admin:
admin@example.com/AdminPass123
Safety:
- MSW never runs during tests (Jest or Playwright)
- Mock files excluded from linting and coverage
See: frontend/docs/DEMO_MODE.md for complete guide.