Skip to main content

Code Style

UniPulse follows consistent coding conventions across the entire monorepo. TypeScript strict mode is enabled everywhere.


General Principles

PrincipleDetails
TypeScript everywhereStrict mode enabled in all packages
Functional patternsPrefer functions and objects over classes
Named exportsPrefer named exports over default exports
Absolute importsUse path aliases (@/, @unipulse/shared)
No anyAvoid any type -- use unknown if type is truly unknown
Explicit return typesAdd return types to service functions

Naming Conventions

ItemConventionExample
Files (services)kebab-case.service.tspost.service.ts, ai-advisor.service.ts
Files (routes)kebab-case.routes.tspost.routes.ts, ab-test.routes.ts
Files (types)kebab-case.types.tspost.types.ts, brand-voice.types.ts
Files (validators)kebab-case.validators.tspost.validators.ts
Files (queues)kebab-case.queue.tspublish.queue.ts
ComponentsPascalCase.tsxPostCard.tsx, DataTable.tsx
Storeskebab-case.store.tsauth.store.ts, ui.store.ts
Hooksuse-kebab-case.tsuse-posts.ts, use-workspace.ts
FunctionscamelCasegetPostById, generateCaption
ConstantsUPPER_SNAKE_CASEMAX_RETRY_COUNT, PROMPT_CONFIGS
Types/InterfacesPascalCaseCreatePostInput, WorkflowNode
EnumsPascalCase (type), UPPER_SNAKE_CASE (values)Role.ADMIN, Platform.FACEBOOK
Database fieldscamelCasecreatedAt, workspaceId
Environment variablesUPPER_SNAKE_CASEDATABASE_URL, JWT_SECRET
Queue nameskebab-caseanalytics-sync, ice-process

File Organization

RuleDetails
One service per filepost.service.ts contains all post-related business logic
One component per filePostCard.tsx exports a single component
Group by feature domainpages/analytics/, services/analytics.service.ts
Index files for re-exportscomponents/ui/index.ts for barrel exports
Co-locate testsservices/__tests__/post.service.test.ts

Backend Patterns

Service Pattern

// apps/api/src/services/example.service.ts
import { prisma } from '../lib/prisma';
import type { CreateExampleInput } from '@unipulse/shared';

export const exampleService = {
async getAll(workspaceId: string): Promise<Example[]> {
return prisma.example.findMany({
where: { workspaceId },
orderBy: { createdAt: 'desc' },
});
},

async create(workspaceId: string, data: CreateExampleInput): Promise<Example> {
return prisma.example.create({
data: { ...data, workspaceId },
});
},
};

Route Pattern

// apps/api/src/routes/example.routes.ts
import { Router } from 'express';
import { authenticate } from '../middleware/auth';
import { requireWorkspace } from '../middleware/requireWorkspace';
import { validate } from '../middleware/validate';
import { createExampleSchema } from '@unipulse/shared';
import { exampleService } from '../services/example.service';

const router = Router();

router.get('/', authenticate, requireWorkspace('VIEWER'), async (req, res, next) => {
try {
const items = await exampleService.getAll(req.workspace.id);
res.json(items);
} catch (error) {
next(error);
}
});

router.post('/', authenticate, requireWorkspace('EDITOR'), validate(createExampleSchema), async (req, res, next) => {
try {
const item = await exampleService.create(req.workspace.id, req.body);
res.status(201).json(item);
} catch (error) {
next(error);
}
});

export default router;

Frontend Patterns

Component Pattern

// apps/web/src/pages/examples/ExampleList.tsx
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { DataTable } from '@/components/data-table';
import type { Example } from '@unipulse/shared';

export function ExampleList() {
const { t } = useTranslation('examples');
const { data, isLoading } = useQuery<Example[]>({
queryKey: ['examples'],
queryFn: () => api.examples.getAll(),
});

if (isLoading) return <Skeleton />;

return (
<div>
<h1>{t('title')}</h1>
<DataTable data={data ?? []} columns={columns} />
</div>
);
}

Store Pattern

// apps/web/src/stores/example.store.ts
import { create } from 'zustand';

interface ExampleState {
selectedId: string | null;
setSelected: (id: string | null) => void;
}

export const useExampleStore = create<ExampleState>((set) => ({
selectedId: null,
setSelected: (id) => set({ selectedId: id }),
}));

Code Quality Rules

RuleToolEnforcement
Zod for all validation@unipulse/shared validatorsMiddleware + zodResolver
Prisma for all DB access@prisma/clientNo raw SQL unless necessary
TanStack Query for API calls@tanstack/react-queryNo manual fetch in components
Workspace scopingworkspaceId in every queryService layer convention
Error handling at boundariesAppError + global handlerDon't catch silently
Translation for all user-facing textreact-i18nextt() function, never hardcoded strings
Logical CSS propertiesTailwind v4 ms-, me-, ps-, pe-RTL support

Import Order

// 1. Node.js built-ins
import path from 'path';

// 2. External packages
import { Router } from 'express';
import { z } from 'zod';

// 3. Internal packages
import type { Post } from '@unipulse/shared';

// 4. Local imports
import { prisma } from '../lib/prisma';
import { postService } from '../services/post.service';

Cross-Reference