Reference

Understand every setting in project.json

NovaModuleTools reads project.json to decide how your project is scaffolded, built, tested, packaged, uploaded, published, and released. Use this page to understand what each setting does, what the defaults are, and when you should override them.

How to read this file

Think of project.json in layers:

  1. Top-level project settings control the build shape, source markers, resource copying, and duplicate-function validation.
  2. Manifest controls metadata for the generated PowerShell module manifest and package metadata reuse.
  3. Package controls package creation and optional raw HTTP upload defaults.
  4. Pester controls the test run configuration used by Test-NovaBuild.
Default behavior matters.

You only need to add settings when you want to override the default workflow. For example, if you never add a Package section, New-NovaModulePackage still works and defaults to a single .nupkg written to artifacts/packages/.

Important compatibility note.

The runtime and shipped examples currently use some manifest and Pester fields more broadly than the JSON schema files explicitly enumerate. In practice, the current product and examples use Manifest.ReleaseNotes, Manifest.LicenseUri, Manifest.IconUri, and Pester.TestResult.OutputFormat. The reference below documents the live behavior that the product uses today and calls out those schema gaps where they matter.

Complete example

The packaged example project is the best real-world reference because it shows the current full configuration surface in one place.

{
  "ProjectName": "NovaExampleModule",
  "Description": "A working example project that demonstrates NovaModuleTools.",
  "Version": "0.1.0",
  "CopyResourcesToModuleRoot": false,
  "BuildRecursiveFolders": true,
  "SetSourcePath": true,
  "FailOnDuplicateFunctionNames": true,
  "Preamble": [
    "Set-StrictMode -Version Latest",
    "$ErrorActionPreference = 'Stop'"
  ],
  "Manifest": {
    "Author": "NovaModuleTools",
    "PowerShellHostVersion": "7.4",
    "GUID": "b3b4ca64-a274-4768-872d-2b3c8bc12a39",
    "Tags": ["Example", "NovaModuleTools", "PowerShell"],
    "ProjectUri": "https://www.novamoduletools.com/",
    "ReleaseNotes": "https://www.novamoduletools.com/release-notes.html",
    "LicenseUri": "https://www.novamoduletools.com/license.html"
  },
  "Package": {
    "Id": "NovaExampleModule",
    "Types": ["NuGet", "Zip"],
    "Latest": true,
    "OutputDirectory": {
      "Path": "artifacts/packages",
      "Clean": true
    },
    "PackageFileName": "NovaExampleModule.0.1.0",
    "FileNamePattern": "NovaExampleModule*",
    "Authors": ["NovaModuleTools", "Example Maintainer"],
    "Description": "Example package metadata and raw upload configuration for NovaExampleModule.",
    "RepositoryUrl": "https://packages.example.test/raw/novamodule/",
    "UploadPath": "stable/latest",
    "Headers": {
      "X-Client-Id": "nova-example"
    },
    "Auth": {
      "HeaderName": "Authorization",
      "Scheme": "Bearer",
      "TokenEnvironmentVariable": "NOVA_EXAMPLE_PACKAGE_TOKEN"
    },
    "Repositories": [
      {
        "Name": "ExampleRaw",
        "Url": "https://packages.example.test/raw/novamodule/"
      }
    ]
  },
  "Pester": {
    "TestResult": {
      "Enabled": true,
      "OutputFormat": "NUnitXml"
    },
    "Output": {
      "Verbosity": "Detailed"
    }
  }
}

See how to use the packaged example as a learning project

Top-level project settings

Setting Purpose Default Workflow effect
ProjectName Name of the module and the output folder under dist/. Required Determines manifest name, module name, and many generated paths.
Description Human-readable project description. Required Feeds manifest and package metadata when you do not override them later.
Version Current semantic version stored for the project. Required Used in package names, manifest metadata, nova version, and release flows.
CopyResourcesToModuleRoot Controls where resources are copied in the built module. false When false, resources stay in a resources/ folder. When true, they are copied into the module root.
BuildRecursiveFolders Controls recursive discovery for classes, private helpers, and tests. true Affects how nested source files and nested tests are discovered.
SetSourcePath Controls # Source: markers in the generated .psm1. true Makes parser and runtime errors easier to map back to source files.
FailOnDuplicateFunctionNames Fails the build when duplicate top-level function names are emitted. true Protects the generated module from ambiguous exports and hidden overwrites.
Preamble Optional lines written at the top of the generated .psm1. Empty array Useful for Set-StrictMode, $ErrorActionPreference, or other module-wide setup lines.

