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:
- Top-level project settings control the build shape, source markers, resource copying, and duplicate-function validation.
Manifestcontrols metadata for the generated PowerShell module manifest and package metadata reuse.Packagecontrols package creation and optional raw HTTP upload defaults.Pestercontrols the test run configuration used byTest-NovaBuild.
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/.
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"
}
}
}
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
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.