Skip to content

[Trace] Template de-dup: de-duplicate SDK doc boilerplate across docs/SDKs - #174

Merged
nicolasiscoding merged 8 commits into
developfrom
trace/docs-sdk-dedup
Sep 23, 2026
Merged

nicolasiscoding merged 8 commits into
developfrom
trace/docs-sdk-dedup

Conversation

@nicolasiscoding

@nicolasiscoding nicolasiscoding commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Closes #173

Trace task: template-detector.mjs, config/anti-ai-rules.json, CONTENT SOP "Crawled - currently not indexed" rule (de-duplicate first).

Evidence

URL Inspection shows Google refusing to index substantial SDK pages: docs/SDKs/javascript (4,186 words, crawled - not indexed), python, quote-javascript, webhooks-java, deliverable-go, deliverable-php (crawled - not indexed), java (discovered - not indexed). template-detector.mjs found the same 5-word phrases repeated across 15 of the 27 live (non-Ruby) SDK pages (a first pass with the tool's own reporting quirks read this as ~17; see "Template detector" below): a generic "Error Handling" intro sentence plus a 7-row status-code table with identical English wording (Invalid or missing API key, Invalid request parameters, Too many requests, Network connectivity issues) copy-pasted regardless of language or product. queries.json shows real developer demand: "python digital signature sdk" (433 impressions, currently ranking on the dotcom guide /guides/sign-documents-with-python, not this docs page), "php digital signature sdk" (378, same pattern), "javascript pdf signature integration" (337, same pattern). Data source: queries.json comes from queries.py, which calls the Google Search Console API directly (searchAnalytics.query via a gcloud ADC bearer token), not PostHog's GSC warehouse; re-verified all three figures against the file before citing them.

What changed

Two layers of duplication, two fixes.

1. De-dup (10 files: deliverable-{go,php,java,javascript,python}.md, partner-{go,php,java,javascript,python}.md): each carried a full copy of the generic error-type table already documented once on the language's canonical page. Replaced the generic intro + table with a short paragraph naming an error that operation actually raises (verified against /home/nicolas/repos/SDK), followed by a link to the language's Error Handling reference for the full table. Kept the already-differentiated code samples and product-specific notes (Go's errors.As, PHP's typed exceptions, Java's nested TurboDocxException.*, partner's IOException/409-conflict callouts). quote-*.md/webhooks-*.md had no such generic error table to begin with, so not part of this fix. (They have their own, separate cross-language duplication in their product-intro paragraphs, disclosed further down; unrelated to the error-table issue fixed here.)

2. Rewrote the 5 canonical pages themselves (go.md, php.md, java.md, javascript.md, python.md): all five opened ## Error Handling with the identical sentence "The SDK provides typed error(s)/exception(s) for different ... scenarios." Three of those five (javascript.md, python.md, java.md) are themselves evidence pages Google won't index. Replaced each intro with that language's real, source-verified idiom:

  • go.md: errors embed TurboDocxError by value; match with errors.As, read fields directly. Added the ConflictError row/case that existed in packages/go-sdk/http.go but wasn't documented.
  • php.md: statusCode/errorCode are public readonly properties; PHP's inherited Exception::getCode() is hardcoded to 0 by the constructor, a real footgun. Added the AuthorizationException/ConflictException rows and catches that existed in packages/php-sdk/src/Exceptions/ but weren't documented, even though partner-php.md/deliverable-php.md already referenced them.
  • java.md: every exception is a nested static class of TurboDocxException; each of the 7 named subclasses falls back to its own DEFAULT_CODE via a shared orDefault helper, so getCode() is populated for those, though the bare TurboDocxException for an unmapped status has no such fallback.
  • javascript.md: code is a plain string the HTTP client passes through from the API response when present, falling back to the class default only when the API doesn't supply one, per the docstring in packages/js-sdk/src/utils/errors.ts.
  • python.md: every subclass sets its own DEFAULT_CODE class attribute; catch the most specific exception first since except TurboDocxError also matches its subclasses.

Bug fixes (index.md), found while verifying the code samples against source:

  • PHP tab called $e->getCode(), which PHP's Exception::getCode() hardcodes to 0 in TurboDocxException's constructor. The real field is the public readonly $e->errorCode (packages/php-sdk/src/Exceptions/TurboDocxException.php). Fixed.
  • Java tab imported com.turbodocx.sdk.* (the SDK's real package is com.turbodocx, no .sdk), returned a SigningResult type that doesn't exist, and called turboSign.sendSignature(...) on a bare variable instead of client.turboSign().sendSignature(...). Fixed to match java.md's own correct examples; also added the com.turbodocx.models.* import that SendSignatureResponse needs.
  • Go tab matched errors.As(err, &turboErr) against *sdk.TurboDocxError only. Go's errors.As requires the target's concrete type to match; *sdk.ValidationError (and the 5 other named error types) is a distinct type from *sdk.TurboDocxError even though it embeds it, and neither implements Unwrap/As, so that check silently failed to match any of the 6 named error types, only the generic unmapped-status case, meaning the VALIDATION_ERROR branch shown was dead code. Fixed to match *sdk.ValidationError directly.
  • Python tab printed e.message. TurboDocxError.__init__ never sets self.message (Python 3's Exception doesn't have one either), so this raises AttributeError at runtime. Fixed to {e} (str(e)), matching python.md's own examples.
  • The "code is always populated" line above these tabs had the same gap the language-page corrections below describe. Qualified it the same way.

Correction (5 deliverable-*.md pages): these claimed ValidationError fires when a variable is missing "placeholder or mimeType". Checked RapidDocxBackend/src/handlers/Deliverable/DeliverableGenerationHandlers.ts: its Variable interface has placeholder: string (required) but mimeType?: string (optional), the opposite emphasis. Couldn't find the runtime validation for a missing placeholder specifically (the handler doesn't appear to check it before using it), so rather than assert an unverified 400, all 5 pages now say "missing a required field" without naming one.

Corrections ("always populated" claims in go.md/java.md/python.md): the Code-field descriptions I originally wrote said the machine-readable code is always populated. True only for the 7 named error subclasses, each with its own default. The bare base error returned for an unmapped HTTP status (an unexpected 5xx, for example) can have an empty/null code: Go's defaultErrorCode() returns "" in its default case, Java's HttpClient.java falls through to the bare TurboDocxException constructor with no fallback, Python's base TurboDocxError has DEFAULT_CODE = None. Qualified all three.

Broken links (4 files): go.md/java.md linked /docs/TurboSign/API-Signatures (hyphen, 404) instead of the correctly-encoded .../API%20Signatures used elsewhere in the same files. partner-php.md/partner-javascript.md linked #orguserrole-organization-users, truncated; the real heading (### OrgUserRole (Organization Users and Org API Keys)) slugifies to #orguserrole-organization-users-and-org-api-keys.

Frontmatter descriptions (11 files): agent-skills.md + 5 quote-*/5 webhooks-* pages had descriptions over 160 chars; shortened to <=155, language + product first.

Noted, not fixed: docs/SDKs/ruby.md/deliverable-ruby.md (and 3 other Ruby product pages) 404 live but still get search impressions. Confirmed the removal was intentional: draft: true since commit 40efd12 because the turbodocx-sdk gem isn't on RubyGems yet; Docusaurus excludes draft pages from the production build. Per the task's own criterion, intentional removal that still draws impressions needs a redirect. The owner picks the target and timing: javascript.md/python.md are the closest topical peers, but both are also on the not-indexed list themselves, so neither is an obviously "safe" redirect target either.

Out of scope: the one-line credentials callout (15 files) and ## Resources GitHub-repo footer (18 files) are short functional text that already links to a single canonical source rather than repeating it; left as-is. Pre-existing em-dashes in quote-*/webhooks-*/agent-skills.md body content (this PR only touched their frontmatter description) were left alone to avoid an unrelated full-file diff; all prose this PR actually added or edited is em-dash-free.

Template detector: before -> after

The stock template-detector.mjs caps its 5-gram report at 30 matches and its heading-strip regex fuses a heading straight into the next paragraph, which understated this fix on a first pass. Re-ran with an uncapped copy (also stripping fenced code blocks, forcing a sentence boundary after headings) against git archive origin/develop vs. the final tree, counting the same 27 non-Ruby files on both sides:

  • provides typed error(s)/provides typed exception(s) (the shared intro sentence): 15 files -> 0 (grep -il "provides typed" docs/SDKs/*.md, excluding the 5 draft Ruby pages, returns nothing)
  • Generic status-row wording (Invalid or missing API..., Invalid request parameters, Too many requests, Network connectivity issues): 15 files -> 5, confirmed by direct grep on the 27 non-Ruby files: only the 5 canonical pages still carry it. The raw uncapped tool reports 7-8 because it scans all 32 files including the 5 draft Ruby pages, which this PR didn't touch and which still have the old table (grep -il "Invalid request parameters" docs/SDKs/*ruby*.md returns 3 of them)
  • Whole-directory uncapped total (every 5-gram shared by >=3 of all 32 files): 5,494 -> 5,388. Most of the residue sits in quote-*.md/webhooks-*.md, which this PR didn't touch (see below).

Disclosed, not fixed: remaining duplication in quote-*.md/webhooks-*.md

Running the uncapped detector on just the 5 quote-*.md files (excluding Ruby) finds 960 five-grams shared by all 5; on just the 5 webhooks-*.md files, 700 shared by all 5. Some is unavoidable component boilerplate (<QuickstartSkillNudge .../>), but part is real: quote-php.md, quote-python.md, and the draft quote-ruby.md open with a byte-identical "What is TurboQuote?" paragraph, while quote-go.md/quote-javascript.md already differ. quote-javascript.md and webhooks-java.md are themselves evidence pages and got only a frontmatter fix here, not a body rewrite: this PR fixed the Error Handling duplication its author investigated first, but the quote/webhooks product-intro duplication shown above is real and unaddressed, not something this PR already covers. A follow-up pass rewriting the quote/webhooks per-language intros the way this PR rewrote Error Handling is a legitimate next step; not folded into this PR to keep it reviewable and avoid ballooning an already-large diff further. Owner call below.

Owner questions

  1. Ruby redirect target: javascript.md or python.md for ruby.md/deliverable-ruby.md (and the other 3 Ruby pages), or leave as-is until the gem ships?
  2. Worth a follow-up PR for the quote-*/webhooks-* per-language intro de-dup described above?
  3. Not a docs issue, an SDK one: every one of the 5 SDKs leaves code empty/null for an error on an HTTP status outside the 7 mapped ones (an unexpected 5xx, for example), even though the Java javadoc for orDefault says code "must still be branchable" and is "kept identical across all six SDKs." Worth a TurboDocx/SDK issue?

Config check

Re-read config/title-engineering.json per the owner's "playbook configs win over TurboDocx SOP where they conflict" note. Its maxLength: 60/number-first rules target page titles for listicle content and don't set a description-length rule, so they don't apply to (and don't conflict with) the description rewrites in this PR.

Merge order

This PR only touches docs/SDKs/*, which the other open Docs Trace PRs (meta-length, broken-links, API-reference enrichment) explicitly skip. No expected conflicts.

SDK repo state

/home/nicolas/repos/SDK was checked out on feature/turbosign-embedded-identity (unmerged PR #77) while researching this. Re-verified with git diff origin/main that the 5 source files actually cited above are byte-identical to origin/main, and confirmed no branch-only symbol (createSigningUrl, getEmbeddedSigningSettings, identityVerification, embedded signing, OTP) appears anywhere in this PR's diff.

Test plan

  • Re-ran template-detector.mjs (uncapped, before/after); cross-checked with direct grep since the tool's cap and heading-fusion were misleading on the first pass
  • Verified every changed code sample against SDK source: go-sdk/http.go, go-sdk/deliverable.go, go-sdk/turbowebhooks.go, php-sdk/src/Exceptions/{TurboDocxException,AuthorizationException,ConflictException}.php, java-sdk/.../{TurboDocxException,TurboDocxClient,HttpClient}.java, java-sdk/.../models/SendSignatureResponse.java, js-sdk/src/utils/errors.ts, js-sdk/src/modules/{deliverable,partner}.ts, py-sdk/src/turbodocx_sdk/http.py
  • Verified the 5 deliverable-*.md claims about the generate-deliverable request body against RapidDocxBackend/src/handlers/Deliverable/DeliverableGenerationHandlers.ts (its Variable interface: placeholder required, mimeType optional, opposite of what an earlier commit here claimed)
  • Also verified the code-passthrough (JS) and DEFAULT_CODE (Python) claims against the actual published @turbodocx/sdk@0.7.0 npm tarball and turbodocx-sdk==0.7.0 PyPI wheel, not just source
  • Verified every changed/added link resolves to an existing file + heading slug (script mirrors Docusaurus's github-slugger)
  • grep -c "—" returns 0 on every file where this PR added or edited prose
  • Confirmed cited SDK source matches origin/main, not the checked-out feature branch
  • Local build
  • Staging deploy

Review vs SDK main

A follow-up diligence pass re-verified every SDK-doc claim in this PR against origin/main of the SDK repo, published package artifacts (npm, PyPI, Maven Central), and origin/master of RapidDocxBackend. 13 confirmed inaccuracies were fixed (plus one duplicate defect shared by deliverable-go.md):

  • docs/SDKs/index.md — the senderEmail note claimed the API rejects TurboSign/TurboQuote sends missing a sender with 400 SenderEmailRequired/SenderNameRequired. Backend commit 80df5fff ("stop rejecting API sends that omit senderEmail", reverted 2026-07-27) removed that rejection; the API now always falls back to a generic TurboDocx sender. Rewrote the note to describe the JS/TS SDK's own client-side configure()-time check instead, softened the credentials table, and removed the SenderEmailRequired/SenderNameRequired rows from the error-code table.
  • docs/SDKs/javascript.md — same stale 400 SenderEmailRequired/SenderNameRequired claim in the TurboSign caution block; rewrote to describe the SDK's HttpClient constructor throwing ValidationError client-side (verified in packages/js-sdk/src/http.ts on SDK origin/main), not an API-side rejection.
  • docs/SDKs/quote-javascript.md — same stale claim for TurboQuote (assertQuoteSenderResolvable/resolveSenderIdentity no longer throw, per the backend's own doc comment: "Neither branch rejects"). Rewrote the tip block to describe the fallback-to-generic-sender behavior, and removed the SenderEmailRequired row from the send-preconditions table.
  • docs/SDKs/quote-javascript.md — the TurboQuote.updateTemplate({ senderEmail, senderName }) sample was missing the required id positional argument (updateTemplate(id: string, request: ...) per packages/js-sdk/src/modules/quote.ts on SDK origin/main); fixed to TurboQuote.updateTemplate(tmpl.id, { senderEmail, senderName }).
  • docs/SDKs/go.md — the Message field's table row claimed Error() returns the bare message string. Verified in packages/go-sdk/http.go that Error() actually composes TurboDocx API error [CODE]: MESSAGE (status N). Corrected the row to describe the real format.
  • docs/SDKs/partner-go.md — the Error Handling example and typed-error list omitted ConflictError, even though the shared mapStatusToError maps 409 to *ConflictError uniformly and AddUserToPartnerPortal() documented earlier in the same file can return 409. Added the ConflictError case to the example switch and to the typed-error list.
  • docs/SDKs/partner-php.md — claimed a wrong/mismatched partnerId throws AuthenticationException (401). Verified in PartnerPortalAuthMiddleware.ts on backend origin/master that a partnerId route-mismatch actually returns 404 (NotFoundException); only an invalid/missing key is 401. Split the claim accordingly.
  • docs/SDKs/php.md — statusCode/errorCode were documented as plain int/string. Verified in packages/php-sdk/src/Exceptions/TurboDocxException.php that both are declared ?int/?string. Corrected the property descriptions.
  • docs/SDKs/java.md, deliverable-java.md, partner-java.md, quote-java.md, webhooks-java.md — all five install snippets pinned 0.5.0, which was never published to Maven Central (confirmed via maven-metadata.xml: versions jump 0.4.0 → 0.6.0; latest is 0.7.0). Updated all Maven/Gradle snippets to 0.7.0.
  • docs/SDKs/java.md — removed the "Metadata Configuration (Conditional Fields)" subsection and the metadata/FieldMetadata field row entirely. Downloaded the published turbodocx-sdk-0.7.0.jar from Maven Central and confirmed com.turbodocx.models.FieldMetadata/FieldConditional do not exist in it (only Field, Field$Builder, Field$Offset, Field$Size, Field$TemplateAnchor) — this is an unreleased feature that must not be documented yet.
  • docs/SDKs/partner-java.md — a caution block claimed ConflictException "would never fire" on a partner call and that 409s surface as the base TurboDocxException. Verified in PartnerHttpClient.handleError() that 409 is mapped to ConflictException like every other status. Replaced the caution with an accurate tip.
  • docs/SDKs/deliverable-python.md (and deliverable-go.md, sharing the same defect) — described ValidationError as being raised "when a variable dict is missing a required field" with no specifics. Verified against the backend's variableSchemaWithStack Joi schema (src/models/Variable/IVariable.ts, origin/master): text is conditionally required (required unless the variable sets variableStack or isDisabled/IsDisabled: true), and mimeType/MimeType must be one of a fixed enum. Rewrote both files to name the actual field and condition instead of the vague original wording.

Flagged, not fixed in this PR (out of scope): the "Metadata Configuration (Conditional Fields)" content documenting FieldMetadata/FieldConditional also exists, pre-dating this PR, in go.md, javascript.md, php.md, and python.md. A quick check of the published @turbodocx/sdk@0.7.0 npm/PyPI packages found no equivalent classes there either, suggesting the same unreleased-feature problem across languages. This content already existed on develop before this PR branched and wasn't part of the confirmed finding set reviewed here, so it was left untouched; recommend a follow-up pass. Also flagged but left alone: docs/SDKs/index.md still pins Java to 0.4.0 in its quickstart snippet (a real Maven Central version, so it won't break an install, just inconsistent with the 0.7.0 used elsewhere after this fix).

…/SDKs

10 deliverable-*/partner-* pages carried a full copy of the generic
Error Handling intro + status-code table already documented once on
each language's canonical page (javascript.md, python.md, go.md,
php.md, java.md). template-detector.mjs flagged the same 5-word
phrases across ~17 files, matching the URL Inspection evidence that
javascript, python, java, quote-javascript, webhooks-java,
deliverable-go, and deliverable-php are crawled/discovered but not
indexed.