Examples

{
  "CopyResourcesToModuleRoot": true,
  "BuildRecursiveFolders": false,
  "SetSourcePath": true,
  "FailOnDuplicateFunctionNames": true,
  "Preamble": [
    "Set-StrictMode -Version Latest",
    "$ErrorActionPreference = 'Stop'"
  ]
}

Use this pattern when you want strict runtime defaults, top-level-only test discovery, and resources copied directly to the module root.

Manifest settings

These settings feed the generated PowerShell module manifest and, in several cases, package metadata.

Setting Required What it does Notes
Author Yes Sets the manifest author and the default package author when Package.Authors is omitted. Use a single author string; package logic can later expand into arrays.
PowerShellHostVersion Yes Defines the minimum PowerShell version expected by the generated module. Users see this in the manifest and module compatibility expectations.
GUID Yes Sets the manifest GUID. Generate a new GUID for each distinct module.
Tags No Adds manifest tags and is reused by package metadata when present. Optional in practice and safe to omit.
ProjectUri No Publishes a project URL in the manifest and package metadata. Explicitly described in the current build schema.
ReleaseNotes No Publishes a release notes link for packaging and user-facing metadata. Used by the current product and examples even though the build schema does not enumerate it separately yet.
LicenseUri No Publishes a license URL for packaging and manifest metadata. Used in practice and shown in the packaged example.
IconUri No Publishes an icon URL in the manifest. Used by the repository project itself and worth keeping stable when you publish publicly.

If Tags, ProjectUri, ReleaseNotes, or LicenseUri are omitted, packaging still succeeds. The corresponding package metadata fields are simply left out.

Package settings

The Package section controls two related but different concerns:

  • package creation via New-NovaModulePackage / nova package
  • raw HTTP artifact upload via Deploy-NovaPackage / nova deploy
Keep these concepts separate.

Package.Types, Package.Latest, and OutputDirectory decide what gets created. RepositoryUrl, Headers, Auth, and Repositories decide how existing artifacts are uploaded later.

Package creation settings

Setting Default What it controls Gotchas
Id ProjectName The package identifier and default naming base. Override this only when the package identity should differ from the module name.
Types ["NuGet"] Which package formats to create. Supported values are NuGet, Zip, .nupkg, and .zip, and matching is case-insensitive.
Latest false Whether to create companion latest artifacts for each selected type. When true, Nova keeps the normal versioned artifact and adds a second file such as MyModule.latest.nupkg.
OutputDirectory.Path artifacts/packages Where packages are written. This is also the default discovery location for Deploy-NovaPackage.
OutputDirectory.Clean true Whether to clear the output directory before packaging. Set it to false only when you intentionally want to retain older files.
PackageFileName <Id>.<Version>.nupkg Base file name used for package generation. Nova normalizes the extension per package type and swaps the version suffix for latest when needed.
FileNamePattern <Id>* in practice Pattern used to discover matching package files for upload. Keep it wide enough to include both versioned and latest artifacts when you use Package.Latest.
Authors Derived from Manifest.Author Package author metadata. Can be a single string or an array of strings.
Description Derived from top-level Description Package description metadata. Use this when the package description should differ from the module description.

Raw upload settings

