diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 851640e674..dbccbe558b 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,9 +1,5 @@
-## Description
-
-
-
-## Notes for the release
-
-
-
+
+- If this PR updates API docs, preview them by running `bun preview-api-docs`
+- Read the full [contributing documentation](https://github.com/emberjs/data/blob/main/contributing/become-a-contributor.md)
+- If you do not have permission to add labels or run the test-suite in CI, a team member will do this for you.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0a75eb9d5d..d22ce849b4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -9,6 +9,7 @@ detailing how to become involved to best ensure your contributions are successfu
- [Becoming a Contributor](./contributing/become-a-contributor.md)
- [Requesting Features or Deprecations](./contributing/rfc-process.md)
- [Submitting Pull Requests](./contributing/submitting-prs.md)
+- [Writing API Docs](./contributing/writing-api-docs.md)
- [Linking the project to your application locally](./contributing/linking-to-applications.md)
- [Key Concepts](./contributing/key-concepts.md)
diff --git a/contributing/become-a-contributor.md b/contributing/become-a-contributor.md
index 949c1cfedc..bb6af74f1b 100644
--- a/contributing/become-a-contributor.md
+++ b/contributing/become-a-contributor.md
@@ -9,6 +9,7 @@ or [RFCs](https://github.com/emberjs/rfcs/labels/T-ember-data), we coordinate wo
- [Setting Up The Project](./setting-up-the-project.md)
- [Project Architecture](./project-architecture.md)
+- [Writing API Docs](./writing-api-docs.md)
- [Key Concepts](./key-concepts.md)
- [Terminology](./terminology.md)
- [RFC Process](./rfc-process.md)
diff --git a/contributing/writing-api-docs.md b/contributing/writing-api-docs.md
new file mode 100644
index 0000000000..895bbec9ff
--- /dev/null
+++ b/contributing/writing-api-docs.md
@@ -0,0 +1,319 @@
+# Writing API Docs
+
+API Documentation is generated from [yuidoc](https://yui.github.io/yuidoc/) comments in the source code.
+
+YUIDoc syntax is very similar to [JSDoc](https://jsdoc.app/) but there are occassional nuances where
+it becomes best to know the underlying parser is YUIDoc.
+
+While API Documentation lives with the source-code, the code itself plays no-part in the documentation
+that is generated: everything is compiled from comments alone.
+
+
+
+---
+
+
+
+## Documentation Syntax
+
+
+
+### What are Doc Comments
+
+Only `**` comments are compiled as potential documentation, e.g.
+
+```ts
+/**
+ * This is a potential documentation block
+ */
+```
+
+Where as single star comment blocks are not considered documentation
+
+```ts
+/*
+ * This is not a potential documentation block
+ */
+```
+
+
+
+### Ignored Doc Comments
+
+When compiling the API documentation, several categories of comments will be ignored:
+
+- `@internal` - signifies internal documentation for contributors for a non-public API
+- `@feature` - signifies documentation for an unreleased feature gated by a canary flag
+- `@typedoc` - signifies typescript-only (in-editor) documentation that should not be compiled into the API docs
+
+Additionally, use of the following tags will cause a doc comment to be ignored due to intended use primarily being docs
+written for in-editor experience similar to `@typedoc`
+
+- `@see`
+- `@link`
+- `@inheritdoc`
+
+For example, the below doc comment would be ignored
+
+```ts
+/**
+ * This is a private utility for updating the state
+ * of a relationship.
+ *
+ * @internal
+ */
+```
+
+
+
+### Always Start with `@module`
+
+The YUIDocs parser will attribute all documentation it discovers to the most recent
+`module` (package) declaration it has seen. For this reason, any file that has documentation
+comments should declare the package it applies to at the top of the file.
+
+For instance, if we were writing documentation for a feature within the `@ember-data/store`
+package, we would declare the following at the top of the file:
+
+```ts
+/**
+ * @module @ember-data/store
+ */
+```
+
+### Doc Comments can be Markdown
+
+Doc comments can contain most any valid markdown syntax, most markdown-valid html,
+and can utilize code-highlighting via language prefix on a code block comment.
+
+For instance
+
+```ts
+/**
+ * ## Overview
+ *
+ * Some details
+ *
+ * ### An Example
+ *
+ * ```ts
+ * new Store();
+ * ```
+ *
+ * @class Store
+ * @public
+ */
+```
+
+
+
+### Doc Comments should start every line with a `*`
+
+While technically doc comments only need to start with `/**`, providing a `*` for
+every line with matching indentation ensures correct parsing of all tags and documentation.
+
+Without this, some decorators in code examples may be incorrectly parsed as documentation tags,
+and some documentation may be unexpectedly truncated.
+
+**Good**
+
+```ts
+/**
+ * ## Overview
+ *
+ * Some details
+ *
+ * ### An Example
+ *
+ * ```ts
+ * class User extends Model {
+ * @attr name;
+ * }
+ * ```
+ *
+ * @class Store
+ * @public
+ */
+```
+
+**Bad**
+
+```ts
+/**
+ ## Overview
+
+ Some details
+
+ ### An Example
+
+ \```ts
+ class User extends Model {
+ @attr name;
+ }
+ \```
+
+ @class Store
+ @public
+*/
+```
+
+### Documenting Modules
+
+Yuidoc syntax refers to packages as "modules". To declare that some code
+is part of a module, we use `@module `, so the package `@warp-drive/core-types`
+is `@module @warp-drive/core-types`.
+
+Modules are documented using a special `@main` tag.
+
+For instance, to write documentation giving an overview of `@warp-drive/core-types`
+we would do the following.
+
+```ts
+/**
+ * This package provides essential types and symbols used
+ * by all the other WarpDrive/EmberData packages.
+ *
+ * @module @warp-drive/core-types
+ * @main @warp-drive/core-types
+ */
+```
+
+Sometimes we may want to reuse the documentation for a primary default export
+class as the module documentation as well. In this case `@module` will be
+declared standalone while `@main` will be affixed to the exported class doc comment.
+
+```ts
+/**
+ * @module @ember-data/serializer/json-api
+ */
+/**
+ * << module (and class) overview goes here >>
+ *
+ * @class JSONAPISerializer
+ * @main @ember-data/serializer/json-api
+ * @public
+ */
+```
+
+
+
+### Documenting Classes
+
+Classes are documented using `@class`.
+
+```ts
+/**
+ * @since 1.13.0
+ * @class JSONAPIAdapter
+ * @main @ember-data/adapter/json-api
+ * @public
+ * @constructor
+ * @extends RESTAdapter
+*/
+```
+
+Methods are documented with `@method` and attatch to the most recent class the parser has
+seen.
+
+```ts
+/**
+ * Some documentation
+ *
+ * @method myMethod
+ * @public
+ * @param {AType} myParam explanation of the param
+ * @return {AnotherType} explanation of the return value
+ */
+```
+
+Properties are documented with `@property` and attach to the most recent class the parser has seen.
+
+```ts
+/**
+ * An explanation of the property
+ *
+ * @property {SomeType} propertyName
+ * @public
+ */
+```
+
+Static methods and properties can be documented by adding `@static` to the definition.
+
+
+
+### Documenting Functions
+
+Functions are documented as "static" methods on modules. For instance the method `recordIdentifierFor`
+imported from `@ember-data/store` would be done like the below
+
+```ts
+/**
+ * Description of the function
+ *
+ * @public
+ * @static
+ * @for @ember-data/store
+ * @param {Object} record a record instance previously obstained from the store.
+ * @return {StableRecordIdentifier}
+ */
+```
+
+
+
+
+### Documenting Interfaces and Types
+
+Yuidoc and the ember API docs do not have a mechanism for documenting types. However, because
+documentation is entirely doc-comment driven, we can document interfaces and types as classes,
+and mark them as such by giving them impossible names. Generally we follow the convention of
+` AnInterface` and ` AType` for this.
+
+For example, the interface for creating a request handler is documented as a class below
+whose name is ` Handler`.
+
+```ts
+/**
+ * << Handler Documentation >>
+ *
+ * @class Handler
+ * @public
+ */
+```
+
+
+
+---
+
+
+
+## Documentation Hygeine
+
+
+
+### Documentation Tests
+
+Run `pnpm test:docs`
+
+This will lint discovered doc comments for common sources of error, as well as validate that no published documentation
+has been added or removed unexpectedly.
+
+If documentation has been added, an entry for it should be added to `tests/docs/fixtures/expected.js`.
+If documentation has been removed, similarly any entry for it should be removed from `tests/docs/fixtures/expected.js`.
+
+If documentation you've added is not being discovered by the test, it is likely that either
+
+- it may have been excluded due to using an [ignored doc comment](#ignored-doc-comments)
+- it may have been excluded due to not using the right [comment syntax](#what-are-doc-comments)
+- it may have been included in the list of paths to search for source code documentation in [yuidoc.json](../docs-generator/yuidoc.json)
+
+
+
+### Previewing Documentation
+
+Run `bun preview-api-docs` from the project root or the `docs-viewer` directory.
+
+This will build and run the (external) api-docs app with the current state of the api docs in the repo.
+
+Changes need to be manually rebuilt with `bun rebuild-api-docs`.
+
+See the [Docs Viewer README](../docs-viewer/README.md) for more info.
diff --git a/packages/core-types/src/schema/fields.ts b/packages/core-types/src/schema/fields.ts
index 9f9f269945..e38117dfb7 100644
--- a/packages/core-types/src/schema/fields.ts
+++ b/packages/core-types/src/schema/fields.ts
@@ -1548,7 +1548,7 @@ export type Schema = ResourceSchema | ObjectSchema;
* @static
* @for @warp-drive/core-types
* @param {ResourceSchema} schema
- * @returns {ResourceSchema} the passed in schema
+ * @return {ResourceSchema} the passed in schema
* @public
*/
export function resourceSchema(schema: T): T {
@@ -1565,7 +1565,7 @@ export function resourceSchema(schema: T): T {
* @static
* @for @warp-drive/core-types
* @param {ObjectSchema} schema
- * @returns {ObjectSchema} the passed in schema
+ * @return {ObjectSchema} the passed in schema
* @public
*/
export function objectSchema(schema: T): T {
@@ -1579,7 +1579,7 @@ export function objectSchema(schema: T): T {
* @static
* @for @warp-drive/core-types
* @param schema
- * @returns {boolean}
+ * @return {boolean}
* @public
*/
export function isResourceSchema(schema: ResourceSchema | ObjectSchema): schema is ResourceSchema {
@@ -1593,7 +1593,7 @@ export function isResourceSchema(schema: ResourceSchema | ObjectSchema): schema
* @static
* @for @warp-drive/core-types
* @param schema
- * @returns {boolean}
+ * @return {boolean}
* @public
*/
export function isLegacyResourceSchema(schema: ResourceSchema | ObjectSchema): schema is LegacyResourceSchema {
diff --git a/packages/experiments/src/persisted-cache/cache.ts b/packages/experiments/src/persisted-cache/cache.ts
index 02ea4b68e7..a73753bd3c 100644
--- a/packages/experiments/src/persisted-cache/cache.ts
+++ b/packages/experiments/src/persisted-cache/cache.ts
@@ -182,7 +182,7 @@ export class PersistedCache implements Cache {
* @method peek
* @internal
* @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
- * @returns {ResourceDocument | ResourceBlob | null} the known resource data
+ * @return {ResourceDocument | ResourceBlob | null} the known resource data
*/
peekRemoteState(identifier: StableRecordIdentifier>): T | null;
peekRemoteState(identifier: StableDocumentIdentifier): ResourceDocument | null;