Problem
Vitest now documents .vitest/ as the shared location for generated reports and artifacts, but the HTML reporter still defaults to html/.
This does not match the newer artifact convention and forces the HTML reporter to copy data that already lives in .vitest, such as attachments, into the report directory.
Goal
Make the default HTML reporter output use .vitest/ as its artifact root.
Default output:
.vitest/
index.html
ui/
metadata.gz
assets/
index-xxx.js
index-xxx.css
attachments/
coverage/
This makes the default report easier to ignore, upload, and reason about as one Vitest artifact directory.
Desired Behavior
When the HTML reporter uses its default output:
- The report entry is
.vitest/index.html.
- HTML reporter implementation files live under
.vitest/ui/.
- Attachments use the existing default
.vitest/attachments/ location without being copied.
- Coverage should eventually use
.vitest/coverage/ without being copied when it is generated in the default compatible location.
- The report remains previewable with
vite preview --outDir .vitest.
When users provide explicit paths:
outputDir is respected.
- Custom
attachmentsDir is respected.
- Custom coverage output is respected.
- The reporter may still copy or relocate files when needed to keep the generated report portable and internally consistent.
Zero-copy behavior is the default happy path, not a guarantee for all custom path combinations.
Reporter Option Shape
As a breaking change, the HTML reporter should use outputDir instead of outputFile.
outputFile is a poor fit because the normal HTML reporter output is not one file. It is a static report app with an entry HTML file, UI assets, metadata, attachments, and optionally coverage.
Proposed shape:
reporters: [
['html', {
outputDir: '.vitest',
}],
]
Multi-file mode writes:
<outputDir>/index.html
<outputDir>/ui/
singleFile: true writes one self-contained:
Remove HTML reporter outputFile support. The option should describe the report root directory directly.
Concern
.vitest/ can contain artifacts from multiple reporters and integrations, not only the HTML report.
For example, a run could generate:
.vitest/
index.html
ui/
attachments/
coverage/
blob/
report.json
junit/
output.xml
Uploading .vitest/ as one artifact may include unrelated or large files such as blob reports or JUnit XML. This overlaps with current coverage output too, since coverage directories already contain files that are not directly visible as HTML pages.
That is acceptable for an “upload all Vitest artifacts” workflow, but .vitest/ should be documented as a shared artifact root, not exclusively the HTML report directory.
Users who want to publish only the HTML report can upload the entry and the subdirectories it references:
.vitest/index.html
.vitest/ui/**
.vitest/attachments/**
.vitest/coverage/**
Alternative: outputDir: '.vitest/html'
A smaller change would keep the current HTML reporter layout and only change the default report directory from:
to:
This aligns the default output with the .vitest/* convention without changing the report layout much:
.vitest/
html/
index.html
html.meta.json.gz
assets/
data/
coverage/
attachments/
This is simpler and less risky. It preserves the idea that the HTML report is a self-contained directory rooted at .vitest/html/, and it follows the existing guidance that reporters own scoped subdirectories under .vitest/.
The trade-off is that it does not use .vitest/ as a shared artifact root. Attachments still need to be copied from .vitest/attachments/ into .vitest/html/data/, and coverage still needs to be copied into .vitest/html/coverage/, even when those artifacts already live under .vitest/ or could be configured to do so.
The proposed .vitest/index.html layout is more ambitious: it treats .vitest/ itself as the artifact root and lets the HTML report reuse shared subdirectories such as attachments/ and coverage/ directly in the default happy path. That requires reserving built-in top-level names such as .vitest/index.html and .vitest/ui/; other reporters and integrations should continue using scoped directories such as .vitest/junit/ or .vitest/my-reporter/.
Related Follow-Up: Shared Report Data
The HTML reporter currently writes its own metadata format for the UI. The blob reporter also serializes run data for later reporting and merge workflows.
These formats are not identical, but they overlap. Blob output contains test files, unhandled errors, coverage data, execution time, and serialized module graph data needed to restore reports. HTML metadata contains test files, paths, config, unhandled errors, module graph data, and test sources.
As a follow-up, HTML reporter should avoid inventing a separate serialized run-result format when the same underlying data already exists in or near the blob reporter format.
Possible direction:
- define a shared report data format used by blob and HTML reporter
- keep UI-only additions separate, such as source file contents needed by the editor view
- let the HTML reporter load or transform shared report data instead of serializing a parallel format
- consider whether default
.vitest/blob/ output can be reused directly as an HTML report asset
This fits the broader .vitest/ artifact-root goal: generated data should have one canonical home when possible, and the HTML report should reference or adapt that data instead of duplicating it under a reporter-specific metadata file.
Problem
Vitest now documents
.vitest/as the shared location for generated reports and artifacts, but the HTML reporter still defaults tohtml/.This does not match the newer artifact convention and forces the HTML reporter to copy data that already lives in
.vitest, such as attachments, into the report directory.Goal
Make the default HTML reporter output use
.vitest/as its artifact root.Default output:
.vitest/ index.html ui/ metadata.gz assets/ index-xxx.js index-xxx.css attachments/ coverage/This makes the default report easier to ignore, upload, and reason about as one Vitest artifact directory.
Desired Behavior
When the HTML reporter uses its default output:
.vitest/index.html..vitest/ui/..vitest/attachments/location without being copied..vitest/coverage/without being copied when it is generated in the default compatible location.vite preview --outDir .vitest.When users provide explicit paths:
outputDiris respected.attachmentsDiris respected.Zero-copy behavior is the default happy path, not a guarantee for all custom path combinations.
Reporter Option Shape
As a breaking change, the HTML reporter should use
outputDirinstead ofoutputFile.outputFileis a poor fit because the normal HTML reporter output is not one file. It is a static report app with an entry HTML file, UI assets, metadata, attachments, and optionally coverage.Proposed shape:
Multi-file mode writes:
singleFile: truewrites one self-contained:Remove HTML reporter
outputFilesupport. The option should describe the report root directory directly.Concern
.vitest/can contain artifacts from multiple reporters and integrations, not only the HTML report.For example, a run could generate:
.vitest/ index.html ui/ attachments/ coverage/ blob/ report.json junit/ output.xmlUploading
.vitest/as one artifact may include unrelated or large files such as blob reports or JUnit XML. This overlaps with current coverage output too, since coverage directories already contain files that are not directly visible as HTML pages.That is acceptable for an “upload all Vitest artifacts” workflow, but
.vitest/should be documented as a shared artifact root, not exclusively the HTML report directory.Users who want to publish only the HTML report can upload the entry and the subdirectories it references:
Alternative:
outputDir: '.vitest/html'A smaller change would keep the current HTML reporter layout and only change the default report directory from:
to:
This aligns the default output with the
.vitest/*convention without changing the report layout much:.vitest/ html/ index.html html.meta.json.gz assets/ data/ coverage/ attachments/This is simpler and less risky. It preserves the idea that the HTML report is a self-contained directory rooted at
.vitest/html/, and it follows the existing guidance that reporters own scoped subdirectories under.vitest/.The trade-off is that it does not use
.vitest/as a shared artifact root. Attachments still need to be copied from.vitest/attachments/into.vitest/html/data/, and coverage still needs to be copied into.vitest/html/coverage/, even when those artifacts already live under.vitest/or could be configured to do so.The proposed
.vitest/index.htmllayout is more ambitious: it treats.vitest/itself as the artifact root and lets the HTML report reuse shared subdirectories such asattachments/andcoverage/directly in the default happy path. That requires reserving built-in top-level names such as.vitest/index.htmland.vitest/ui/; other reporters and integrations should continue using scoped directories such as.vitest/junit/or.vitest/my-reporter/.Related Follow-Up: Shared Report Data
The HTML reporter currently writes its own metadata format for the UI. The blob reporter also serializes run data for later reporting and merge workflows.
These formats are not identical, but they overlap. Blob output contains test files, unhandled errors, coverage data, execution time, and serialized module graph data needed to restore reports. HTML metadata contains test files, paths, config, unhandled errors, module graph data, and test sources.
As a follow-up, HTML reporter should avoid inventing a separate serialized run-result format when the same underlying data already exists in or near the blob reporter format.
Possible direction:
.vitest/blob/output can be reused directly as an HTML report assetThis fits the broader
.vitest/artifact-root goal: generated data should have one canonical home when possible, and the HTML report should reference or adapt that data instead of duplicating it under a reporter-specific metadata file.