The Deno Standard Library is a collection of high-quality packages for Deno and
the web, distributed via JSR as @std/*. It supports multiple runtimes: Deno,
Node.js, Bun, browsers, and Cloudflare Workers.
- Each top-level directory is a package (e.g.,
async/,http/,collections/) _tools/contains internal CI/dev tooling (lint plugins, doc checkers, etc.)- Root
deno.jsondefines the workspace, tasks, compiler options, and imports (mapping all@std/*packages and dev dependencies)
Every package follows this structure:
<package>/
├── deno.json # Name (@std/<package>), version, exports
├── mod.ts # Public entry point
├── <api>.ts # Implementation (one function/class per file)
├── <api>_test.ts # Tests for the corresponding source file
└── unstable_<api>.ts # Experimental APIs (stable packages only)
- Minimal exports: each file exports a single function/class and related types
- Unstable APIs (
unstable_*.ts): used in packages with version >= 1.0.0; must have@experimentalTSDoc tag; must NOT be exported frommod.ts - Packages with version < 1.0.0 have no unstable file restrictions
Run deno task ok before submitting. This runs:
deno task lint—deno lint(includes the custom style-guide plugin at_tools/lint_plugin.ts) plus:lint:circular— circular dependency detectionlint:tools-types— type-checks_tools/lint:mod-exports— validatesmod.tsexportslint:export-names— verifies export naminglint:docs— validates JSDoc completenesslint:unstable-deps— ensures stable entrypoints don't import unstable modules
deno fmt --checkdeno task test:browser(browser compatibility check)deno task test(full test suite with coverage and doc tests)
Spell checking (deno task typos) runs separately in CI.
PR titles must follow semantic format with a package scope:
feat(http): add streaming response support
fix(csv): handle escaped quotes correctly
docs(fmt): update docstrings
deprecation(encoding): base32hex
The scope must match an existing package name. New packages must first add their
name to the scopes list in .github/workflows/title.yml.
Follow the same semantic format as PR titles.
- Framework:
Deno.test()with@std/assertfor assertions - Test names: descriptive, include the symbol and criteria
delay() resolves immediately with ms = 0ensureDirSync() creates dir if it does not exist
- Each source file gets a corresponding
_test.tsfile - Do NOT use
@std/assertin implementation code — only in tests
All public symbols must have JSDoc with:
- Short description
@typeParamfor each type parameter@paramfor each parameter@returnsfor return value- At least one
@examplewith a title and runnable code snippet
Example snippets must be reproducible and use @std/assert assertions. Use
ignore directive to skip running a snippet, expect-error for expected
failures, no-assert to exempt a snippet from requiring assertions.
deno task test (via --doc) also type-checks TypeScript code fences in
markdown files such as README.md; mark snippets that cannot run in CI by tagging
the fence ts ignore instead of ts.
Module files (mod.ts) need a @module tag.
Follow Error Messages in CONTRIBUTING.md when writing user-facing error messages.
Follow Error Classes in CONTRIBUTING.md when choosing which error class to throw.
Tests run on Ubuntu, Windows, and macOS against Deno v1.x and v2.x. Canary is covered by a scheduled nightly workflow, not PR CI. Cross-runtime testing includes Node.js and Bun. Timezone-sensitive tests run across Sydney, London, and Toronto.
- Packages >= 1.0.0: follow semver
- Packages < 1.0.0: follow semver proposal (semver/semver#923)
- Release tags:
release-YYYY.MM.DD - Publishing:
workspace_publishworkflow pushes to JSR
Deprecated APIs use the format:
/**
* @deprecated This will be removed in X.Y.Z. Use {@linkcode bar} instead.
*/Deprecated symbols are removed in the next major version. PRs use the title
format deprecation(<package>): <symbol>.