Skip to content

Coding Conventions

This page documents all coding patterns enforced in the Juca codebase. Following these conventions ensures consistency and makes the codebase predictable for both human and AI contributors.

ContextConventionExample
ComponentsPascalCaseWorkCanvas.tsx, PhaseRail.tsx
HookscamelCase with use prefixuseFeatureFlag, useSSEStream
Server ActionscamelCaseupdateDiagnosis, evaluatePrecedent
API routeskebab-case directoriesdocument-metadata/, validate-processo/
Block typessnake_caserisk_balance, exit_card, action_prompt
Feature flagscamelCaseunifiedHome, deepMode
CSS tokenskebab-case with -- prefix--color-primary, --radius-xl

The codebase uses two auth patterns. Never mix them:

Server Actions — Use requireActionAuth():

src/actions/briefing.ts
'use server';
import { requireActionAuth } from '@/actions/utils';
export async function updateDiagnosis(sessionId: string, fields: object) {
const user = await requireActionAuth(); // throws if unauthorized
// ...
}

API Routes — Use auth() directly:

src/app/api/unified/sessions/route.ts
import { auth } from '@/lib/auth';
export async function GET() {
const session = await auth();
if (!session?.user) return new Response('Unauthorized', { status: 401 });
// ...
}

Always use factory helpers to create blocks:

import { createDiagnosisData } from '@/lib/blocks/types';
import { getBlocksDB } from '@/lib/db/sessions';
const blockData = createDiagnosisData(analysis);
await getBlocksDB().addBlock({
sessionId,
type: 'diagnosis',
data: blockData
});

Route parameters in Next.js 16 are Promise-based:

export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params; // Must await!
// ...
}
feat(scope): description # New feature
fix(scope): description # Bug fix
docs: description # Documentation only
chore: description # Maintenance, dependencies

Scopes: rewrite, briefing, deploy, lint, test, auth, etc.

All commits include a co-author header:

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Tailwind v4 CSS-first approach — tokens in src/app/globals.css:

:root {
--color-primary: #000000;
--color-accent: #fff06d;
--color-bg-primary: #ffffff;
}

Available animation utilities:

ClassEffect
animate-fade-in300ms fadeIn (translateY 10px→0, opacity 0→1)
spring-transitioncubic-bezier(0.34, 1.56, 0.64, 1) for spring feel
animate-pulseBuilt-in Tailwind pulse
scroll-smooth-blockSmooth scroll behavior

For staggered animations:

<div style={{
animationDelay: `${index * 100}ms`,
animationFillMode: 'backwards'
}}>

All imports use the @/ alias. Order:

// 1. React / Next.js
import React, { useState } from 'react';
import { NextResponse } from 'next/server';
// 2. External libraries
import { jsPDF } from 'jspdf';
// 3. Internal libraries
import { auth } from '@/lib/auth';
import { getBlocksDB } from '@/lib/db/sessions';
// 4. Components
import { WorkCanvas } from '@/components/canvas/WorkCanvas';
// 5. Types
import type { Block, BlockType } from '@/types/blocks';
  • TypeScript strict mode — all code must pass tsc without errors
  • ESLint with Next.js rules (flat config in eslint.config.mjs)
  • No Prettier — ESLint handles formatting
  • No console.log in production code — use the centralized logger at src/lib/logger.ts