Skip to main content
The microservices-app project follows industry-standard style guides adapted for our specific needs.

Overview

We use three primary style guides:
  • Go - Based on Google Go Style Guide
  • TypeScript/React - Based on Google TypeScript Style Guide
  • React Architecture - Based on bulletproof-react patterns
All style rules are enforced automatically through:
  • golangci-lint for Go code
  • Biome for TypeScript/React code
  • Pre-commit hooks that run on every commit

Go Style Guide

Our Go code follows the Google Go Style Guide with project-specific adaptations.

Key Conventions

Naming:
  • Exported names: PascalCase (e.g., NewService, RetryBudget)
  • Unexported names: camelCase (e.g., callExternal, retryCount)
  • Package names: lowercase, single word preferred (e.g., greeter, platform)
  • Acronyms: All uppercase or all lowercase (e.g., HTTP, ID, URL)
Error Handling:
  • Always check errors (enforced by errcheck)
  • Use errors.Is() and errors.As() for error comparison
  • Wrap errors with context using fmt.Errorf("...: %w", err)
  • Error strings start lowercase, no punctuation
Imports: Automatically grouped by goimports:
import (
    // Standard library
    "context"
    "fmt"

    // External libraries
    "connectrpc.com/connect"

    // Project packages
    "github.com/hackz-megalo-cup/microservices-app/services/internal/platform"
)
Concurrency:
  • Always make goroutine lifetimes explicit
  • Use context.Context for cancellation
  • Prefer sync.WaitGroup or errgroup over fire-and-forget goroutines
Testing:
  • Use table-driven tests for multiple test cases
  • Call t.Helper() in test helper functions

Enforcement

Run these commands to check and format Go code:
# Format all Go code
fmt

# Lint Go code
lint
Pre-commit hooks automatically:
  • Format code with goimports
  • Run golangci-lint
  • Run tests with go test

Complete Guide

For the full Go style guide with detailed examples and rationale, see:

TypeScript Style Guide

Our TypeScript code follows the Google TypeScript Style Guide with project-specific adaptations.

Key Conventions

File Naming:
  • Use kebab-case: my-component.tsx
  • Test files: .test.ts or .test.tsx
Imports:
// External libraries
import { useState } from "react";

// Project modules
import { transport } from "@/lib/transport";
Type System:
  • Never use any - use unknown with type guards instead
  • Never use object type - define specific interfaces
  • Use import type for type-only imports
  • Prefer type inference over explicit type annotations
  • Avoid non-null assertions (!) - use explicit checks
Naming:
  • Variables/functions: camelCase (e.g., userName, fetchData())
  • Types/interfaces/classes: PascalCase (e.g., UserProfile, AuthService)
  • Constants: CONSTANT_CASE (e.g., MAX_RETRY_COUNT)
  • Files: kebab-case (e.g., auth-panel.tsx)
Functions:
  • Top-level named functions: use function declarations
  • Callbacks and nested functions: use arrow functions
  • React components: use function declarations
// Top-level
export function GreeterDemo() {
  // Nested
  const handleClick = () => { ... };
}
Code Style:
  • Always use === and !== (never == or !=)
  • Always use braces, even for single-line statements
  • Use optional chaining ?. instead of && chains
  • No var - only const and let
  • No default exports (except in config files)

Enforcement

Run these commands to check and format TypeScript code:
# Format all TypeScript code
fmt

# Lint TypeScript code
lint
Pre-commit hooks automatically:
  • Format code with Biome
  • Run biome check for linting

Complete Guide

For the full TypeScript style guide with detailed examples, see:

React Architecture (bulletproof-react)

Our React frontend follows the bulletproof-react architecture pattern.

Directory Structure

src/
├── app/                    # Application entry point
│   ├── main.tsx
│   ├── App.tsx
│   └── providers/          # React providers
├── features/               # Feature-based modules
│   ├── auth/
│   │   ├── api/           # API calls
│   │   ├── components/    # UI components
│   │   ├── hooks/         # Custom hooks
│   │   └── types/         # Type definitions
│   ├── greeter/
│   └── gateway/
├── gen/                    # Generated code (buf)
├── interceptors/           # Connect-go interceptors
├── lib/                    # Shared utilities
├── testing/                # Test utilities (MSW)
└── types/                  # Shared types

Feature-First Design

Principles:
  • Each feature is an independent module
  • No direct imports between features
  • Shared code goes in lib/ or types/
  • Each feature has api/, components/, hooks/, and types/ subdirectories
Feature Structure:
  • api/ - External API communication logic
  • components/ - UI components (depend on hooks/api only)
  • hooks/ - Custom hooks wrapping API calls and state
  • types/ - TypeScript type definitions

connect-query Integration

Query Pattern (greeter):
const { data } = useQuery(greet, { name }, { enabled: false });
Mutation Pattern (gateway):
const mutation = useMutation(serviceMethod);

Adding New Features

  1. Create src/features/<feature-name>/ directory
  2. Add types/index.ts with type definitions
  3. Add api/ with API logic (REST with fetch or gRPC with connect-query)
  4. Add hooks/ with custom hooks
  5. Add components/ with UI components
  6. Import component in App.tsx

Complete Guide

For the complete architecture guide with patterns and examples, see:

Automated Enforcement

Pre-commit Hooks

All style rules are enforced automatically through Git pre-commit hooks:
  • treefmt - Formats Nix files
  • golangci-lint - Lints Go code
  • goimports - Formats Go imports
  • biome - Checks TypeScript/React code
  • go test - Runs Go tests
Hooks are configured in devenv.nix and run automatically on git commit.

Manual Commands

# Format everything and stage changes
fmt

# Lint everything without changes
lint

CI/CD Integration

The same checks run in CI pipelines to ensure code quality before merging.

Editor Configuration

VS Code

Recommended extensions:
  • Go (golang.go)
  • Biome (biomejs.biome)
  • Nix IDE (jnoortheen.nix-ide)
Recommended settings (.vscode/settings.json):
{
  "[go]": {
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.organizeImports": true
    }
  },
  "[typescript]": {
    "editor.defaultFormatter": "biomejs.biome",
    "editor.formatOnSave": true
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "biomejs.biome",
    "editor.formatOnSave": true
  }
}

Other Editors

Configure your editor to:
  • Run goimports on save for Go files
  • Run Biome formatter on save for TypeScript/React files
  • Integrate with golangci-lint for Go linting
  • Integrate with Biome for TypeScript linting

Contributing

When contributing code:
  1. Before committing: Run fmt to format all code
  2. Before pushing: Run lint to check for issues
  3. Fix all linting errors - Pre-commit hooks will block commits with errors
  4. Follow naming conventions - Use the appropriate case for your language
  5. Write tests - Follow the testing patterns in each style guide
  6. Document public APIs - Add comments for exported functions and types
The pre-commit hooks and CI checks ensure consistent code quality across the project.

Build docs developers (and LLMs) love