Replaced the duplicated table on each deliverable-*/partner-* page
with a short paragraph naming the errors that operation actually
raises (verified against /home/nicolas/repos/SDK), followed by a link
to the language's own Error Handling reference for the full table.
Kept the already-differentiated code samples and product-specific
notes (Go's errors.As, PHP's typed exceptions, Java's nested
TurboDocxException.* classes, partner's IOException/409-conflict
callouts) as-is.

Also:
- Fixed a real bug found while verifying code samples: index.md's PHP
  error handling example called $e->getCode(), but PHP's
  Exception::getCode() is hardcoded to 0 by TurboDocxException's
  constructor; the real field is $e->errorCode.
- Fixed two broken links (go.md, java.md pointed at
  /docs/TurboSign/API-Signatures instead of the correctly-encoded
  .../API%20Signatures used elsewhere in the same files) and two
  broken anchors (partner-php.md, partner-javascript.md linked to
  #orguserrole-organization-users, truncated; the real heading
  slugifies to #orguserrole-organization-users-and-org-api-keys).
- Shortened 11 frontmatter descriptions over 160 chars (agent-skills
  + 5 quote-*/5 webhooks-* pages) to <=155 chars, language + product
  first.

Not fixed (noted for the owner): docs/SDKs/ruby.md and
deliverable-ruby.md 404 live but still get search impressions. This
is intentional (draft: true, set in 40efd12 because the gem isn't on
RubyGems yet); Docusaurus excludes draft pages from the production
build. If those impressions are worth capturing, that needs a
redirect decision, not a content change.
@nicolasiscoding nicolasiscoding self-assigned this Sep 23, 2026
Nicolas Fry added 7 commits September 23, 2026 07:52
…s, fix canonical tables

Follow-up to the previous commit after review found three real gaps:

1. The 5 canonical per-language pages (javascript.md, python.md, go.md,
   php.md, java.md) still shared the generic "The SDK provides typed
   error(s)/exception(s) for different ... scenarios" intro sentence
   verbatim, and 3 of them (javascript, python, java) are themselves
   evidence pages (crawled/discovered but not indexed). Rewrote each
   intro to state the real, verified idiom for that language: Go's
   errors.As + embedded struct, PHP's readonly statusCode/errorCode
   (and the getCode()-returns-0 gotcha), Java's nested
   TurboDocxException.* classes with getCode()'s orDefault fallback,
   JS's code passthrough from the API response, Python's DEFAULT_CODE
   class attribute and Exception-subclass catch order. Sourced from
   packages/{go,php,java,js,py}-sdk directly (errors.ts,
   TurboDocxException.java, TurboDocxException.php, http.py).

2. deliverable-go.md and deliverable-php.md linked to go.md/php.md as
   the canonical Error Handling reference for classes those pages
   didn't actually document: go.md's table was missing ConflictError
   (it exists in http.go) and php.md's was missing
   AuthorizationException and ConflictException (both exist in
   packages/php-sdk/src/Exceptions/). Added the missing rows so the
   canonical pages actually contain what the product pages point to.

3. Removed unverified "most commonly" frequency language from the 10
   deliverable-*/partner-* pages' Error Handling intros (added in the
   previous commit); rephrased as "returns/throws/raises X when Y"
   without a frequency claim.