Setting What it does Notes
RepositoryUrl Canonical package-level raw upload base URL. Use this when you only need one default upload target.
RawRepositoryUrl Legacy compatibility alias. If present, it still maps into RepositoryUrl when the canonical setting is missing.
UploadPath Optional extra path segment appended before the file name during upload. Useful for folder-style raw repositories such as stable/latest or preview.
Headers Generic additional HTTP headers. Merged with repository-specific headers and dynamic parameter headers when you invoke upload.
Auth.HeaderName Name of the authentication header to emit. Examples: Authorization, X-Api-Key.
Auth.Scheme Optional scheme prefix for the auth header value. Examples: Bearer, Basic.
Auth.Token Literal token value. Good for local testing only. Prefer environment variables for real secrets.
Auth.TokenEnvironmentVariable Name of the environment variable that stores the token value. This should be the variable name, not the secret itself.
Repositories Named upload targets with optional overrides. Each repository needs Name and Url, then can add UploadPath, Headers, and Auth.

Authentication examples

{
  "Package": {
    "RepositoryUrl": "https://packages.example/raw/",
    "Auth": {
      "HeaderName": "Authorization",
      "Scheme": "Bearer",
      "TokenEnvironmentVariable": "NOVA_PACKAGE_TOKEN"
    }
  }
}

Use this for bearer-token-style endpoints.

{
  "Package": {
    "Repositories": [
      {
        "Name": "RawRepo",
        "Url": "https://packages.example/raw/",
        "Auth": {
          "HeaderName": "X-Api-Key",
          "TokenEnvironmentVariable": "NOVA_PACKAGE_API_KEY"
        }
      }
    ]
  }
}

Use this for custom API-key headers.

{
  "Package": {
    "Repositories": [
      {
        "Name": "LocalNexus",
        "Url": "http://localhost:8081/repository/raw/modules/",
        "Auth": {
          "HeaderName": "Authorization",
          "Scheme": "Basic",
          "TokenEnvironmentVariable": "NOVA_NEXUS_BASIC_AUTH"
        }
      }
    ]
  }
}

Use this generic model for Basic auth when the endpoint expects a pre-encoded token value. In that case, the environment variable should hold the Base64 value for username:password, not the raw username or password.

Pester settings

NovaModuleTools passes your Pester settings into the test run configuration used by Test-NovaBuild.

Setting Current usage Default/Example Where you see it
Pester.TestResult.Enabled Controls whether test results are configured for output. true in the project template and packaged example Influences the generated test result artifact behavior.
Pester.TestResult.OutputFormat Passed through by the current project template and examples. NUnitXml Determines the result format written to artifacts/TestResults.xml.
Pester.Output.Verbosity Controls Pester console verbosity. Detailed in the current project template Affects what you see during Test-NovaBuild and nova test.

At runtime, Test-NovaBuild also lets you override verbosity and render mode temporarily with -OutputVerbosity and -OutputRenderMode.

Common recipes

Minimal module project

{
  "ProjectName": "MyModule",
  "Description": "My module",
  "Version": "0.1.0",
  "Manifest": {
    "Author": "You",
    "PowerShellHostVersion": "7.4",
    "GUID": "00000000-0000-0000-0000-000000000000"
  }
}

Use this when you want the smallest workable Nova project with default build, test, and packaging behavior.

Create both NuGet and Zip artifacts, plus latest aliases

{
  "Package": {
    "Types": ["NuGet", "Zip"],
    "Latest": true,
    "OutputDirectory": {
      "Path": "artifacts/packages",
      "Clean": true
    }
  }
}

This creates four files when both package types are selected: versioned and latest variants for each format.

Use named raw repositories with shared defaults

{
  "Package": {
    "RepositoryUrl": "https://packages.example/raw/default/",
    "Headers": {
      "X-Client": "my-module"
    },
    "Auth": {
      "HeaderName": "Authorization",
      "Scheme": "Bearer",
      "TokenEnvironmentVariable": "NOVA_PACKAGE_TOKEN"
    },
    "Repositories": [
      {
        "Name": "Stable",
        "Url": "https://packages.example/raw/stable/"
      },
      {
        "Name": "Preview",
        "Url": "https://packages.example/raw/preview/",
        "UploadPath": "nightly"
      }
    ]
  }
}

Use package-level values for the shared default behavior, then override only the repository-specific parts that need to change.