pyssg is pre-1.0 and under active development - APIs, config, and themes may change.
pyssg.cli.commands.new

2 min read

pyssg.cli.commands.new

pyssg new -- scaffold a site, post, theme, or plugin.

The new group is the single home for project scaffolding. The historical top-level commands pyssg init and pyssg eject-layout are preserved as hidden aliases for new site / new theme so existing docs, scripts, and the published Obsidian adapter keep working.

run_new_site(site: Path, *, preset: str, force: bool) -> int

Scaffold a new site for preset under site; return an exit code.

run_new_theme(site: Path, *, theme: str, to: str) -> int

Copy a built-in theme into site/to (the eject); return an exit code.

run_new_post(site: Path, *, title: str, date: str, tags: list[str], slug: str | None, force: bool) -> int

Scaffold content/posts/<slug>.md for a new post; return an exit code.

run_new_plugin(site: Path, *, name: str, force: bool) -> int

Scaffold plugins/<name>.py -- a starter plugin; return an exit code.

new_site(ctx: typer.Context, preset: Annotated[str, typer.Option('--preset', help='site preset: docs|blog|obsidian')] = 'docs', force: Annotated[bool, typer.Option('--force', help='overwrite an existing config')] = False) -> None

Scaffold a new site for a preset.

new_theme(ctx: typer.Context, name: Annotated[str, typer.Option('--name', help='built-in theme to copy')], to: Annotated[str, typer.Option('--to', help='destination dir (relative to site)')] = 'layouts/theme') -> None

Copy a built-in theme into the site so it can be customized.

new_post(ctx: typer.Context, title: Annotated[str, typer.Option('--title', help='post title')] = 'New Post', tag: Annotated[list[str] | None, typer.Option('--tag', help='a tag (repeatable)')] = None, date: Annotated[str | None, typer.Option('--date', help='ISO date (default: today)')] = None, slug: Annotated[str | None, typer.Option('--slug', help='file slug (default: from title)')] = None, force: Annotated[bool, typer.Option('--force', help='overwrite an existing post')] = False) -> None

Scaffold a new blog post under content/posts.

new_plugin(ctx: typer.Context, name: Annotated[str, typer.Argument(help='plugin name (a Python identifier)')], force: Annotated[bool, typer.Option('--force', help='overwrite an existing file')] = False) -> None

Scaffold a starter plugin module under plugins/.

init(ctx: typer.Context, preset: Annotated[str, typer.Option('--preset', help='site preset: docs|blog|obsidian')] = 'docs', force: Annotated[bool, typer.Option('--force', help='overwrite an existing config')] = False) -> None

Deprecated alias for new site.

eject_layout_command(ctx: typer.Context, theme: Annotated[str, typer.Option('--theme', help='built-in theme to copy')], to: Annotated[str, typer.Option('--to', help='destination dir (relative to site)')] = 'layouts/theme') -> None

Deprecated alias for new theme.