DocsDocumentation

Nitro CLI

Build static sites with Python code instead of template engines.

A static site generator that lets you build websites using Python and nitro-ui.

Features

  • Python-Powered - Write pages in Python with nitro-ui instead of template languages
  • Live Reload - Development server with automatic browser refresh
  • Incremental Builds - Only rebuild changed pages
  • Dynamic Routes - Generate pages from data with [slug].py pattern
  • Draft Pages - Mark pages as drafts to exclude from production builds
  • Environment Variables - Auto-load .env files with from nitro import env
  • Image Optimization - Responsive images with WebP/AVIF conversion
  • Islands Architecture - Partial hydration for interactive components
  • Plugin System - Extend the build lifecycle with nitro-dispatch hooks
  • One-Click Deploy - Netlify, Vercel, or Cloudflare Pages

Installation

pip install nitro-cli

AI Assistant Integration

Add Nitro CLI knowledge to your AI coding assistant:

npx skills add nitro-sh/nitro-cli

This enables AI assistants like Claude Code to understand Nitro CLI and generate correct nitro-ui code.

Quick Start

nitro new my-site
cd my-site
nitro dev

Visit http://localhost:3000. Build for production with nitro build.

Writing Pages

Pages are Python files in src/pages/ that export a render() function:

# src/pages/index.py
from nitro_ui import HTML, Head, Body, Title, Meta, H1
from nitro import Page

def render():
    return Page(
        title="Home",
        content=HTML(
            Head(
                Meta(charset="UTF-8"),
                Meta(name="viewport", content="width=device-width, initial-scale=1.0"),
                Title("Home"),
            ),
            Body(H1("Welcome!"))
        )
    )

Output paths mirror the file structure: src/pages/about.pybuild/about.html

Dynamic Routes

Generate multiple pages from data using [param].py naming:

# src/pages/blog/[slug].py
from nitro import Page
from nitro_datastore import NitroDataStore

def get_paths():
    data = NitroDataStore.from_file("src/data/posts.json")
    return [{"slug": p.slug, "title": p.title} for p in data.posts]

def render(slug, title):
    return Page(title=title, content=...)

Commands

CommandDescription
nitro new <name>Create new project
nitro initInitialize Nitro in current dir
nitro devStart dev server with live reload
nitro buildBuild for production
nitro previewPreview production build
nitro routesList all routes
nitro checkValidate site without building
nitro exportExport site as zip archive
nitro cleanRemove build artifacts
nitro deployDeploy to hosting platform
nitro infoShow project and environment info

Run nitro <command> --help for options.

Configuration

# nitro.config.py
from nitro import Config

config = Config(
    site_name="My Site",
    base_url="https://mysite.com",
    renderer={"minify_html": True},
    plugins=[],
)

Ecosystem

License

This project is licensed under the BSD 3-Clause License. See the LICENSE file for details.

API Reference

Auto-generated from the installed package's public API. Signatures and docstrings come directly from the source.

Page

Page#

Page(title: str, content: Any, meta: Optional[Dict[str, Any]] = None, template: Optional[str] = None, draft: bool = False)

A single rendered page in a Nitro site.

Config

Config#

Config(site_name: str = 'My Site (built with nitro.sh)', base_url: str = 'http://localhost:8008', build_dir: str = 'build', source_dir: str = 'src', renderer: Optional[Dict[str, Any]] = None, plugins: Optional[List[str]] = ...

Project-level configuration for a Nitro site.

Environment

env#

Lazy-loading accessor for environment variables.

Image pipeline

ImageConfig#

ImageConfig(sizes: List[int] = <factory>, formats: List[str] = <factory>, quality: Dict[str, int] = <factory>, lazy_load: bool = True, default_sizes: str = '(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw', output_dir: ...

Tunable settings for the image optimization pipeline.

ImageOptimizer#

ImageOptimizer(config: Optional[nitro.core.images.ImageConfig] = None)

Build-time image optimizer that produces responsive variants.

3 methods
generate_picture_element(self, optimized: nitro.core.images.OptimizedImage, alt: str = '', css_class: str = '', sizes: Optional[str] = None) -> str

Build a responsive `<picture>` element for an optimized image.

optimize_image(self, source_path: pathlib.Path, output_dir: pathlib.Path, base_url: str = '') -> Optional[nitro.core.images.OptimizedImage]

Generate responsive variants for a single source image.

process_html(self, html_content: str, source_dir: pathlib.Path, output_dir: pathlib.Path, base_url: str = '') -> str

Rewrite `<img>` tags in HTML into optimized `<picture>` elements.

OptimizedImage#

OptimizedImage(original_path: pathlib.Path, original_width: int, original_height: int, variants: Dict[str, Dict[int, pathlib.Path]], hash: str) -> None

Result of optimizing a single source image.

2 methods
get_src(self, format: str = 'webp', width: Optional[int] = None) -> str

Return a single `src` path for the given format and width.

get_srcset(self, format: str = 'webp') -> str

Return a `srcset` attribute value for the given format.

Islands

Island#

Island(name: str, component: Any, props: Dict[str, Any] = <factory>, client: Literal['load', 'idle', 'visible', 'media', 'interaction', 'none'] = 'idle', client_only: bool = False, media: Optional[str] = None) -> None

An interactive component that hydrates on the client.

1 methods
render(self) -> str

Render the island as HTML with hydration markers.

IslandConfig#

IslandConfig(output_dir: str = '_islands', default_strategy: Literal['load', 'idle', 'visible', 'media', 'interaction', 'none'] = 'idle', debug: bool = False) -> None

Tunable settings for the islands hydration pipeline.

IslandProcessor#

IslandProcessor(config: Optional[nitro.core.islands.IslandConfig] = None)

Post-process HTML to wire up island hydration.

2 methods
generate_hydration_script(self) -> str

Return the client-side hydration runtime as a JS source string.

process_html(self, html_content: str, inject_script: bool = True) -> str

Inject the hydration runtime into HTML when islands are present.