Files
pos-system/docs/en/skills/project-rules.md
Ho Ngoc Hai 2640b351c3 Enhance documentation with detailed diagrams and structured flows
- Added request/response flow diagrams to api-design and api-gateway-advanced skills for better visualization of processes.
- Introduced configuration loading flow in configuration-management skill to clarify the configuration process.
- Included error propagation flow in error-handling-patterns skill to illustrate error handling across layers.
- Enhanced various skills with additional diagrams to improve understanding of complex concepts.

These updates aim to provide clearer guidance and improve the overall documentation experience for developers.
2026-01-01 23:22:54 +07:00

401 lines
13 KiB
Markdown

---
name: project-rules
description: GoodGo Microservices Platform coding standards and architecture patterns. Use when working with services, apps, packages, or infrastructure.
---
# GoodGo Project Rules
## Architecture
**Monorepo Structure:**
- **Apps**: Next.js (web) + Flutter (mobile)
- **Services**: Node.js/TypeScript microservices (Express)
- **Packages**: Shared libraries (logger, types, http-client, auth-sdk, tracing)
- **Infrastructure**: Traefik (API Gateway), Redis, Neon PostgreSQL, Observability
- **Deployments**: Local (Docker Compose), Staging/Production (Kubernetes)
**Template Location**: `services/_template/` - Use as starting point for new services
### Monorepo Architecture
```mermaid
graph TB
subgraph apps[Apps Layer]
webAdmin[web-admin<br/>Next.js Admin]
webClient[web-client<br/>Next.js Client]
appAdmin[app-admin<br/>Flutter Admin]
appClient[app-client<br/>Flutter Client]
end
subgraph gateway[API Gateway]
traefik[Traefik<br/>Path-based Routing]
end
subgraph services[Services Layer]
iamService[iam-service<br/>IAM Service]
templateService[_template<br/>Service Template]
otherServices[Other Services<br/>Node.js/TypeScript]
end
subgraph packages[Shared Packages]
loggerPackage[@goodgo/logger<br/>Centralized Logging]
typesPackage[@goodgo/types<br/>TypeScript Types]
httpClientPackage[@goodgo/http-client<br/>API Client]
authSdkPackage[@goodgo/auth-sdk<br/>Auth Utilities]
tracingPackage[@goodgo/tracing<br/>OpenTelemetry]
configPackage[@goodgo/config<br/>Shared Configs]
end
subgraph infrastructure[Infrastructure]
postgres[Neon PostgreSQL<br/>Database]
redis[Redis<br/>Cache]
prometheus[Prometheus<br/>Metrics]
grafana[Grafana<br/>Dashboards]
loki[Loki<br/>Log Aggregation]
end
subgraph deployments[Deployments]
dockerCompose[Docker Compose<br/>Local Development]
kubernetes[Kubernetes<br/>Staging/Production]
end
webAdmin --> traefik
webClient --> traefik
appAdmin --> traefik
appClient --> traefik
traefik --> iamService
traefik --> otherServices
iamService --> packages
otherServices --> packages
iamService --> postgres
otherServices --> postgres
iamService --> redis
otherServices --> redis
services --> prometheus
services --> loki
prometheus --> grafana
loki --> grafana
services --> deployments
```
## Tech Stack
**Frontend:**
- Next.js 14+ (App Router), TypeScript, Tailwind CSS, Zustand
- Flutter 3.x with Provider pattern
- Use `@goodgo/types` and `@goodgo/http-client`
**Backend:**
- Node.js 20+, TypeScript 5+, Express
- Prisma ORM + Neon PostgreSQL
- Zod validation, `@goodgo/logger`, `@goodgo/tracing`, `@goodgo/auth-sdk`
**Infrastructure:**
- Traefik (path-based routing), Redis (cache), Prometheus + Grafana + Loki
## Project Structure
**Service:** `src/{config,modules,middlewares,routes,main.ts}` + `prisma/` + `Dockerfile`
**Package:** `src/index.ts` + `package.json` + `tsconfig.json` + `README.md`
**App:** `src/{app,services/api,stores}` + `Dockerfile`
### Detailed Structure Diagram
```mermaid
graph TB
subgraph service[Service Structure]
serviceRoot[service-name/]
serviceSrc[src/]
serviceConfig[config/<br/>Configuration]
serviceModules[modules/<br/>Feature Modules]
serviceMiddlewares[middlewares/<br/>Express Middlewares]
serviceRoutes[routes/<br/>Route Definitions]
serviceMain[main.ts<br/>Entry Point]
servicePrisma[prisma/<br/>Schema & Migrations]
serviceDockerfile[Dockerfile<br/>Container Definition]
servicePackageJson[package.json<br/>Dependencies]
serviceRoot --> serviceSrc
serviceRoot --> servicePrisma
serviceRoot --> serviceDockerfile
serviceRoot --> servicePackageJson
serviceSrc --> serviceConfig
serviceSrc --> serviceModules
serviceSrc --> serviceMiddlewares
serviceSrc --> serviceRoutes
serviceSrc --> serviceMain
end
subgraph package[Package Structure]
packageRoot[package-name/]
packageSrc[src/]
packageIndex[index.ts<br/>Main Export]
packagePackageJson[package.json<br/>Package Metadata]
packageTsconfig[tsconfig.json<br/>TypeScript Config]
packageReadme[README.md<br/>Documentation]
packageRoot --> packageSrc
packageRoot --> packagePackageJson
packageRoot --> packageTsconfig
packageRoot --> packageReadme
packageSrc --> packageIndex
end
subgraph app[App Structure - Next.js]
appRoot[app-name/]
appSrc[src/]
appApp[app/<br/>Next.js App Router]
appServicesApi[services/api/<br/>API Clients]
appStores[stores/<br/>State Management]
appDockerfile[Dockerfile<br/>Container Definition]
appPackageJson[package.json<br/>Dependencies]
appRoot --> appSrc
appRoot --> appDockerfile
appRoot --> appPackageJson
appSrc --> appApp
appSrc --> appServicesApi
appSrc --> appStores
end
subgraph module[Module Structure inside modules/]
moduleRoot[modules/feature-name/]
moduleController[feature.controller.ts<br/>HTTP Handlers]
moduleService[feature.service.ts<br/>Business Logic]
moduleRepository[feature.repository.ts<br/>Data Access]
moduleDto[feature.dto.ts<br/>Zod Schemas]
moduleTypes[feature.types.ts<br/>TypeScript Types]
moduleTest[feature.controller.test.ts<br/>Unit Tests]
moduleRoot --> moduleController
moduleRoot --> moduleService
moduleRoot --> moduleRepository
moduleRoot --> moduleDto
moduleRoot --> moduleTypes
moduleRoot --> moduleTest
moduleController --> moduleService
moduleService --> moduleRepository
end
serviceModules --> moduleRoot
```
## Naming Conventions
- **Services/Packages**: `kebab-case` (e.g., `auth-service`, `http-client`)
- **Files**: `kebab-case.type.ts` (e.g., `user.controller.ts`)
- **Components**: `PascalCase.tsx` (React), `snake_case.dart` (Flutter)
- **Classes**: `PascalCase`, **Functions**: `camelCase`, **Constants**: `UPPER_SNAKE_CASE`
- **Package Names**: `@goodgo/package-name`
## Workflows
**New Service:**
1. Copy `services/_template/`
2. Update `package.json` name to `@goodgo/service-name`
3. Add to `deployments/local/docker-compose.yml` with Traefik labels
4. Configure Prisma schema if needed
5. Add health check endpoint
**New Package:**
1. Create in `packages/`, export from `src/index.ts`
2. Add to `pnpm-workspace.yaml`
3. Use TypeScript strict mode
**Dependencies:**
```bash
pnpm --filter @goodgo/service-name add package-name
pnpm --filter @goodgo/service-name add @goodgo/logger # workspace
pnpm --filter @goodgo/service-name add -D @types/pkg # dev
```
**Database:**
```bash
pnpm --filter @goodgo/service-name prisma migrate dev
pnpm --filter @goodgo/service-name prisma generate
```
## Code Standards
**TypeScript:**
- Strict mode, no `any` (use `unknown`)
- Zod for runtime validation
- Export shared types from `@goodgo/types`
**API Responses:**
```typescript
// Success: { success: true, data: any }
// Error: { success: false, error: { code, message, details? } }
```
**Logging:**
```typescript
import { logger } from '@goodgo/logger';
logger.info('Message', { context });
logger.error('Error', { error, context });
```
**Environment:**
- Use `.env.example` template, never commit `.env`
- Validate with Zod at startup
- Document all vars in README
## Testing
- **Unit**: Place tests next to source (`*.test.ts`), use Jest, mock dependencies, >80% coverage
- **Integration**: Test API endpoints, use test database, cleanup after
- **Commands**: `pnpm test`, `pnpm --filter @goodgo/service-name test`, `pnpm test:coverage`
## Docker
**Multi-stage Build Pattern:**
```dockerfile
FROM node:20-alpine AS builder
# ... build stage
FROM node:20-alpine
# ... production stage with non-root user
```
**Image Naming:** `goodgo/service-name:version` (semantic versioning)
## Git Workflow
**Branches:** `feature/`, `fix/`, `hotfix/`, `release/`
**Commits:** Conventional Commits format
```
type(scope): subject
```
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
**PRs:** Use template, link issues, ensure CI passes, squash merge to main
## CI/CD
**GitHub Actions:** PR (lint, test, build) → `develop` (staging) → `main` (production)
**Deployment Checklist:** Tests pass, no lint errors, env vars set, migrations applied, docs updated, monitoring configured
## Security
**Auth:** JWT (15min access, 7d refresh), httpOnly cookies, use `@goodgo/auth-sdk`
**Authorization:** RBAC, check permissions at service level, middleware for routes
**Data:** bcrypt (cost 12), HTTPS, sanitize inputs, Zod validation
**Secrets:** Environment variables, Kubernetes secrets, never hardcode, rotate regularly
## Performance
**Backend:** Redis caching, connection pooling, pagination, database indexes, rate limiting
**Frontend:** Next.js Image optimization, code splitting, lazy loading, React.memo, bundle optimization
**Database:** Prisma optimization, indexes, transactions, soft deletes
## Observability
**Metrics:** Prometheus (request count, duration, errors), set alerts
**Logging:** `@goodgo/logger` with trace IDs, levels (error, warn, info, debug), Loki aggregation
**Tracing:** OpenTelemetry via `@goodgo/tracing`, trace cross-service requests
## Documentation
**Code:** JSDoc for public APIs, inline comments for complex logic, README per service/package
**API:** OpenAPI/Swagger specs in `docs/api/openapi/`, document endpoints with examples
**Architecture:** System design in `docs/architecture/`, service communication, data flows, ADRs
## Architecture Patterns
**Modular Structure:** Controller → Service → Repository pattern
**DTO Validation:** Zod schemas with type inference
**Error Handling:** Custom error classes, global error middleware
**Dependency Injection:** Constructor injection for testability
**Example Module:**
```typescript
// DTO with Zod
export const CreateFeatureDto = z.object({
name: z.string().min(1),
email: z.string().email()
});
export type CreateFeatureDto = z.infer<typeof CreateFeatureDto>;
// Controller
export class FeatureController {
constructor(private service: FeatureService) {}
async create(req: Request, res: Response, next: NextFunction) {
try {
const dto = CreateFeatureDto.parse(req.body);
const result = await this.service.create(dto);
res.json({ success: true, data: result });
} catch (error) { next(error); }
}
}
// Service
export class FeatureService {
constructor(private repository: FeatureRepository) {}
async create(dto: CreateFeatureDto) {
return this.repository.create(dto);
}
}
// Repository
export class FeatureRepository extends BaseRepository<Feature> {
async create(data: CreateFeatureDto) {
return this.prisma.feature.create({ data });
}
}
```
## Deployment & Traefik
**Service Registration:**
Services are deployed via `deployments/local/docker-compose.yml` and auto-discovered by Traefik:
```yaml
services:
my-service:
build:
context: ../..
dockerfile: services/my-service/Dockerfile
labels:
- "traefik.enable=true"
- "traefik.http.routers.my-service.rule=PathPrefix(`/api/v1/my-service`)"
- "traefik.http.services.my-service.loadbalancer.server.port=5002"
- "traefik.http.services.my-service.loadbalancer.healthcheck.path=/health/live"
```
**Traefik Configuration:**
- **Location**: `infra/traefik/` (platform-level, not per-service)
- **Static Config**: `traefik.yml` - Entry points, providers, dashboard
- **Dynamic Config**: `dynamic/middlewares.yml`, `dynamic/routes.yml`
- **Dashboard**: http://localhost:8080
**Access Points:**
- API: `http://localhost/api/v1/service-name`
- Health: `http://localhost/api/v1/service-name/health`
- Docs: `http://localhost/api/v1/service-name/api-docs`
## Troubleshooting
**Common Issues:**
- Port conflicts: Check `deployments/local/docker-compose.yml`
- Database: Verify `DATABASE_URL` in `.env.local`
- Module not found: Run `pnpm install`
- Type errors: Run `pnpm --filter @goodgo/service-name prisma generate`
**Debug:**
```bash
cd deployments/local
docker-compose logs -f service-name
docker-compose ps
docker-compose up -d --build
```
## Resources
- [Architecture Docs](../../docs/architecture/)
- [API Specs](../../docs/api/openapi/)
- [Development Guide](../../docs/guides/development.md)
- [Deployment Guide](../../docs/guides/deployment.md)
- [Neon Database Guide](../../docs/guides/neon-database.md)
- [Contributing Guide](../../CONTRIBUTING.md)