Also swept remaining em-dashes in the 5 base-language pages, now that
they have real body edits (previously only go.md/java.md were fully
swept, for their link fixes).
…andling intro

The previous wording implied errors.As was needed specifically because
TurboDocxError is embedded by value ("so match... rather than a type
switch"), which isn't the right causal link and isn't accurate SDK
guidance (a plain type switch would work fine on the unwrapped return
values; errors.As is just the more defensive/robust choice against any
future wrapping). Reworded to state two independently-true facts: by-
value embedding promotes the fields for direct access, and the SDK's
own example already uses errors.As.
Second review pass found more accuracy issues:

- go.md/java.md/python.md's Code-field descriptions said the machine-
  readable code is "always populated". True only for the 7 named
  subclasses (each has a default). The bare base error returned for an
  unmapped HTTP status (e.g. an unexpected 5xx) can have an empty/null
  code, verified: Go's defaultErrorCode() returns "" in its default
  case, Java's HttpClient.java falls through to
  `new TurboDocxException(message, code, ...)` with no fallback, and
  Python's base TurboDocxError has DEFAULT_CODE = None. Qualified all
  three.

- index.md's Java Error Handling tab imported `com.turbodocx.sdk.*`
  (wrong package; the SDK's actual package is `com.turbodocx`, no
  `.sdk`), used a response type SigningResult that doesn't exist, and
  called `turboSign.sendSignature(...)` on a bare variable instead of
  `client.turboSign().sendSignature(...)`. All three didn't match
  java.md's own (correct) examples. Fixed to match.

- Five deliverable-*.md pages claimed ValidationError fires when a
  variable is missing "placeholder or mimeType". Checked
  RapidDocxBackend's actual generate-deliverable handler
  (DeliverableGenerationHandlers.ts): the Variable interface has
  `placeholder: string` (required) but `mimeType?: string` (optional).
  Dropped the incorrect mimeType half of the claim.
…ied field claim

Third review pass on index.md's Error Handling tabs (the same code
block already touched for the PHP getCode()/Java package fixes):

