From d48ed2e9895ae478a62b25aaa2bca3cce9cf48d2 Mon Sep 17 00:00:00 2001 From: Deepesh123455 Date: Tue, 17 Mar 2026 13:45:10 +0530 Subject: [PATCH 1/7] fix(core-components): resolve DOM nesting warning in OAuthRequestDialog Signed-off-by: Deepesh123455 --- .../OAuthRequestDialog/LoginRequestListItem.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx index a34ae21892..9bd1eead73 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx @@ -92,11 +92,19 @@ const LoginRequestListItem = ({ request, busy, setBusy }: RowProps) => { secondary={ <> {message && ( - + {message} )} - {error && {error}} + {error && ( + + {error} + + )} } /> From 320eed3a6c46d32ebd0e26c16628731d92720395 Mon Sep 17 00:00:00 2001 From: Deepesh123455 Date: Tue, 17 Mar 2026 14:08:58 +0530 Subject: [PATCH 2/7] fix(core-components): address layout feedback and add changeset Signed-off-by: Deepesh123455 --- .changeset/lazy-jars-shake.md | 5 +++++ .../components/OAuthRequestDialog/LoginRequestListItem.tsx | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .changeset/lazy-jars-shake.md diff --git a/.changeset/lazy-jars-shake.md b/.changeset/lazy-jars-shake.md new file mode 100644 index 0000000000..f63191f1bf --- /dev/null +++ b/.changeset/lazy-jars-shake.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Resolved DOM nesting warning in OAuthRequestDialog by rendering secondary text as block-level spans. diff --git a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx index 9bd1eead73..0067f2d82c 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx @@ -95,13 +95,14 @@ const LoginRequestListItem = ({ request, busy, setBusy }: RowProps) => { {message} )} {error && ( - + {error} )} From 375b546fa1c48c4d8882f90eabbc0e0320329936 Mon Sep 17 00:00:00 2001 From: Michael Walsh Date: Fri, 20 Mar 2026 17:19:09 +0100 Subject: [PATCH 3/7] fix(catalog): Fix catalog refresh_state deadlock when running multiple replicas getProcessableEntities uses SELECT ... FOR UPDATE SKIP LOCKED to prevent concurrent processors from selecting the same rows, but it was called with a raw Knex instance instead of a transaxction. This meant the row locks were released immediately after the SELECT, before the subsequent UPDATE executed - making SKIP LOCKED ineffective and allowing multiple replicas to update overlapping rows, causing PostgreSQL deadlock (error 40P01). Wrapping the call in a transaction ensures the locks are held through the UPDATE, so concurrent replicas correctly skip already-claimed rows. Signed-off-by: Michael Walsh --- .changeset/fix-catalog-refresh-state-deadlock.md | 5 +++++ .../src/processing/DefaultCatalogProcessingEngine.ts | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-catalog-refresh-state-deadlock.md diff --git a/.changeset/fix-catalog-refresh-state-deadlock.md b/.changeset/fix-catalog-refresh-state-deadlock.md new file mode 100644 index 0000000000..867bafce49 --- /dev/null +++ b/.changeset/fix-catalog-refresh-state-deadlock.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Fixed a deadlock in the catalog processing loop that occurred when running multiple replicas. The `getProcessableEntities` method used `SELECT ... FOR UPDATE SKIP LOCKED` to prevent concurrent processors from claiming the same rows, but the call was not wrapped in a transaction, so the row locks were released before the subsequent `UPDATE` executed. This allowed multiple replicas to select and update overlapping rows, causing PostgreSQL deadlock errors (code 40P01). diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index 9416fceea1..0f3f764901 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -143,8 +143,10 @@ export class DefaultCatalogProcessingEngine { loadTasks: async count => { try { const { items } = - await this.processingDatabase.getProcessableEntities(this.knex, { - processBatchSize: count, + await this.processingDatabase.transaction(async tx => { + return this.processingDatabase.getProcessableEntities(tx, { + processBatchSize: count, + }); }); return items; } catch (error) { From 35f69e168c9ba4b9d7e450708c637c85c7dfb1c5 Mon Sep 17 00:00:00 2001 From: Michael Walsh Date: Fri, 20 Mar 2026 17:57:29 +0100 Subject: [PATCH 4/7] fix: Run Prettier Signed-off-by: Michael Walsh --- .../src/processing/DefaultCatalogProcessingEngine.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index 0f3f764901..dc97868b1a 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -142,12 +142,13 @@ export class DefaultCatalogProcessingEngine { pollingIntervalMs: this.pollingIntervalMs, loadTasks: async count => { try { - const { items } = - await this.processingDatabase.transaction(async tx => { + const { items } = await this.processingDatabase.transaction( + async tx => { return this.processingDatabase.getProcessableEntities(tx, { processBatchSize: count, }); - }); + }, + ); return items; } catch (error) { this.logger.warn('Failed to load processing items', error); From 7c99d4f3021c375b4dea1bae6156ccbf527580e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 00:29:12 +0000 Subject: [PATCH 5/7] fix(deps): update nextjs monorepo to v16.2.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docs-ui/package.json | 6 +-- docs-ui/yarn.lock | 118 +++++++++++++++++++++---------------------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/docs-ui/package.json b/docs-ui/package.json index 8119bf922c..30b6d28b45 100644 --- a/docs-ui/package.json +++ b/docs-ui/package.json @@ -21,14 +21,14 @@ "@lezer/highlight": "^1.2.1", "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", - "@next/mdx": "16.1.7", + "@next/mdx": "16.2.1", "@remixicon/react": "^4.6.0", "@uiw/codemirror-themes": "^4.23.7", "@uiw/react-codemirror": "^4.23.7", "clsx": "^2.1.1", "html-react-parser": "^5.2.5", "motion": "^12.4.1", - "next": "16.1.7", + "next": "16.2.1", "next-mdx-remote-client": "^2.1.2", "prop-types": "^15.8.1", "react": "19.2.4", @@ -43,7 +43,7 @@ "@types/react": "19.2.10", "@types/react-dom": "19.2.3", "eslint": "^9", - "eslint-config-next": "16.1.7", + "eslint-config-next": "16.2.1", "postcss": "^8.5.6", "postcss-import": "^16.1.1", "typescript": "^5", diff --git a/docs-ui/yarn.lock b/docs-ui/yarn.lock index 3475f63f8f..085b426dc6 100644 --- a/docs-ui/yarn.lock +++ b/docs-ui/yarn.lock @@ -928,25 +928,25 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:16.1.7": - version: 16.1.7 - resolution: "@next/env@npm:16.1.7" - checksum: 10/5f05c5e6e2ecfbfb1f2d828c25d916caf0eb6843d414f38916209f6439fa13b4aa942c317e65bf3c2bc7dee4601158ee505096b689f172c36048af8a9b66c6b0 +"@next/env@npm:16.2.1": + version: 16.2.1 + resolution: "@next/env@npm:16.2.1" + checksum: 10/c4f19f1767d7a1e8e9ff93cdee7e3b6a923d26d9d71f44124a797f03703ab9a18508b5ede997cc99d0307f2e0d0d1c426e9673a6c11ea10e170b87462a572236 languageName: node linkType: hard -"@next/eslint-plugin-next@npm:16.1.7": - version: 16.1.7 - resolution: "@next/eslint-plugin-next@npm:16.1.7" +"@next/eslint-plugin-next@npm:16.2.1": + version: 16.2.1 + resolution: "@next/eslint-plugin-next@npm:16.2.1" dependencies: fast-glob: "npm:3.3.1" - checksum: 10/66a4ced42f0ef5070cc8330633b49f43da8d7c316fdf03c692b681c5d0614bd3332643169eb0545b2be3edf59aa1488d0b559cc4506649a10f1de2af459a18c6 + checksum: 10/8892f8ea6b2a642d9284f05098827f6c15acf3c7e2ff592430080355f8eb3cec7a70ba7543960819d69eff4eba75430eb6ce2fee4c8918abf0d8a9366fa0a59a languageName: node linkType: hard -"@next/mdx@npm:16.1.7": - version: 16.1.7 - resolution: "@next/mdx@npm:16.1.7" +"@next/mdx@npm:16.2.1": + version: 16.2.1 + resolution: "@next/mdx@npm:16.2.1" dependencies: source-map: "npm:^0.7.0" peerDependencies: @@ -957,62 +957,62 @@ __metadata: optional: true "@mdx-js/react": optional: true - checksum: 10/13e365030be521029636d5d74030731f27d3dae75c75e550e7a0949668694aaa707720a537ba8350bc9cfa2a60a657b902a6f23ab2ec44fe2309dd32f1061559 + checksum: 10/eed6747ac8dd048384eb0fd2cc5668bef3e2bc9c27c45a07c03dae8a2466638a26f46b440d6d27546c5f0fafc0df7dbacfe8f503f870e6e77a7c336d915500c4 languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-darwin-arm64@npm:16.1.7" +"@next/swc-darwin-arm64@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-darwin-arm64@npm:16.2.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-darwin-x64@npm:16.1.7" +"@next/swc-darwin-x64@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-darwin-x64@npm:16.2.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-linux-arm64-gnu@npm:16.1.7" +"@next/swc-linux-arm64-gnu@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-arm64-gnu@npm:16.2.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-linux-arm64-musl@npm:16.1.7" +"@next/swc-linux-arm64-musl@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-arm64-musl@npm:16.2.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-linux-x64-gnu@npm:16.1.7" +"@next/swc-linux-x64-gnu@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-x64-gnu@npm:16.2.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-linux-x64-musl@npm:16.1.7" +"@next/swc-linux-x64-musl@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-x64-musl@npm:16.2.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-win32-arm64-msvc@npm:16.1.7" +"@next/swc-win32-arm64-msvc@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-win32-arm64-msvc@npm:16.2.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:16.1.7": - version: 16.1.7 - resolution: "@next/swc-win32-x64-msvc@npm:16.1.7" +"@next/swc-win32-x64-msvc@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-win32-x64-msvc@npm:16.2.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2336,7 +2336,7 @@ __metadata: "@lezer/highlight": "npm:^1.2.1" "@mdx-js/loader": "npm:^3.1.0" "@mdx-js/react": "npm:^3.1.0" - "@next/mdx": "npm:16.1.7" + "@next/mdx": "npm:16.2.1" "@octokit/rest": "npm:^22.0.1" "@remixicon/react": "npm:^4.6.0" "@shikijs/transformers": "npm:^3.13.0" @@ -2348,10 +2348,10 @@ __metadata: "@uiw/react-codemirror": "npm:^4.23.7" clsx: "npm:^2.1.1" eslint: "npm:^9" - eslint-config-next: "npm:16.1.7" + eslint-config-next: "npm:16.2.1" html-react-parser: "npm:^5.2.5" motion: "npm:^12.4.1" - next: "npm:16.1.7" + next: "npm:16.2.1" next-mdx-remote-client: "npm:^2.1.2" postcss: "npm:^8.5.6" postcss-import: "npm:^16.1.1" @@ -2629,11 +2629,11 @@ __metadata: languageName: node linkType: hard -"eslint-config-next@npm:16.1.7": - version: 16.1.7 - resolution: "eslint-config-next@npm:16.1.7" +"eslint-config-next@npm:16.2.1": + version: 16.2.1 + resolution: "eslint-config-next@npm:16.2.1" dependencies: - "@next/eslint-plugin-next": "npm:16.1.7" + "@next/eslint-plugin-next": "npm:16.2.1" eslint-import-resolver-node: "npm:^0.3.6" eslint-import-resolver-typescript: "npm:^3.5.2" eslint-plugin-import: "npm:^2.32.0" @@ -2648,7 +2648,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/5e088f7686bee2b2d50bd9e672c47f18c70807c3695fc54fe290b19d7b179cdf3c8b60e06713b969c164d3333408d40115197a1b3bdc8cbcc0eba8cc3ffba1fb + checksum: 10/3622048ff1883f801c14a21205e9f92fd83172362d6d006fc7a32ea178687a9e11aff0db3aa5fbfb86b32541b03ac127f12da8da12e8fff4430f4757e0ceecfd languageName: node linkType: hard @@ -4587,24 +4587,24 @@ __metadata: languageName: node linkType: hard -"next@npm:16.1.7": - version: 16.1.7 - resolution: "next@npm:16.1.7" +"next@npm:16.2.1": + version: 16.2.1 + resolution: "next@npm:16.2.1" dependencies: - "@next/env": "npm:16.1.7" - "@next/swc-darwin-arm64": "npm:16.1.7" - "@next/swc-darwin-x64": "npm:16.1.7" - "@next/swc-linux-arm64-gnu": "npm:16.1.7" - "@next/swc-linux-arm64-musl": "npm:16.1.7" - "@next/swc-linux-x64-gnu": "npm:16.1.7" - "@next/swc-linux-x64-musl": "npm:16.1.7" - "@next/swc-win32-arm64-msvc": "npm:16.1.7" - "@next/swc-win32-x64-msvc": "npm:16.1.7" + "@next/env": "npm:16.2.1" + "@next/swc-darwin-arm64": "npm:16.2.1" + "@next/swc-darwin-x64": "npm:16.2.1" + "@next/swc-linux-arm64-gnu": "npm:16.2.1" + "@next/swc-linux-arm64-musl": "npm:16.2.1" + "@next/swc-linux-x64-gnu": "npm:16.2.1" + "@next/swc-linux-x64-musl": "npm:16.2.1" + "@next/swc-win32-arm64-msvc": "npm:16.2.1" + "@next/swc-win32-x64-msvc": "npm:16.2.1" "@swc/helpers": "npm:0.5.15" baseline-browser-mapping: "npm:^2.9.19" caniuse-lite: "npm:^1.0.30001579" postcss: "npm:8.4.31" - sharp: "npm:^0.34.4" + sharp: "npm:^0.34.5" styled-jsx: "npm:5.1.6" peerDependencies: "@opentelemetry/api": ^1.1.0 @@ -4643,7 +4643,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: 10/50bfebb84cbcf2091b950d77b78b8877c7de39de705785fe0231c828917a95baffe9c27e84e934b69e294f3e3c07f54a56b4e925b649cf5f5b3140ef3cca3962 + checksum: 10/319c0b18173a90e53b5e5ffafa8a8fecb7cc340b77728796743edd996c7ee7652201892bff60c32f6a3b75abdff1449b77f13f6fab8fd56d4f9da47cf0fb9299 languageName: node linkType: hard @@ -5365,7 +5365,7 @@ __metadata: languageName: node linkType: hard -"sharp@npm:^0.34.4": +"sharp@npm:^0.34.5": version: 0.34.5 resolution: "sharp@npm:0.34.5" dependencies: From 7f26ea88c58c9e6f14d83a4c6b216c4f9260b412 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Date: Tue, 24 Mar 2026 15:44:35 +0100 Subject: [PATCH 6/7] docs: add documentation style guide for Backstage contributors (#33538) * docs: add documentation style guide for Backstage contributors Adapted from the Kubernetes documentation style guide, tailored for the Backstage project with Backstage-specific terminology, Docusaurus conventions, tone guidelines, and project word list. Co-Authored-By: Claude Opus 4.6 Signed-off-by: aramissennyeydd * docs: soften "we" guidance and link style guide from CONTRIBUTING.md Relax the "avoid we" rule to allow "we" in tutorials and walkthroughs where it means "you and I, working through this together." Also add references to the style guide from CONTRIBUTING.md and AGENTS.md. Co-Authored-By: Claude Opus 4.6 Signed-off-by: aramissennyeydd * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> * fix link checker Signed-off-by: aramissennyeydd * skip block Signed-off-by: aramissennyeydd * address feedback Signed-off-by: aramissennyeydd --------- Signed-off-by: aramissennyeydd Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../config/vocabularies/Backstage/accept.txt | 10 +- AGENTS.md | 6 +- CONTRIBUTING.md | 4 +- docs/contribute/doc-style-guide.md | 334 ++++++++++++++++++ microsite/sidebars.ts | 1 + 5 files changed, 349 insertions(+), 6 deletions(-) create mode 100644 docs/contribute/doc-style-guide.md diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index 30fd3e7311..5b9d088e23 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -49,6 +49,7 @@ bundler bundlers bursty callout +callouts camelCase CDNs Chai @@ -59,6 +60,7 @@ chanwit Chanwit CI/CD classname +cleye cli CLIs cloudbuild @@ -138,6 +140,7 @@ dyno ecco elasticsearch Entra +enums env Env esbuild @@ -248,6 +251,7 @@ lightbox Lightsail limitranges liveness +LLMs LocalStack lockdown lockfile @@ -394,6 +398,7 @@ repos requestors rerender rerenders +resizable resourcequotas retryable reusability @@ -562,6 +567,7 @@ VMware Vodafone VPCs VSCode +walkthroughs Wayfair Weaveworks Webpack @@ -580,7 +586,3 @@ zod Zolotusky zoomable zsh -resizable -enums -LLMs -cleye diff --git a/AGENTS.md b/AGENTS.md index 010ebca9e7..15de219e83 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,11 @@ Backstage is an open platform for building developer portals. This is a TypeScri - `/packages/backend`: Example backend for local development - `/docs`: Documentation files -Packages prefixed with `core-` (e.g., `@backstage/core-plugin-api`) are part of the old frontend system. Packages prefixed with `frontend-` (e.g., `@backstage/frontend-plugin-api`) are part of the new frontend system (NFS). Packages prefixed with `backend-` (e.g., `@backstage/backend-plugin-api`) are part of the backend system. +Packages prefixed with `core-` (e.g., `@backstage/core-plugin-api`) are part of the old frontend system. Packages prefixed with `frontend-` (e.g., `@backstage/frontend-plugin-api`) are part of the new frontend system. Packages prefixed with `backend-` (e.g., `@backstage/backend-plugin-api`) are part of the backend system. + +## Writing Standards + +Changes to the docs should follow the documentation style guide at `/docs/contribute/doc-style-guide.md`. ## Code Standards diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index adf04c48e2..5d01886873 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -170,7 +170,9 @@ To help your changes get reviewed and merged smoothly, please keep the following - We really appreciate contributions that improve clarity or fix outdated information. That said, we generally don’t accept changes that are purely stylistic (e.g., rewording a sentence just to tweak the tone or phrasing). If something is **unclear**, **confusing**, or **factually inaccurate**, those are great opportunities to help! -Ready to get started? You can find all the documentation files in the [docs](docs) directory! If you have any questions or need help, feel free to reach out in the [Backstage Discord Docs Channel](https://discord.com/channels/687207715902193673/687994765559463940) +Ready to get started? You can find all the documentation files in the [docs](docs) directory! +Please take a look through [our style guide](./docs/contribute/doc-style-guide.md) as well for writing style tips. +If you have any questions or need help, feel free to reach out in the [Backstage Discord Docs Channel](https://discord.com/channels/687207715902193673/687994765559463940). Thank you in advance for your contributions! We really appreciate it. 🙏 diff --git a/docs/contribute/doc-style-guide.md b/docs/contribute/doc-style-guide.md new file mode 100644 index 0000000000..901df0c55c --- /dev/null +++ b/docs/contribute/doc-style-guide.md @@ -0,0 +1,334 @@ +--- +id: doc-style-guide +title: Documentation Style Guide +description: Writing style guidelines for Backstage documentation +--- + +This page gives writing style guidelines for the Backstage documentation. +These are guidelines, not rules. Use your best judgment, and feel free to +propose changes to this document in a pull request. + +For additional information on contributing to the docs, see the +[Contributors Guide](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#documentation-guidelines). + +## Language + +Backstage documentation uses U.S. English spelling and grammar. + +The documentation site is built with [Docusaurus](https://docusaurus.io/) and +uses standard Markdown with some Docusaurus-specific features like +[admonitions](https://docusaurus.io/docs/markdown-features/admonitions). + +## Tone + +Backstage documentation should feel approachable, professional, and helpful. +Write as if you are a knowledgeable colleague explaining something to a peer +who is new to the topic but not new to software development. + +- **Be friendly but not casual.** Avoid slang, humor that might not translate, + or overly enthusiastic language. A warm, straightforward tone works best. +- **Be respectful of the reader's time.** Get to the point. If a concept needs + a longer explanation, provide it, but don't pad content with filler. +- **Be encouraging without being patronizing.** Assume the reader is competent. + Avoid phrases like "as everyone knows" or "obviously." +- **Be inclusive.** Use gender-neutral language. Avoid cultural references that + might not be understood globally. Write for an international audience. +- **Be precise.** Use the correct technical terminology for Backstage concepts. + When introducing a new term, define it on first use. + +## Documentation formatting standards + +### Use bold for user interface elements + +| Do | Don't | +| :---------------- | :-------------- | +| Click **Fork**. | Click "Fork". | +| Select **Other**. | Select "Other". | + +### Use italics to define or introduce new terms + +| Do | Don't | +| :------------------------------------------ | :-------------------------------------------- | +| A _plugin_ is a modular extension ... | A "plugin" is a modular extension ... | +| These components form the _backend system_. | These components form the **backend system**. | + +### Use code style for filenames, directories, and paths + +| Do | Don't | +| :--------------------------------------------- | :------------------------------------------- | +| Open the `app-config.yaml` file. | Open the app-config.yaml file. | +| Go to the `/plugins` directory. | Go to the /plugins directory. | +| Open the `packages/backend/src/index.ts` file. | Open the packages/backend/src/index.ts file. | + +### Use code style for inline code and commands + +| Do | Don't | +| :------------------------------------------------------------------------- | :------------------------------------------------------------------- | +| The `yarn start` command starts the app. | The "yarn start" command starts the app. | +| Run `yarn install` from the project root. | Run "yarn install" from the project root. | +| Use single backticks to enclose inline code, for example `const x = true`. | Use bold or italics for inline code, for example **const x = true**. | +| Enclose code samples with triple backticks. | Enclose code samples with any other syntax. | +| Use meaningful variable names that have context. | Use variable names such as `foo`, `bar`, and `baz`. | + +### Use code style for package names and API references + + + +| Do | Don't | +| :--------------------------------------------------------------- | :--------------------------------------------------------------- | +| Install the `@backstage/core-plugin-api` package. | Install the @backstage/core-plugin-api package. | +| The `createRouter` function creates a new router. | The createRouter function creates a new router. | +| Set the value of the `backend.baseUrl` field in the config file. | Set the value of the "backend.baseUrl" field in the config file. | + + + +### Use angle brackets for placeholders + +Use angle brackets for placeholders. Tell the reader what a placeholder +represents. For example: + +```shell +yarn workspace @backstage/plugin- start +``` + +### Use the international standard for punctuation inside quotes + +| Do | Don't | +| :---------------------------------------------- | :---------------------------------------------- | +| Events are recorded with an associated "stage". | Events are recorded with an associated "stage." | +| The copy is called a "fork". | The copy is called a "fork." | + +## Code snippet formatting + +### Don't include the command prompt + +| Do | Don't | +| :------------- | :--------------- | +| `yarn install` | `$ yarn install` | + +### Separate commands from output + +Verify that the app is running: + +```shell +yarn start +``` + +The output is similar to this: + +```console +[0] webpack output is served from / +[1] Loaded config from app-config.yaml +``` + +### Use appropriate language tags for code blocks + +Use the correct language identifier for fenced code blocks: `ts` or `typescript` +for TypeScript, `yaml` for YAML configuration, `shell` for shell commands, +`console` for command output, and `diff` for changesets. + +## Admonitions + +Backstage documentation uses +[Docusaurus admonitions](https://docusaurus.io/docs/markdown-features/admonitions) +for callouts. Use `:::note`, `:::tip`, `:::caution`, and `:::danger` as +appropriate. + +```markdown +:::note +You can use _Markdown_ inside admonitions. +::: +``` + +:::note +You can use _Markdown_ inside admonitions. +::: + +Use `:::note` for supplementary information, `:::tip` for helpful suggestions, +`:::caution` for potential pitfalls, and `:::danger` for actions that could +cause data loss or security issues. + +Keep admonitions short and focused. Each admonition should contain a single, +clear point. If you find yourself writing multiple paragraphs inside an +admonition, consider whether the content belongs in the main text instead. + +Avoid stacking multiple admonitions in a row. Too many callouts on a page +dilute their impact and make the content harder to read. If a section has +more than two admonitions, restructure the content so that most of the +information is in regular paragraphs. + +## Markdown elements + +### Line breaks + +Use a single newline to separate block-level content like headings, lists, +images, code blocks, and others. Manually wrap paragraphs in the Markdown +source at a reasonable line length. This makes diffs easier to review and +helps downstream localization. + +### Headings and titles + +| Do | Don't | +| :------------------------------------------------------------------------ | :--------------------------------------------------------------------- | +| Use ordered headings to provide a meaningful outline of your content. | Use headings level 4 through 6 unless absolutely necessary. | +| Use sentence case for headings. For example, **Extend the catalog model** | Use title case for headings. For example, **Extend The Catalog Model** | +| Use pound signs (`#`) for headings. | Use underlines (`---` or `===`) for headings. | + +### Paragraphs + +| Do | Don't | +| :---------------------------------------------------------- | :----------------------------------- | +| Try to keep paragraphs under 6 sentences. | Write long, unbroken walls of text. | +| Use three hyphens (`---`) for horizontal rules when needed. | Use horizontal rules for decoration. | + +### Links + +| Do | Don't | +| :------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | +| Write hyperlinks with descriptive text. For example: See [Getting Started](../getting-started/index.md) for details. | Use ambiguous link text. For example: See [here](../getting-started/index.md) for details. | +| Write Markdown-style links: `[link text](./index.md)`. | Write HTML-style links or create links that open in new tabs. | + +### Lists + +- End each item in a list with a period if one or more items in the list are + complete sentences. For consistency, either all items or none should be + complete sentences. +- Use the number one (`1.`) for ordered lists. +- Use (`-`) for unordered lists. +- Leave a blank line after each list. +- Indent nested lists with two spaces. + +### Tables + +Use Markdown tables with clear column headers. Keep table content concise. +For large amounts of structured data, consider using a list or separate +subsections instead. + +## Content best practices + +### Spell out acronyms on first use + +When using an acronym, spell it out in full on first use followed by the +acronym in parentheses. After that, you can use the acronym alone. + +| Do | Don't | +| :------------------------------------------------------ | :------------------------------------ | +| Software Development Kit (SDK) | SDK (without ever defining it) | +| Role-Based Access Control (RBAC) ... configure RBAC ... | RBAC ... configure RBAC ... | +| Hyper Text Markup Language (HTML) | HTML (on first use without expansion) | + +Exception: Universally understood acronyms like URL, API, or HTML do not +need to be spelled out if they are common knowledge for the target audience +of software developers. + +### Use present tense + +| Do | Don't | +| :---------------------------------- | :-------------------------------------- | +| This command starts a proxy. | This command will start a proxy. | +| The plugin provides a catalog page. | The plugin will provide a catalog page. | + +Exception: Use future or past tense if it is required to convey the correct +meaning. + +### Use active voice + +| Do | Don't | +| :--------------------------------------- | :------------------------------------------ | +| You can explore the API using a browser. | The API can be explored using a browser. | +| The YAML file specifies the base URL. | The base URL is specified in the YAML file. | + +Exception: Use passive voice if active voice leads to an awkward construction. + +### Use simple and direct language + +| Do | Don't | +| :-------------------------- | :------------------------------------------------------- | +| To create a plugin, ... | In order to create a plugin, ... | +| See the configuration file. | Please see the configuration file. | +| View the catalog entities. | With this next command, we'll view the catalog entities. | + +### Address the reader as "you" + +| Do | Don't | +| :--------------------------------------- | :-------------------------------------- | +| You can create a plugin by ... | We'll create a plugin by ... | +| In the preceding output, you can see ... | In the preceding output, we can see ... | + +### Avoid Latin phrases + +Prefer English terms over Latin abbreviations. + +| Do | Don't | +| :--------------- | :-------- | +| For example, ... | e.g., ... | +| That is, ... | i.e., ... | + +Exception: Use "etc." for and so on. + +## Patterns to avoid + +### Be intentional with "we" + +"We" is fine in tutorials and walkthroughs where it means "you and I, working +through this together." Avoid "we" when it's unclear whether it refers to the +Backstage project, the maintainers, or the reader's team. + +| Ok | Avoid | +| :------------------------------------------ | :--------------------------------- | +| Next, we need to add the backend package. | We provide a new feature ... | +| We can verify this by running `yarn start`. | In version 1.25, we have added ... | + +### Avoid jargon and idioms + +Some readers speak English as a second language. Avoid jargon and idioms to +help them understand better. + +| Do | Don't | +| :------------------- | :-------------------- | +| Internally, ... | Under the hood, ... | +| Create a new plugin. | Spin up a new plugin. | + +### Avoid statements about the future + +Avoid making promises or giving hints about the future. If you need to talk +about an experimental feature, clearly label it as such. + +### Avoid statements that will soon be out of date + +Avoid words like "currently" and "new." A feature that is new today might not +be considered new in a few months. + +| Do | Don't | +| :------------------------------ | :---------------------------------- | +| In version 1.25, ... | In the current version, ... | +| The search feature provides ... | The new search feature provides ... | + +### Avoid words that assume a specific level of understanding + +Avoid words such as "just", "simply", "easy", "easily", or "simple". These +words do not add value. + +| Do | Don't | +| :------------------------- | :------------------------------ | +| Include one command in ... | Include just one command in ... | +| Run the container ... | Simply run the container ... | +| You can remove ... | You can easily remove ... | +| These steps ... | These simple steps ... | + +## Backstage word list + +A list of Backstage-specific terms and words to be used consistently across +the site. + +| Term | Usage | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------------- | --- | +| Backstage | Always capitalized. | +| plugin | Lowercase when referring to the concept. Use code style when referring to a specific package, for example `@backstage/plugin-catalog`. | +| Software Catalog | Capitalized as a product name. Use "catalog" (lowercase) when referring to the concept generically. | +| Software Templates | Capitalized as a product name. | +| TechDocs | One word, camel case. | +| Scaffolder | Capitalized as a product name. | +| app-config | Use code style: `app-config.yaml`. | +| open source | Two words, lowercase (unless starting a sentence). | +| backend system | Lowercase when referring to the Backstage backend framework. | | diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index 78319b4cdb..871fbe09e9 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -732,6 +732,7 @@ export default { 'contribute/index', 'contribute/getting-involved', 'contribute/project-structure', + 'contribute/doc-style-guide', ], ), sidebarElementWithIndex( From e0209029d616203c4a5acc55437b424f12d7f24e Mon Sep 17 00:00:00 2001 From: Peter Macdonald Date: Tue, 24 Mar 2026 15:47:41 +0100 Subject: [PATCH 7/7] docs: update golden paths sustainable-plugin-development section (#33539) Signed-off-by: Peter Macdonald --- .../plugins/sustainable-plugin-development.md | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/docs/golden-path/plugins/sustainable-plugin-development.md b/docs/golden-path/plugins/sustainable-plugin-development.md index 4f2753fbb7..d19d5b7ac8 100644 --- a/docs/golden-path/plugins/sustainable-plugin-development.md +++ b/docs/golden-path/plugins/sustainable-plugin-development.md @@ -8,23 +8,53 @@ description: Best practices for maintaining and iterating on Backstage plugins l Plugins are not created in a vacuum, they generally solve a customer ask, be that - a business problem, like showing cloud spend -- a new integration, like showing data from an external vendor such as Pagerduty +- a new integration, like showing data from an external vendor such as PagerDuty - a developer pain point, like organizing information from disjoint or disorganized systems. To ensure that your plugin lives the test of time, you'll need to figure out how to keep it up-to-date, -### Finding your stakeholders +## Finding your stakeholders - +Your internal developer teams are your customers. They are the ones who will use your plugin day-to-day, and they are the best source of truth for whether it's solving the right problems. Before writing a single line of code, it's worth spending time talking to them. -### Iterating on your plugin +Start by identifying which teams are most affected by the problem you're trying to solve. If you're building a cloud spend plugin, talk to the teams who own cloud infrastructure. If you're consolidating on-call information, find the teams that own your incident response process. These are your primary stakeholders. -In many cases, your first version of a plugin will cut a few corners - this is a good sign, you're more focused on delivering a strong use case to continue development than over-indexing on your initial code. It may be temporary after all, if you don't get the response you're looking for! +When you meet with them, listen for: + +- **Pain points**: What manual steps are slowing them down? What information do they have to hunt for across multiple tools? +- **Frequency**: How often do they hit this problem? A daily frustration is worth more investment than a quarterly one. +- **Workarounds**: What are they doing today instead? Existing workarounds often reveal what the minimum viable solution needs to cover. + +Secondary stakeholders like platform teams, engineering managers, or team leads can give you a broader view of organizational needs and help you prioritize across teams. They can also act as champions who drive adoption once your plugin ships. + +Keep these conversations ongoing. A quick check-in after you ship an early version is often more valuable than a long requirements-gathering session upfront. Your stakeholders will give you much clearer feedback once they've seen something working. + +## Iterating on your plugin + +In many cases, your first version of a plugin will cut a few corners. This is a good sign; you're more focused on delivering a strong use case to continue development than over-indexing on your initial code. It may be temporary after all, if you don't get the response you're looking for! So, how do you decide when you should iterate on your plugin? - +The clearest signal is feedback from the teams using it. Go back to the stakeholders you identified earlier. Are they actually using the plugin? Are they hitting friction you didn't anticipate? Direct conversations and usage patterns will tell you far more than assumptions made during initial development. -### Ensuring the success of your plugin +Some common triggers for iteration: - +- **Stakeholder feedback reveals a gap**: A team is using your plugin but still switching to another tool for one specific thing. That gap is your next iteration. +- **Adoption is lower than expected**: If teams aren't using it, find out why before adding features. The problem is often discoverability, missing context, or a workflow mismatch rather than missing functionality. +- **The underlying data or service has changed**: External systems evolve. If your plugin surfaces data from another service, keep a line open with the team that owns it so you're not caught off guard. +- **Analytics surface unexpected patterns**: Backstage has built-in support for analytics events. If you've instrumented your plugin, usage data can reveal which parts of your plugin are heavily used, which are ignored, and where users drop off. A page with high traffic but short visit times might indicate users aren't finding what they need. + +Not every piece of feedback warrants an immediate change. Weigh requests against how broadly they apply; a request from one team may not justify the complexity it adds for everyone else. Your stakeholders are your best guide for prioritization here too. + +## Ensuring the success of your plugin + +A successful plugin is one that continues to be used, trusted, and improved over time. That doesn't happen by accident. It's the result of staying connected to the people who depend on it. + +The foundations are straightforward: + +- **Keep your stakeholder relationships active.** Don't treat the initial conversations as a one-time exercise. Check in regularly, especially after shipping new versions. The teams using your plugin are the fastest way to find out what's working and what isn't. +- **Let feedback drive your priorities.** It can be tempting to iterate on the parts of your plugin you find most interesting technically. Let usage patterns and stakeholder feedback anchor your roadmap instead. +- **Instrument your plugin.** Analytics give you signal between conversations. If a feature is being ignored, or a page has high drop-off, that's worth investigating before investing further in that direction. +- **Treat it like a product, not a project.** A plugin that ships and gets abandoned quickly loses the trust of its users. Even small, regular improvements signal that the plugin is maintained and worth relying on. + +The common thread across all of this is that your developers are your customers. Keeping that relationship healthy is what separates a plugin that becomes a critical part of your developer portal from one that quietly gets bypassed.