Leaving files out
A docs project often shares its folder with things that aren’t the site: a package.json, a .env, an export with customer data. Writedocs leaves a list of such files out by default, and a .wdignore file at the project root lets you add your own - or bring a default one back.
A file that’s left out is never published and never read as content: it isn’t published at its own path, it isn’t a page, its CSS or JavaScript isn’t loaded, and an image in it isn’t shown.
The .wdignore file
Create a file named .wdignore next to writedocs.json, with one pattern per line. The syntax is the one .gitignore uses:
# Drafts and internal material
drafts/
internal-notes.md
# Every CSV, except the public ones
*.csv
!data/public/*.csv| Pattern | What it leaves out |
|---|---|
drafts/ | Every folder named drafts, at any depth, and everything in it. |
/drafts/ | Only the drafts folder at the project root. |
internal-notes.md | Every file (or folder) with that name, at any depth. |
docs/guides/old.mdx | That one file. A pattern with a / in the middle starts at the project root. |
*.csv | Every file ending in .csv. * doesn’t cross a /. |
data/**/*.csv | Every .csv under data/, at any depth. |
!data/public/*.csv | Brings back what an earlier line left out. |
# ... | A comment. Blank lines are skipped too. |
Later lines win over earlier ones, and upper and lower case are treated as the same.
As in .gitignore: once a folder is left out, a ! line for a file inside it does nothing. Bring the folder back (!drafts/), then leave out what you don’t want in it.
writedocs dev picks up a change to .wdignore without a restart.
What’s left out by default
These apply to every project, with or without a .wdignore.
Never published
Secrets. No .wdignore line brings these back, and they’re left out of the public/ folder too:
| Pattern | What it is |
|---|---|
.env, .env.* | Environment files - API keys and passwords. |
.git/ | The repository’s history. |
.npmrc | Package manager configuration, which can hold an access token. |
*.pem, *.key, *.p12, *.pfx | Private keys, and the files that carry them. |
id_rsa*, id_dsa*, id_ecdsa*, id_ed25519* | SSH keys. |
Left out unless you bring them back
Tooling and data that a docs repository holds but a site rarely means to publish. A ! line in .wdignore brings one back:
| Pattern | What it is |
|---|---|
.* | Every file and folder whose name starts with a dot: .gitignore, .gitmodules, .gitattributes, .github/, .vscode/, .DS_Store, .wdignore itself, .writedocs/ … |
package.json, package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb, bun.lock, composer.json, composer.lock | Package manifests and lockfiles. |
node_modules/, dist/ | Dependencies and build output, at any depth. |
tsconfig.json, jsconfig.json, vercel.json, netlify.json, netlify.toml, wrangler.json, wrangler.jsonc, wrangler.toml, Dockerfile, docker-compose*.yml, docker-compose*.yaml | Tooling and hosting configuration. |
*.crt, *.jks, *.keystore | Certificates and key stores. |
*.sqlite, *.sqlite3, *.db, *.sql | Databases and dumps. |
*.log | Logs. |
Each one applies at any depth: examples/app/package.json is left out like the one at the root.
Bringing a default back
Some of these are sometimes real content - a package.json a guide walks through, a SQL file to download, a .well-known/ folder. Add a ! line:
# The example app's manifest, for readers to download
!examples/app/package.json
# A folder whose name starts with a dot
!.well-known/
# The built example, zipped
!examples/app/dist/Bringing a file back makes it a file like any other, so the usual rule still decides whether it’s published: it is when it’s one of the kinds of file Writedocs publishes. !.well-known/ publishes .well-known/security.txt, and !examples/app/package.json publishes that file. A .sql file isn’t one of those kinds - to offer one for download, put it in public/, where it’s published without a .wdignore line.
Three things don’t come back:
- The files under Never published.
node_modules/,dist/and.writedocs/at the project root.- Pages, CSS and JavaScript inside a folder whose name starts with a dot.
!.drafts/publishes the PDFs and images in.drafts/, but an.mdxfile there still isn’t a page.
The public folder
Everything in a public/ folder is published as it is - putting a file there already says “publish this”. So the defaults under Left out unless you bring them back don’t apply inside it: public/.well-known/security.txt and public/downloads/schema.sql are published with no .wdignore at all.
Two things still apply in public/:
- The files under Never published. A
public/.envorpublic/server.keyis not published. - Your own
.wdignorelines. A pattern matches the file’s path from the project root, sopublic/old/leaves that folder out.
Links to a file that’s left out
A page can still name a file that’s left out - link to it, or show it as an image. The build doesn’t fail: the file just isn’t on the site, so the link leads nowhere and the image doesn’t load.
writedocs broken-links finds these, and says why:
index.mdx
12 /internal/plan.pdf - internal/plan.pdf is in the project, but the ignore rules leave it out, so it isn't published.
To publish it, bring it back in .wdignore - a line with !internal/plan.pdf, or its folder's (!folder/) when the whole folder is left out.What to keep in mind
- Don’t leave out a file the site is built from. A snippet a page imports, or the OpenAPI spec an API reference reads, has to be there when the site is built - with one of them left out, the build fails.
writedocs broken-linksreports a page that imports a snippet that’s left out.writedocs.jsonis always read and never published, whatever.wdignoresays. - A page that’s left out has no address. If
writedocs.json’s navigation still lists it,writedocs validatereports the missing page. - It decides what’s published, not what’s in your repository. A secret that’s committed is still in the repository’s history.
.wdignorekeeps it off the site. .mintignorestill works. A project that came from Mintlify keeps its.mintignore, which lists files that aren’t pages..wdignoredoes that too, and also covers every other file - use it for anything new.