Skip to content

Structure

structure

Node structure gold-standard checks — license, contributing, readme, gitignore.

Ports the intent of the Python checks.structure / checks.docs.readme gold-standard files to a node project. These are language-agnostic project hygiene files; the README section convention matches the Python check.

check_contributing(project)

Check: a CONTRIBUTING.md exists at the project root.

Source code in packages/axm-init/src/axm_init/checks/node/structure.py
Python
def check_contributing(project: Path) -> CheckResult:
    """Check: a CONTRIBUTING.md exists at the project root."""
    if (project / "CONTRIBUTING.md").is_file():
        return CheckResult(
            name="structure.contributing",
            category="structure",
            passed=True,
            weight=2,
            message="CONTRIBUTING.md found",
            details=[],
            fix="",
        )
    return CheckResult(
        name="structure.contributing",
        category="structure",
        passed=False,
        weight=2,
        message="CONTRIBUTING.md not found",
        details=[],
        fix="Create CONTRIBUTING.md with dev setup and commit conventions.",
    )

check_gitignore(project)

Check: a .gitignore exists that ignores node_modules.

Source code in packages/axm-init/src/axm_init/checks/node/structure.py
Python
def check_gitignore(project: Path) -> CheckResult:
    """Check: a .gitignore exists that ignores node_modules."""
    path = project / ".gitignore"
    if not path.is_file():
        return CheckResult(
            name="structure.gitignore",
            category="structure",
            passed=False,
            weight=2,
            message=".gitignore not found",
            details=[],
            fix="Create a .gitignore ignoring node_modules, dist, coverage.",
        )
    content = path.read_text(encoding="utf-8", errors="replace")
    if "node_modules" not in content:
        return CheckResult(
            name="structure.gitignore",
            category="structure",
            passed=False,
            weight=2,
            message=".gitignore does not ignore node_modules",
            details=["node_modules must be git-ignored"],
            fix="Add node_modules/ to .gitignore.",
        )
    return CheckResult(
        name="structure.gitignore",
        category="structure",
        passed=True,
        weight=2,
        message=".gitignore present",
        details=[],
        fix="",
    )

check_license_file(project)

Check: a LICENSE file exists at the project root.

Source code in packages/axm-init/src/axm_init/checks/node/structure.py
Python
def check_license_file(project: Path) -> CheckResult:
    """Check: a LICENSE file exists at the project root."""
    if (project / "LICENSE").is_file() or (project / "LICENSE.md").is_file():
        return CheckResult(
            name="structure.license",
            category="structure",
            passed=True,
            weight=3,
            message="LICENSE file found",
            details=[],
            fix="",
        )
    return CheckResult(
        name="structure.license",
        category="structure",
        passed=False,
        weight=3,
        message="LICENSE file not found",
        details=[],
        fix="Create a LICENSE file (MIT, Apache-2.0, …).",
    )

check_lock_file(project)

Check: a dependency lockfile is committed (node analog of uv.lock).

Source code in packages/axm-init/src/axm_init/checks/node/structure.py
Python
def check_lock_file(project: Path) -> CheckResult:
    """Check: a dependency lockfile is committed (node analog of uv.lock)."""
    if any((project / name).is_file() for name in _LOCK_FILES):
        return CheckResult(
            name="structure.lock_file",
            category="structure",
            passed=True,
            weight=2,
            message="Lockfile present",
            details=[],
            fix="",
        )
    return CheckResult(
        name="structure.lock_file",
        category="structure",
        passed=False,
        weight=2,
        message="No lockfile committed",
        details=[],
        fix="Commit a lockfile (package-lock.json / pnpm-lock.yaml).",
    )

check_readme(project)

Check: README.md exists with the standard sections.

Source code in packages/axm-init/src/axm_init/checks/node/structure.py
Python
def check_readme(project: Path) -> CheckResult:
    """Check: README.md exists with the standard sections."""
    path = project / "README.md"
    if not path.is_file():
        return CheckResult(
            name="structure.readme",
            category="structure",
            passed=False,
            weight=3,
            message="README.md not found",
            details=[],
            fix="Create README.md with Features/Installation/Development/License.",
        )
    lowered = path.read_text(encoding="utf-8", errors="replace").lower()
    missing = [s for s in _README_SECTIONS if f"## {s.lower()}" not in lowered]
    if missing:
        return CheckResult(
            name="structure.readme",
            category="structure",
            passed=False,
            weight=3,
            message=f"README missing {len(missing)} section(s)",
            details=[f"Missing: {', '.join(missing)}"],
            fix=f"Add {', '.join(missing)} section(s) to README.md.",
        )
    return CheckResult(
        name="structure.readme",
        category="structure",
        passed=True,
        weight=3,
        message="README follows standard",
        details=[],
        fix="",
    )

check_tests_dir(project)

Check: the project has tests (a tests/ dir or colocated *.test.ts).

Source code in packages/axm-init/src/axm_init/checks/node/structure.py
Python
def check_tests_dir(project: Path) -> CheckResult:
    """Check: the project has tests (a tests/ dir or colocated *.test.ts)."""
    if (project / "tests").is_dir():
        return CheckResult(
            name="structure.tests_dir",
            category="structure",
            passed=True,
            weight=2,
            message="tests/ directory present",
            details=[],
            fix="",
        )
    src = project / "src"
    if src.is_dir() and any(
        p.name.endswith((".test.ts", ".test.tsx", ".spec.ts", ".spec.tsx"))
        for p in src.rglob("*")
        if p.is_file()
    ):
        return CheckResult(
            name="structure.tests_dir",
            category="structure",
            passed=True,
            weight=2,
            message="Colocated tests present",
            details=[],
            fix="",
        )
    return CheckResult(
        name="structure.tests_dir",
        category="structure",
        passed=False,
        weight=2,
        message="No tests found",
        details=["Expected a tests/ dir or colocated *.test.ts files"],
        fix="Add tests (tests/ directory or colocated *.test.ts).",
    )