This file aggregates all RFC (Request for Comments) contribution guidelines that have landed.
This is a monorepo project using npm workspaces. All projects use strict TypeScript configuration ("strict": true in all tsconfig.json files), ensuring type safety across the entire codebase.
The monorepo contains multiple applications and shared packages:
Applications:
apps/api- Hono + OpenAPI REST API with tsyringe DIapps/deploy-web- Next.js frontend for deploying on Akash Networkapps/stats-web- Next.js frontend for network statisticsapps/indexer- Node.js blockchain indexer (Express, no DI)apps/notifications- NestJS service for handling notifications (NestJS built-in DI)apps/log-collector- Standalone log collector (vanilla Node.js + tsyringe)apps/provider-proxy- Hono service for proxying requests to providers (manual factory DI)apps/provider-console- Provider console applicationapps/tx-signer- Internal transaction signing service (Hono + tsyringe)
Shared Packages:
packages/database- Database shared package (Drizzle ORM schemas)packages/dev-config- Shared ESLint, TypeScript, and Prettier configspackages/docker- Docker build utilitiespackages/env-loader- Environment variable loading (uses@dotenvx/dotenvx)packages/http-sdk- HTTP client SDKpackages/instrumentation- OpenTelemetry instrumentation setuppackages/logging- Logging utilities (Pino-basedLoggerService)packages/net- Blockchain Network utilitiespackages/network-store- Network state managementpackages/react-query-proxy- React Query wrapper utilitiespackages/react-query-sdk- React Query SDK for console servicespackages/releaser- Release management utilitiespackages/ui- Shared UI components
- Node.js: >= 24.14.1 (enforced via Volta)
- Package Manager: npm 11.11.0
- Framework: Next.js 14.x, Hono, Nest.js
- Database: PostgreSQL with Drizzle ORM and legacy sequelize
- Monorepo: npm workspaces
- Testing: Vitest (primary), Jest (legacy in indexer & provider-console), Playwright (e2e), React Testing Library
- Styling: Material-UI, Emotion, Tailwind CSS
- State: React Query, Jotai
- Blockchain: Cosmos, Akash network
Build production images:
npm run dc:buildRun services in development mode:
npm run dc:up:devRun specific service with dependencies:
npm run dc:up:dev -- deploy-webStop all services:
npm run dc:downEach application has its own build script. Navigate to the app directory and run:
cd apps/<app-name>
npm run buildIMPORTANT: Before pushing, ALWAYS run in the affected app:
npm test(runs unit, integration, and functional tests)npm run lint -- --quietnpx tsc --noEmit
All applications and packages use Vitest for unit testing.
In applications:
# Run all unit tests
cd apps/<app-name>
npm run test:unit
# Run with watch mode
npm run test:unit -- --watchIn packages:
# Run tests for all packages
npm run test -w ./packages
# Run tests for a specific package
cd packages/<package-name>
npm testIntegration tests run against real infrastructure (database, etc.) and are currently used in apps/api.
- Naming:
*.integration.ts(colocated next to source files, like unit tests) - Running:
cd apps/api npm run test:integration - Setup: Requires Docker services running via
npm run test:ci-setup - Vitest project: Configured as a separate
integrationproject invitest.config.tswith its own setup files and extended timeouts (60s test, 30s hook)
Functional tests are available in apps/api, apps/notifications, apps/provider-proxy:
cd apps/<app-name>
npm run test:functional
# With watch mode
npm run test:functional -- --watchCI Setup/Teardown for Functional Tests:
Some services require Docker services to be running before functional tests can execute. These services provide test:ci-setup and test:ci-teardown scripts:
-
apps/api:cd apps/api npm run test:ci-setup # Start required Docker services npm run test:functional # Run functional tests npm run test:ci-teardown # Stop Docker services
-
apps/notifications:cd apps/notifications npm run test:ci-setup # Start database service npm run test:functional # Run functional tests npm run test:ci-teardown # Stop Docker services
These scripts use Docker Compose (dc) to manage test dependencies. The setup script starts services in detached mode (-d), and teardown stops all services.
E2E tests are available in apps/api, apps/deploy-web, apps/provider-proxy:
cd apps/deploy-web
npm run test:e2eE2E tests in deploy-web require:
- Playwright browsers installed:
npx playwright install - Test environment variables configured in
env/.env.testfile (see app-specific documentation)
To run both unit and functional tests together:
cd apps/<app-name>
npm testAll projects use strict TypeScript with the following key settings:
"strict": true- Enables all strict type checking options"noImplicitAny": true- Prevents implicitanytypes- Type checking is enforced via
validate:typesscripts in packages
Type checking packages:
# Check all packages
npm run validate:types -w ./packages
# Check specific package
cd packages/<package-name>
npm run validate:typesType checking applications:
cd apps/<app-name>
# or
npx tsc --noEmitThe project uses ESLint with a shared configuration from packages/dev-config. All code is automatically linted on commit via lint-staged and husky.
From the root:
# Lint entire monorepo
npm run lint
# Auto-fix linting issues
npm run lint:fixIn individual applications/packages:
cd apps/<app-name>
npm run lint
# Most apps also support auto-fix
npm run lint -- --fix- Base config:
packages/dev-config/.eslintrc.base.js- Common rules for all projects - TypeScript config:
packages/dev-config/.eslintrc.ts.js- TypeScript-specific rules - Next.js config:
packages/dev-config/.eslintrc.next.js- Next.js-specific rules for web apps - Root config:
.eslintrc.js- Monorepo-wide overrides
- Import sorting: Enforced via
eslint-plugin-simple-import-sort - Import validation:
eslint-plugin-import-xchecks for:- Extraneous dependencies
- Circular dependencies
- Self-imports
- Useless path segments
- TypeScript: Enforces consistent type imports and warns on
anytypes - Custom rules:
eslint-plugin-akashincludes project-specific rules (e.g.,akash/no-mnemonic)
The project uses semantic release with conventional commits for automated versioning and changelog generation. All commit messages must comply with the rules defined in commitlintrc.json.
Most backend apps use tsyringe for DI. The exception is apps/notifications (NestJS built-in DI) and apps/indexer (no DI — direct imports).
- Use
@singleton()for stateless services,@scoped(Lifecycle.ResolutionScoped)for request-scoped services - Register providers in
src/providers/files that are imported for side effects during bootstrap - Resolve services from the container via
container.resolve(ServiceClass)in route handlers
Routes use Hono with @hono/zod-openapi for type-safe, OpenAPI-documented endpoints:
import { createRoute } from "@src/core/lib/create-route/create-route";
import { OpenApiHonoHandler } from "@src/core/services/open-api-hono-handler/open-api-hono-handler";
const myRouter = new OpenApiHonoHandler();
const myRoute = createRoute({
method: "get",
path: "/v1/example",
tags: ["Example"],
security: SECURITY_BEARER_OR_API_KEY,
responses: { 200: { description: "Success", content: { "application/json": { schema: MyResponseSchema } } } }
});
myRouter.openapi(myRoute, async function routeGetExample(c) {
return c.json(await container.resolve(MyController).getExample(), 200);
});- Always use
createRoutefrom@src/core/lib/create-route/create-route(wraps@hono/zod-openapiwith cache-control and body-limit middleware) - Always use
OpenApiHonoHandler(wrapsOpenAPIHonowith centralized error handling) - Route handlers resolve controllers from the tsyringe container
- Error responses use the
http-errorspackage, not custom error classes
- Repositories extend
BaseRepository<T, Input, Output>from@src/core/repositories/base.repository - Built-in CRUD, pagination, CASL ability-based row filtering, and Drizzle ORM transaction support
- Use
DrizzleAbilityfor authorization at the data layer
All backend apps use these TypeScript path aliases (defined in tsconfig.build.json):
@src/*→./src/*@test/*→./test/*
- Naming:
*.spec.ts(not*.test.ts) - Location: Colocated next to source files (not in
__tests__/directories) - Mocking: Use
vitest-mock-extended(mock(),MockProxy<T>) - Environment:
@akashnetwork/env-loaderloads vars fromenv/.env.*.testfiles
See detailed guidelines: @./.claude/instructions/setup-function-instead-of-beforeeach-in-unit-service-level-tests.md
See detailed guidelines: @./.claude/instructions/use-logger-service-instead-of-console.md
See detailed guidelines: @./.claude/instructions/commit-and-pr-conventions.md
Always use the /console-tests skill when writing, fixing, reviewing, or refactoring tests in this repo.