document-swift
Write and maintain high-quality Swift DocC documentation for the TMDb package, following its established `///` conventions. Use when adding or changing any public declaration (protocol, class, struct,
SKILL.md.claude/skills/document-swift/SKILL.md
GitHubDocument Swift (DocC conventions)
The canonical guide for documenting public API in the TMDb Swift package. Apply
these conventions inline, in the same step you write the declaration — a
public symbol without a /// comment is not finished (CLAUDE.md requires it,
and make build-docs runs warnings-as-errors, so a miss breaks the build). For
documenting many files at once, the documentation-writer agent follows these
same rules in an isolated context.
Scope
- Document only
publicdeclarations — skipinternal,private,fileprivate,package. - Document every public declaration — no "self-explanatory" exceptions:
protocols, classes, structs, enums (and cases where meaning isn't obvious),
actors, typealiases, models, stored/computed properties, initializers, methods,
subscripts. Custom
init(from:)/encode(to:)in apublic extensionneed comments too (a common miss). - Use
///style — never/** */. - 100-character line length; wrap continuation lines indented to align with the text above.
Summary patterns
The first /// line after the opening blank /// is the summary. Match the
project's house style by declaration kind:
- Method — verb phrase: "Returns the primary information about a movie." (not "Gets a movie.")
- Property — noun phrase: "Movie identifier." (not "The ID of the movie.")
- Type (struct/class) — "A model representing a [noun]."
- Protocol — "Provides an interface for [verb]-ing [noun] from TMDb."
- Enum — "A model representing a [noun]."; cases use concise noun phrases/adjectives.
- Initializer — "Creates a [type description] object."
Be concise. Extra detail goes in later paragraphs only when it adds something the signature doesn't.
Structure of a doc comment
Opening ///, summary, blank ///, then sections in this order, each separated
by a blank /// line: API link → Precondition → Parameters → Throws →
Returns. No trailing whitespace on blank /// lines.
- TMDb API link — every service protocol method includes, right after the
summary:
/// [TMDb API - <Category>: <Endpoint>](https://developer.themoviedb.org/reference/<slug>) - Parameters —
- Parameter name:(singular) for exactly one parameter;- Parameters:with an indented list for two or more. - Precondition — methods with a
pageparameter add a/// - Precondition:line — e.g.pagecan be between1and1000. - Throws — service methods use
/// - Throws: TMDb error ``TMDbError``.; forDecodableinits, list the specificDecodingErrorcases. - Returns — describe what comes back, e.g. "Matching review."
Standard parameter descriptions (reuse verbatim)
language: "ISO 639-1 language code to display results in. Defaults to the client's configured default language."country: "ISO 3166-1 country code."page: "The page of results to return."idparameters: "The identifier of the [entity]."session: "The user's TMDb session."
Cross-references
- Types: double backticks —
TMDbError. - Articles/guides:
<doc:/TMDb/ArticleName>. - Image paths: any
URL?property representing an image path —posterPath,backdropPath,profilePath,logoPath,stillPath— must add, on its own paragraph: "To generate a full URL see doc:/TMDb/GeneratingImageURLs."
Canonical examples
Service method, multiple parameters (note Precondition + plural Parameters):
///
/// Returns the user reviews for a movie.
///
/// [TMDb API - Movies: Reviews](https://developer.themoviedb.org/reference/movie-reviews)
///
/// - Precondition: `page` can be between `1` and `1000`.
///
/// - Parameters:
/// - movieID: The identifier of the movie.
/// - page: The page of results to return.
/// - language: ISO 639-1 language code to display results in.
/// Defaults to the client's configured default language.
///
/// - Throws: TMDb error ``TMDbError``.
///
/// - Returns: Reviews for the matching movie as a pageable list.
///
func reviews(
forMovie movieID: Movie.ID,
page: Int?,
language: String?
) async throws -> ReviewPageableList
Service method, single parameter (singular Parameter):
///
/// Returns a review's details.
///
/// [TMDb API - Reviews: Details](https://developer.themoviedb.org/reference/review-details)
///
/// - Parameter id: The identifier of the review.
///
/// - Throws: TMDb error ``TMDbError``.
///
/// - Returns: Matching review.
///
func details(forReview id: Review.ID) async throws -> Review
Model struct with an image path and a matching initializer:
///
/// A model representing a movie.
///
public struct MovieListItem: Identifiable, Codable, Equatable, Hashable, Sendable {
///
/// Movie identifier.
///
public let id: Int
///
/// Movie poster path.
///
/// To generate a full URL see <doc:/TMDb/GeneratingImageURLs>.
///
public let posterPath: URL?
///
/// Creates a movie list item object.
///
/// - Parameters:
/// - id: Movie identifier.
/// - posterPath: Movie poster path.
///
public init(id: Int, posterPath: URL? = nil)
}
Initializer parameter descriptions must stay consistent with the corresponding property documentation.
Keep the DocC catalog in sync
When public API changes, update Sources/TMDb/TMDb.docc/ so make build-docs
(warnings-as-errors) stays green. Catalog layout:
Sources/TMDb/TMDb.docc/
├── TMDb.md # Main catalog with topic sections
├── Extensions/
│ ├── TMDbClient.md # TMDbClient properties
│ └── <ServiceName>Service.md # Service method groupings
├── GettingStarted/
├── HowTos/
└── Resources/
- New service → create
Extensions/<ServiceName>Service.md; add the service and its return types toTMDb.md; add the property toTMDbClient.md. - New method on an existing service → add a reference under the right topic
heading in the service's extension file, double-backtick with labels:
reviews(forMovie:page:language:). - New public model/type → add to the appropriate topic section in
TMDb.md. - Renamed/removed API → update every affected catalog file.
Extension file shape:
# ``MovieService``
## Topics
### Reviews
- ``reviews(forMovie:page:language:)``
Keep the README API overview in sync
README.md carries a human-facing overview that drifts out of date as the API
grows — update it in the same change, then run make lint-markdown:
- Available Services table (
## Available Services) — one row per service,| **serviceName** | capability, capability, … |.- New service → add a row, and bump the service count in the
**Comprehensive API Coverage**feature bullet so the number stays accurate. - New method/capability on an existing service → extend that service's row description if it adds a notable capability (e.g. add "watch providers" to the movies row). A new endpoint that's just a variant of an existing one does not always need a new word — judge whether a user scanning the table would miss it.
- New service → add a row, and bump the service count in the
- Features list (
## Features) → add or amend a bullet when the change introduces a headline, user-visible capability (a new search mode, a new formatting conformance, etc.), not for routine endpoint additions. - Code examples (
## Setup,## Common Use Cases) → if the change alters a usage pattern shown in an example, update the example; these aren't compiled, so verify types, property names, andtry/awaitby hand. Example blocks must show theswift-tools-versionthat matchesPackage.swift. - Requirements / Installation → only if platform support or
swift-tools-versionchanged, or a new tool/dependency is required (bump Prerequisites).
Rule of thumb: the README is the at-a-glance map of the API — if a user reading only the Features list and the service table would now have a wrong or incomplete picture, fix it here. Skip churn for purely internal changes.
What NOT to do
- Don't repeat what the signature already says, or use vague filler ("does something", "handles stuff").
- Don't leave placeholders (
/// ?,Array of...) — write complete descriptions. - Don't copy-paste carelessly: catch "movie" left in a
Persondoc, orMovie.IDwherePerson.IDis meant. - Don't reference SwiftUI/UIKit — this is a pure API-client library.
- Don't add
@availableunless it matches the enclosing type's declaration.
Verify before finishing
- Every public declaration in the change has a
///comment. - Summary style matches the declaration kind; structure is summary → blank → sections, no trailing whitespace.
- Service methods carry the
[TMDb API - …]link. - Singular vs plural
Parameter(s)is correct; order is Parameters → Throws → Returns. - Lines ≤ 100 chars; image-path properties cross-reference the image-URL guide.
- Init parameter docs match property docs.
- DocC catalog (extension files,
TMDb.md,TMDbClient.md) reflects the current public API. README.mdoverview is in sync — the Available Services table (row + capability words), the service count in the Features bullet, the Features list for any headline capability, and any affected code examples.- Run
make build-docsto confirm docs compile with no warnings, andmake lint-markdownifREADME.md(or any.md) changed.
For Apple API specifics (concurrency safety, availability, behaviour), look it up
with the sosumi MCP tools rather than guessing. For documenting async/actor/
Sendable API, the swift-concurrency skill has the concurrency vocabulary.