# Code Style Guidelines for Open-Notebook: Python and TypeScript Standards

> Discover Open Notebooks code style guidelines. Learn about Python standards with Ruff and MyPy, and TypeScript best practices with ESLint and Prettier for clean, maintainable code.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: best-practices
- Published: 2026-06-13

---

**Open-Notebook enforces automated code quality through Ruff, Isort (Black profile), and MyPy for Python (88-character line limit), plus ESLint and Prettier for the TypeScript/React frontend (2-space indentation), all configured in [`pyproject.toml`](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml) and `frontend/eslint.config.mjs`.**

The open-notebook repository maintains strict code style guidelines to ensure consistency across its Python backend and TypeScript frontend. These standards are fully automated via configuration files and CI pipelines, eliminating manual formatting debates. Contributors must adhere to the rules defined in [`pyproject.toml`](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml) and `frontend/eslint.config.mjs` to pass mandatory linting checks.

## Python Backend Code Style

The Python backend relies on **Ruff** for linting, **Isort** for import sorting, and **Black** for formatting. All tool configurations reside in the root [[`pyproject.toml`](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml)](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml).

### Line Length and Import Ordering

Maximum line length is **88 characters**, optimized for Black's formatting defaults. Isort organizes imports into three distinct groups separated by blank lines: standard library, third-party packages, and local application modules.

```python
import os
import json

import httpx
import numpy as np

from open_notebook.utils import text_utils, graph_utils

```

### Linting Rules and Per-File Ignores

Ruff is configured under `[tool.ruff.lint]` to check specific error families (`E`, `F`, `I`), while explicitly ignoring:
- **E501**: Line too long (handled by the 88-character limit)
- **E402**: Module-level import not at top (required for Streamlit pages)
- **E722**: Bare except clauses
- **F401**: Unused imports (allowed for type hints)
- **F541**: F-strings without placeholders
- **F841**: Local variables assigned but never used

Per-file ignores in [`pyproject.toml`](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml) exempt Streamlit UI components from the `E402` rule:

```toml
[tool.ruff.lint.per-file-ignores]
"app_home.py" = ["E402"]
"pages/**/*.py" = ["E402"]

```

### Type Checking with MyPy

**MyPy** runs strict type checking against the codebase but excludes Streamlit UI modules via configuration overrides:

```toml
[tool.mypy.overrides]
module = "pages.*"
ignore_errors = true

```

## Frontend Code Style (TypeScript/React)

The Next.js frontend uses **ESLint** and **Prettier** for code quality, defined in [`frontend/eslint.config.mjs`](https://github.com/lfnovo/open-notebook/blob/main/frontend/eslint.config.mjs).

### ESLint and Prettier Configuration

ESLint extends Next.js and React recommended settings with these enforced rules:
- **2-space indentation**
- **Semicolons required**
- **No unused variables** (`no-unused-vars`)
- **React Hooks rules** (`react-hooks/rules-of-hooks`)

Prettier integration runs with these defaults:
- **Print width**: 80 characters
- **Trailing commas**: all
- **Single quotes**: true

### TypeScript Strict Mode

The [[`frontend/tsconfig.json`](https://github.com/lfnovo/open-notebook/blob/main/frontend/tsconfig.json)](https://github.com/lfnovo/open-notebook/blob/main/frontend/tsconfig.json) enables `strict` mode, `noImplicitAny`, and `exactOptionalPropertyTypes` to ensure type-safe code throughout the React application.

## Automated Enforcement

Continuous Integration blocks merges that fail style checks. For the backend, CI runs:

```bash
ruff check .
ruff format --check .

```

For the frontend, CI executes:

```bash
eslint . --ext .js,.jsx,.ts,.tsx
prettier --check .

```

**Pre-commit hooks** automatically format and lint code on every local commit after running `pre-commit install`, ensuring violations are caught before submission.

## Summary

- **Python standards**: 88-character lines, Ruff + Isort (Black profile), MyPy type checking with Streamlit exemptions
- **Frontend standards**: 2-space indentation, ESLint + Prettier integration, strict TypeScript compiler options
- **Configuration files**: [`pyproject.toml`](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml) (Python), `frontend/eslint.config.mjs` and [`frontend/tsconfig.json`](https://github.com/lfnovo/open-notebook/blob/main/frontend/tsconfig.json) (Frontend)
- **Enforcement**: CI pipelines and pre-commit hooks prevent style violations from entering the main branch

## Frequently Asked Questions

### What is the maximum line length for Python code in open-notebook?

Python code must not exceed **88 characters** per line. This limit is configured in [`pyproject.toml`](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml) to align with Black's default formatting standard, balancing readability with modern screen widths while working seamlessly with the Isort Black profile.

### How are imports ordered in the Python backend?

Imports are automatically sorted by **Isort** using the Black profile, grouping them into three categories: standard library imports, third-party packages, and local application modules. Each group is separated by a blank line, and the tool runs automatically via pre-commit hooks or CI.

### Why does the project ignore E402 errors in Streamlit pages?

The `E402` error (module-level import not at top) is ignored for files matching [`app_home.py`](https://github.com/lfnovo/open-notebook/blob/main/app_home.py) and `pages/**/*.py` because Streamlit applications often require configuration statements or page setup code before importing certain modules. The [`pyproject.toml`](https://github.com/lfnovo/open-notebook/blob/main/pyproject.toml) explicitly configures these per-file ignores under `[tool.ruff.lint.per-file-ignores]`.

### How do I ensure my code passes the style checks before submitting a PR?

Run `pre-commit install` to install git hooks that automatically lint and format your code on every commit. You can also manually run `ruff check .` and `ruff format .` for Python, or `eslint .` and `prettier --check .` for frontend code to verify compliance before pushing changes to the repository.