- Go tab: errors.As(err, &turboErr) targeted *sdk.TurboDocxError only.
  Go's errors.As requires the target's concrete type to match; the 6
  named error types (ValidationError, AuthenticationError, ...) are
  distinct types from TurboDocxError even though they embed it, and
  none implement Unwrap/As, so this silently matched nothing except
  the generic unmapped-status case. The VALIDATION_ERROR branch shown
  was dead code. Fixed to match *sdk.ValidationError directly.

- Python tab: printed e.message, but TurboDocxError.__init__ never
  sets self.message and Python 3's Exception doesn't have one either,
  so this raises AttributeError at runtime. Fixed to {e} (str(e)),
  matching python.md's own examples.

- Java tab: missing the com.turbodocx.models.* import that
  SendSignatureResponse needs (follow-up to the package-name fix in
  the previous commit).

- The "code is always populated" line above these tabs had the same
  gap already qualified on the language pages. Qualified it the same
  way.

Also corrected the 5 deliverable-*.md pages' claim that ValidationError
fires on a variable missing "placeholder or mimeType". Checked
RapidDocxBackend's DeliverableGenerationHandlers.ts: the Variable
interface has placeholder required, mimeType optional (the reverse of
what was claimed), and I could not find where a missing placeholder is
actually validated at the HTTP boundary (the handler doesn't appear to
check it before using it). Rather than assert an unverified 400, all 5
now say "missing a required field" without naming one, matching
deliverable-java.md's already-safe phrasing.
…rors broke the build)

11 SDK pages (agent-skills, quote-*, webhooks-*) had unquoted description
values like 'TurboQuote Go SDK: ...'; YAML reads the second ': ' as a
mapping and Docusaurus fails to build. Quote them.
@nicolasiscoding
nicolasiscoding marked this pull request as ready for review September 23, 2026 15:58
@nicolasiscoding
nicolasiscoding merged commit f2d438e into develop Sep 23, 2026
1 check passed

This branch was successfully deployed

1 active deployment
preview — a662ca4a Deployed Sep 23, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Trace] Template de-dup: de-duplicate SDK doc boilerplate across docs/SDKs

1 participant