Code style
Grafana’s codebase has been developed over time with a mix of styles. This guide explains how we write code going forward.
Frontend style guide
Grafana Labs follows the Airbnb React/JSX Style Guide.
Basic rules
- Keep files small and focused
- Break large components into sub-components
- Use spaces for indentation
Naming conventions
Class names
Use PascalCase:
Constants
Use ALL_CAPS:
Functions and variables
Use camelCase:
Interfaces and types
Use PascalCase (no I prefix):
Files and directories
-
Files: Name according to primary export
- PascalCase for classes/React components
- camelCase for functions
- Use
constants.ts for constants
- Use
actions.ts for Redux actions
- Use
reducers.ts for Redux reducers
- Use
*.test.ts(x) for test files
-
Directories: Use dash-case (kebab-case)
- Example:
features/new-important-feature/utils.ts
React components
Use function declarations:
Callback props should use on prefix:
Code organization
For external plugin code:
- Components and types →
@grafana/ui
- Data models and utilities →
@grafana/data
- Runtime service interfaces →
@grafana/runtime
Exports
- Use named exports (not default exports)
- Use declaration exports:
export const foo = ...
- Only export code meant for external use
Type annotations
Let TypeScript infer types when possible, but:
State management
- Don’t mutate state in reducers or thunks
- Use
createSlice from Redux Toolkit
- Use
reducerTester to test reducers
- Use state selectors instead of accessing state directly
Styling
Use Emotion with useStyles2 hook:
SASS styles are deprecated. Migrate to Emotion when modifying SASS styles.
- Use TSDoc for documentation comments
- Use
/** ... */ for React prop documentation (react-docgen)
- Use inline comments inside functions and classes
Backend style guide
Follow these standard Go guidelines:
We use GolangCI-Lint with a custom configuration.
Run the linter:
Globals
Avoid global variables when possible. They make code difficult to maintain, reason about, and test. The Grafana codebase currently uses global variables (especially for configuration), but we’re working to reduce this.
Pointers
Prefer value types. Use pointers only when necessary:
- Passing modifiable arguments to functions
- Performance considerations (benchmark first!)
- When
nil has semantic meaning (prefer zero values when possible)
Pointers increase the risk of nil pointer panics.
Database patterns
Foreign keys
We generally don’t use foreign key constraints for historical and technical reasons.
Unique columns
If a column or column combination should be unique, add a uniqueness constraint through a migration.
XORM Session methods
Session.Insert() and Session.InsertOne() return the number of affected rows, NOT the newly introduced primary key. Contributors should be extra cautious when using them.
JSON
The simplejson package is legacy code. For new code, use the standard library encoding/json instead.
Frontend (ESLint)
We use @grafana/eslint-config with bulk suppressions.
ESLint runs:
- As a precommit hook (may auto-update
eslint-suppressions.json)
- In CI (must pass before merge)
Frontend (Prettier)
Frontend (TypeScript)
Backend (Go)