upcontent 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/.github/workflows/ci.yml +61 -0
  2. package/.github/workflows/deploy.yml +59 -0
  3. package/.github/workflows/publish.yml +75 -0
  4. package/.github/workflows/reusable-pages.yml +74 -0
  5. package/.upcontent/config.json +85 -0
  6. package/.upcontent/favicon.svg +4 -0
  7. package/.upcontent/logo.svg +6 -0
  8. package/.upcontent/portal.css +139 -0
  9. package/CONTEXT.md +25 -0
  10. package/Makefile +33 -0
  11. package/README.md +132 -2
  12. package/SHOWCASE.mdx +163 -0
  13. package/assets/readme/portal-home.png +0 -0
  14. package/assets/readme/portal-showcase.png +0 -0
  15. package/astro.config.mjs +167 -0
  16. package/customization/config-json.md +100 -0
  17. package/customization/content.md +62 -0
  18. package/customization/environment.md +43 -0
  19. package/customization/index.md +33 -0
  20. package/customization/navigation.md +57 -0
  21. package/customization/site-identity.md +43 -0
  22. package/customization/theme.md +47 -0
  23. package/deployment/github-pages.md +46 -0
  24. package/deployment/index.md +25 -0
  25. package/deployment/npm.md +39 -0
  26. package/deployment/static-hosts.md +34 -0
  27. package/getting-started/consumer-repository.md +156 -0
  28. package/getting-started/first-build.md +78 -0
  29. package/guides/authoring-content.md +105 -0
  30. package/guides/validate-your-site.md +58 -0
  31. package/package.json +40 -4
  32. package/scripts/upcontent-cli.mjs +111 -0
  33. package/scripts/verify-external-build.mjs +32 -0
  34. package/scripts/verify-golden-build.mjs +9 -0
  35. package/src/components/MermaidLoader.astro +304 -0
  36. package/src/components/PaletteShowcase.astro +122 -0
  37. package/src/components/StructuredDataCopy.astro +22 -0
  38. package/src/content/__mocks__/astro-content.ts +7 -0
  39. package/src/content/__mocks__/astro-loaders.ts +3 -0
  40. package/src/content/i18n/en.json +1 -0
  41. package/src/content.config.test.ts +209 -0
  42. package/src/content.config.ts +113 -0
  43. package/src/lib/content-blocklist.test.ts +47 -0
  44. package/src/lib/content-blocklist.ts +55 -0
  45. package/src/lib/doc-links.test.ts +62 -0
  46. package/src/lib/doc-links.ts +31 -0
  47. package/src/lib/mermaid-render.test.ts +42 -0
  48. package/src/lib/mermaid-render.ts +24 -0
  49. package/src/lib/portal-config.test.ts +153 -0
  50. package/src/lib/portal-config.ts +187 -0
  51. package/src/lib/portal-routes.test.ts +62 -0
  52. package/src/lib/portal-routes.ts +59 -0
  53. package/src/lib/product-identity.ts +2 -0
  54. package/src/lib/rehype-callouts.test.ts +69 -0
  55. package/src/lib/rehype-callouts.ts +61 -0
  56. package/src/lib/remark-doc-links.test.ts +50 -0
  57. package/src/lib/remark-doc-links.ts +21 -0
  58. package/src/lib/remark-strip-duplicate-title.test.ts +73 -0
  59. package/src/lib/remark-strip-duplicate-title.ts +37 -0
  60. package/src/lib/remark-structured-data-preview.test.ts +104 -0
  61. package/src/lib/remark-structured-data-preview.ts +66 -0
  62. package/src/lib/remark-wiki-links.test.ts +102 -0
  63. package/src/lib/remark-wiki-links.ts +112 -0
  64. package/src/lib/seo-sitemap.test.ts +37 -0
  65. package/src/lib/seo-sitemap.ts +54 -0
  66. package/src/lib/sidebar.test.ts +142 -0
  67. package/src/lib/sidebar.ts +114 -0
  68. package/src/lib/structured-data-tree.test.ts +75 -0
  69. package/src/lib/structured-data-tree.ts +55 -0
  70. package/src/overrides/Footer.astro +114 -0
  71. package/src/overrides/Head.astro +103 -0
  72. package/src/pages/robots.txt.ts +46 -0
  73. package/src/styles/callouts.css +29 -0
  74. package/src/styles/structured-data-preview.css +95 -0
  75. package/src/upcontent-cli.test.ts +36 -0
  76. package/test-fixtures/external-consumer/.upcontent/config.json +30 -0
  77. package/test-fixtures/external-consumer/.upcontent/favicon.svg +4 -0
  78. package/test-fixtures/external-consumer/.upcontent/logo.svg +4 -0
  79. package/test-fixtures/external-consumer/.upcontent/theme.css +4 -0
  80. package/test-fixtures/external-consumer/.upcontent-renderer/README.md +3 -0
  81. package/test-fixtures/external-consumer/README.md +6 -0
  82. package/test-fixtures/external-consumer/forbidden.md +5 -0
  83. package/test-fixtures/external-consumer/noindex.md +7 -0
  84. package/test-fixtures/external-consumer/public.md +6 -0
  85. package/tsconfig.json +7 -0
  86. package/vitest.config.ts +18 -0
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: Customization
3
+ description: Configure the portal from the consumer repository without editing the renderer.
4
+ sidebar:
5
+ order: 1
6
+ ---
7
+
8
+ Customization belongs to the consumer repository. The renderer stays shared; the consumer decides what the site is called, how it looks, what appears in navigation, and where it is published.
9
+
10
+ ## Choose a path
11
+
12
+ - [Site identity](site-identity/): title, description, logo, favicon, and repository links.
13
+ - [Theme and CSS](theme/): colors, typography, spacing, and dark mode using Starlight tokens.
14
+ - [Navigation](navigation/): sidebar roots, labels, and content blocklists.
15
+ - [Content behavior](content/): title fields, page metadata, and supported rendered content.
16
+ - [JSON configuration](config-json/): the complete `.upcontent/config.json` guide.
17
+ - [Environment variables](environment/): build-time values for repository URLs and hosting paths.
18
+
19
+ The [configuration reference](config-json/) is the source of truth for supported fields. The [capability showcase](../showcase/) demonstrates the result in one page.
20
+
21
+ ## The customization boundary
22
+
23
+ Consumer-owned files normally live here:
24
+
25
+ ```text
26
+ .upcontent/
27
+ ├── config.json
28
+ ├── favicon.svg
29
+ ├── logo.svg
30
+ └── theme.css
31
+ ```
32
+
33
+ If a customization requires changing `astro.config.mjs`, it is not part of the normal consumer configuration surface.
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: Navigation
3
+ description: Shape the sidebar and keep internal material out of the published portal.
4
+ sidebar:
5
+ order: 4
6
+ ---
7
+
8
+ The sidebar is generated from the consumer file structure. Use configuration when the default filesystem order is not the right experience for readers.
9
+
10
+ ## Select top-level roots
11
+
12
+ ```json
13
+ {
14
+ "navigation": {
15
+ "roots": [
16
+ "README.md",
17
+ "getting-started",
18
+ "guides",
19
+ "reference"
20
+ ]
21
+ }
22
+ }
23
+ ```
24
+
25
+ `roots` limits the files and folders shown at the top level. It does not move files or change their URLs.
26
+
27
+ ## Rename generated labels
28
+
29
+ ```json
30
+ {
31
+ "navigation": {
32
+ "labelOverrides": {
33
+ "api": "API reference",
34
+ "runbooks": "Runbooks"
35
+ }
36
+ }
37
+ }
38
+ ```
39
+
40
+ Keys are matched case-insensitively. Use labels that describe the reader's destination, not the team's internal shorthand.
41
+
42
+ ## Exclude content before parsing
43
+
44
+ ```json
45
+ {
46
+ "navigation": {
47
+ "blocklist": {
48
+ "exact": ["notes.md"],
49
+ "prefixes": ["drafts/", "internal/"]
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ Blocklisted paths are excluded from the content collection and sidebar before Markdown is parsed. The portal also protects internal paths such as `.upcontent/`, `.github/`, `src/`, and `node_modules/`.
56
+
57
+ Blocklisting is not access control. Do not put secrets in a repository that will be published to a public host.
@@ -0,0 +1,43 @@
1
+ ---
2
+ title: Site identity
3
+ description: Give a consumer portal its own name, assets, and repository links.
4
+ sidebar:
5
+ order: 2
6
+ ---
7
+
8
+ The consumer controls the visible identity of the published portal.
9
+
10
+ ## Configuration
11
+
12
+ ```json
13
+ {
14
+ "site": {
15
+ "title": "Engineering Docs",
16
+ "description": "Documentation for the engineering team.",
17
+ "url": "https://docs.example.com",
18
+ "logo": {
19
+ "src": ".upcontent/logo.svg",
20
+ "alt": "Engineering Docs",
21
+ "replacesTitle": false
22
+ },
23
+ "favicon": ".upcontent/favicon.svg"
24
+ },
25
+ "repo": {
26
+ "url": "https://github.com/acme/engineering-docs"
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## Logo behavior
32
+
33
+ Use a compact logo mark when the header should display the site title beside it. Set `replacesTitle` to `true` when the logo already contains the full wordmark.
34
+
35
+ Always provide useful alternative text when the logo communicates identity. Use an empty `alt` when the adjacent visible site title already provides the accessible name.
36
+
37
+ Relative asset paths resolve from the consumer repository. Logo and favicon assets are copied into the static output during the build.
38
+
39
+ ## Repository links
40
+
41
+ `repo.url` powers links that let readers view or edit the source document on GitHub. Set it to the repository containing the content, not the repository containing the shared portal renderer.
42
+
43
+ If the content repository is private, confirm that the links are appropriate for the readers who will receive the published site.
@@ -0,0 +1,47 @@
1
+ ---
2
+ title: Theme and CSS
3
+ description: Customize color, typography, and spacing with the official Starlight CSS seam.
4
+ sidebar:
5
+ order: 3
6
+ ---
7
+
8
+ Use `theme.customCss` to refine the Starlight surface without replacing its layout or accessibility behavior.
9
+
10
+ ## Load a consumer stylesheet
11
+
12
+ ```json
13
+ {
14
+ "theme": {
15
+ "customCss": [".upcontent/theme.css"]
16
+ }
17
+ }
18
+ ```
19
+
20
+ The path is relative to the consumer repository. CSS is bundled during the build, so keep the stylesheet in the content repository rather than depending on a remote stylesheet.
21
+
22
+ ## Use Starlight tokens
23
+
24
+ ```css
25
+ :root {
26
+ --sl-color-accent: #0f766e;
27
+ --sl-color-accent-high: #115e59;
28
+ --sl-font: 'Poppins', sans-serif;
29
+ }
30
+
31
+ :root[data-theme='dark'] {
32
+ --sl-color-accent: #5eead4;
33
+ --sl-color-accent-high: #99f6e4;
34
+ }
35
+ ```
36
+
37
+ Tokens keep custom colors aligned with callouts, links, code blocks, and theme switching.
38
+
39
+ ## Keep the interface coherent
40
+
41
+ - Define both light and dark values for strong colors.
42
+ - Prefer tokens over hard-coded colors in component selectors.
43
+ - Keep body text readable before adjusting decorative styles.
44
+ - Use one display or body family consistently instead of styling every section differently.
45
+ - Check keyboard focus and reduced-motion behavior after adding transitions.
46
+
47
+ The site's stylesheet is a working example of this seam.
@@ -0,0 +1,46 @@
1
+ ---
2
+ title: GitHub Pages
3
+ description: Publish a consumer repository through the reference GitHub Actions workflow.
4
+ sidebar:
5
+ order: 2
6
+ ---
7
+
8
+ The reusable Upcontent workflow builds the consumer repository and uploads `dist/` to GitHub Pages. Run `pnpm dlx upcontent init` in the consumer repository to generate the caller workflow.
9
+
10
+ ## Enable Pages
11
+
12
+ 1. Open the repository's **Settings > Pages**.
13
+ 2. Set the source to **GitHub Actions**.
14
+ 3. Confirm the workflow has `contents: read`, `pages: write`, and `id-token: write` permissions.
15
+ 4. Push to `main` or run the deployment workflow manually.
16
+
17
+ ## Configure the site URL
18
+
19
+ A project site normally needs a base path:
20
+
21
+ ```yaml
22
+ env:
23
+ BASE_PATH: /engineering-docs
24
+ SITE_URL: https://acme.github.io/engineering-docs
25
+ ```
26
+
27
+ A custom domain normally uses an empty base path:
28
+
29
+ ```yaml
30
+ env:
31
+ BASE_PATH: ''
32
+ SITE_URL: https://docs.acme.com
33
+ ```
34
+
35
+ Read [Environment variables](../customization/environment/) before changing these values.
36
+
37
+ ## Verify the published site
38
+
39
+ After deployment, open the published URL and check:
40
+
41
+ - The header logo and favicon load.
42
+ - Internal links include the correct base path.
43
+ - Search returns results.
44
+ - Light and dark themes work.
45
+ - Mermaid, callouts, and structured previews render.
46
+ - The browser console has no required-asset errors.
@@ -0,0 +1,25 @@
1
+ ---
2
+ title: Deployment
3
+ description: Publish the generated static portal to GitHub Pages or another static host.
4
+ sidebar:
5
+ order: 1
6
+ ---
7
+
8
+ Upcontent produces static files. The deployment job only needs to build the content and upload `dist/` to a host that serves HTML, CSS, JavaScript, and assets.
9
+
10
+ ## Choose a path
11
+
12
+ - [GitHub Pages](github-pages/): use the included workflow and repository settings.
13
+ - [Other static hosts](static-hosts/): publish `dist/` to Netlify, Vercel, S3, or another file host.
14
+ - [Release the npm package](npm/): publish versioned package releases through GitHub Actions.
15
+ - [Environment variables](../customization/environment/): set the URL and base path for the host.
16
+
17
+ ## Before publishing
18
+
19
+ ```sh
20
+ pnpm test
21
+ pnpm check
22
+ make build CONTENT_PATH=/path/to/your-consumer-repo
23
+ ```
24
+
25
+ Then confirm that `dist/` contains the generated pages and Pagefind assets.
@@ -0,0 +1,39 @@
1
+ ---
2
+ title: Release the npm package
3
+ description: Publish versioned Upcontent releases through GitHub Actions and npm Trusted Publishing.
4
+ sidebar:
5
+ order: 3
6
+ ---
7
+
8
+ Upcontent publishes the `upcontent` package from version tags. Ordinary pushes to `main` run validation and deploy the documentation portal, but do not publish to npm.
9
+
10
+ ## Configure npm once
11
+
12
+ On the [upcontent npm package](https://www.npmjs.com/package/upcontent), add a GitHub Actions Trusted Publisher with:
13
+
14
+ - Organization or user: `lumamontes`
15
+ - Repository: `upcontent`
16
+ - Workflow filename: `publish.yml`
17
+ - Allow direct `npm publish`
18
+
19
+ Trusted Publishing uses short-lived GitHub OIDC credentials. No npm token is stored in GitHub Actions.
20
+
21
+ ## Release a version
22
+
23
+ Choose the next semantic version, update `package.json`, and commit the change:
24
+
25
+ ```sh
26
+ npm version patch --no-git-tag-version
27
+ git add package.json
28
+ git commit -m "release: v$(node -p "require('./package.json').version")"
29
+ ```
30
+
31
+ Create and push the matching tag:
32
+
33
+ ```sh
34
+ VERSION=$(node -p "require('./package.json').version")
35
+ git tag -a "v$VERSION" -m "Release v$VERSION"
36
+ git push origin main --follow-tags
37
+ ```
38
+
39
+ The publish workflow verifies that the tag and package version match, runs the full validation contract, inspects the package contents, and publishes the package with npm provenance.
@@ -0,0 +1,34 @@
1
+ ---
2
+ title: Other static hosts
3
+ description: Publish dist to a static hosting provider of your choice.
4
+ sidebar:
5
+ order: 3
6
+ ---
7
+
8
+ The output of `make build` is portable. Upload the contents of `dist/` to any host that serves static files.
9
+
10
+ ## Generic flow
11
+
12
+ ```sh
13
+ make build CONTENT_PATH=/path/to/your-consumer-repo
14
+ upload dist/ to your hosting provider
15
+ ```
16
+
17
+ Set `SITE_URL` when the host supports canonical URLs or sitemap generation. Set `BASE_PATH` when the site is served below the domain root.
18
+
19
+ ## Separate portal and content repositories
20
+
21
+ A CI job can check out both repositories before building:
22
+
23
+ ```text
24
+ checkout the portal repository
25
+ checkout the consumer repository
26
+ make build CONTENT_PATH=/workspace/consumer
27
+ upload dist/
28
+ ```
29
+
30
+ The consumer checkout provides Markdown, `.upcontent/config.json`, assets, and CSS. The portal checkout provides the renderer and validation pipeline.
31
+
32
+ ## Privacy
33
+
34
+ A private source repository does not make a public static host private. Use a host with access controls when the published site must be restricted.
@@ -0,0 +1,156 @@
1
+ ---
2
+ title: Set up a consumer repository
3
+ description: Prepare a documentation repository to be rendered by Upcontent.
4
+ sidebar:
5
+ order: 2
6
+ ---
7
+
8
+ A consumer repository is the source of truth for a published portal. It contains the documentation and the `.upcontent/` directory that describes the consumer's identity and presentation.
9
+
10
+ Upcontent itself is also a GitHub repository. This project uses the same consumer contract described here: the repository root is the golden consumer, while `src/` contains the renderer.
11
+
12
+ ## This site as an example
13
+
14
+ The repository behind this site keeps the renderer and its golden consumer together:
15
+
16
+ ```text
17
+ upcontent/
18
+ ├── .upcontent/
19
+ │ ├── config.json
20
+ │ ├── favicon.svg
21
+ │ ├── logo.svg
22
+ │ └── portal.css
23
+ ├── README.md
24
+ ├── getting-started/
25
+ ├── guides/
26
+ ├── customization/
27
+ ├── deployment/
28
+ ├── SHOWCASE.mdx
29
+ ├── package.json
30
+ └── .github/workflows/
31
+ ```
32
+
33
+ The public pages are Markdown or MDX files in the repository root. The renderer implementation lives separately under `src/`; it is not part of the published sidebar. A separate consumer repository only needs its own documentation and `.upcontent/` directory.
34
+
35
+ This site's actual `.upcontent/config.json` uses the same fields available to consumers:
36
+
37
+ ```json
38
+ {
39
+ "site": {
40
+ "title": "Upcontent",
41
+ "description": "Create a beautiful, customizable Starlight portal from your documentation repository.",
42
+ "url": "https://lumamontes.github.io/upcontent",
43
+ "logo": {
44
+ "src": ".upcontent/logo.svg",
45
+ "alt": "",
46
+ "replacesTitle": false
47
+ },
48
+ "favicon": ".upcontent/favicon.svg"
49
+ },
50
+ "repo": {
51
+ "url": "https://github.com/lumamontes/upcontent"
52
+ },
53
+ "theme": {
54
+ "customCss": [".upcontent/portal.css"]
55
+ },
56
+ "starlight": {
57
+ "lastUpdated": true,
58
+ "pagination": true
59
+ }
60
+ }
61
+ ```
62
+
63
+ The filename is `.upcontent/config.json`; `portal.json` is not part of the current contract.
64
+
65
+ ## Recommended structure
66
+
67
+ ```text
68
+ my-consumer-repo/
69
+ ├── .upcontent/
70
+ │ ├── config.json
71
+ │ ├── favicon.svg
72
+ │ ├── logo.svg
73
+ │ └── theme.css
74
+ ├── getting-started/
75
+ │ └── first-page.md
76
+ ├── guides/
77
+ │ └── operating-the-system.md
78
+ └── README.md
79
+ ```
80
+
81
+ The structure is a recommendation, not a requirement. Existing repositories can keep their current folders and use `navigation.roots` and `navigation.labelOverrides` to shape the sidebar.
82
+
83
+ ## Add the Upcontent configuration
84
+
85
+ Create `.upcontent/config.json`:
86
+
87
+ ```json
88
+ {
89
+ "site": {
90
+ "title": "Engineering Docs",
91
+ "description": "Documentation for the engineering team.",
92
+ "logo": {
93
+ "src": ".upcontent/logo.svg",
94
+ "alt": "Engineering Docs"
95
+ },
96
+ "favicon": ".upcontent/favicon.svg"
97
+ },
98
+ "repo": {
99
+ "url": "https://github.com/acme/engineering-docs"
100
+ },
101
+ "theme": {
102
+ "customCss": [".upcontent/theme.css"]
103
+ }
104
+ }
105
+ ```
106
+
107
+ Relative asset paths resolve from the consumer repository. Absolute URLs are also supported for externally hosted assets.
108
+
109
+ See the [capability showcase](../../showcase/) and [configuration reference](../../customization/config-json/) for the supported options.
110
+
111
+ ## Bootstrap with the CLI
112
+
113
+ From the consumer repository root:
114
+
115
+ ```sh
116
+ pnpm dlx upcontent init
117
+ ```
118
+
119
+ This creates the `.upcontent/` directory and a GitHub Pages workflow. The command preserves existing files and asks you to use `--force` before replacing generated files.
120
+
121
+ Preview the repository locally before publishing:
122
+
123
+ ```sh
124
+ pnpm dlx upcontent dev
125
+ ```
126
+
127
+ ## Choose the content root
128
+
129
+ Use the consumer repository itself:
130
+
131
+ ```sh
132
+ make dev CONTENT_PATH=/path/to/my-consumer-repo
133
+ ```
134
+
135
+ For separate portal and content repositories, check out both repositories in the workflow and pass the content checkout as `CONTENT_PATH`.
136
+
137
+ ## Keep internal material private from navigation
138
+
139
+ The portal always excludes its protected internal paths. Add consumer-specific paths with `navigation.blocklist`:
140
+
141
+ ```json
142
+ {
143
+ "navigation": {
144
+ "blocklist": {
145
+ "exact": ["notes.md"],
146
+ "prefixes": ["drafts/", "internal/"]
147
+ }
148
+ }
149
+ }
150
+ ```
151
+
152
+ Blocklisted files are excluded before content parsing. They do not become pages or sidebar links.
153
+
154
+ :::caution
155
+ Blocklisting is a build-time content boundary, not an access-control system. Do not publish secrets or rely on a public static host to protect a private document.
156
+ :::
@@ -0,0 +1,78 @@
1
+ ---
2
+ title: Your first build
3
+ description: Run Upcontent locally and understand what it generates.
4
+ sidebar:
5
+ order: 1
6
+ ---
7
+
8
+ This guide takes you from a cloned Upcontent repository to a local documentation portal. If you have not cloned it yet:
9
+
10
+ ```sh
11
+ git clone https://github.com/lumamontes/upcontent.git
12
+ cd upcontent
13
+ ```
14
+
15
+ ## What you need
16
+
17
+ - Node.js supported by the repository toolchain
18
+ - pnpm
19
+ - A documentation repository containing Markdown or MDX files
20
+
21
+ Install dependencies from the portal repository:
22
+
23
+ ```sh
24
+ pnpm install
25
+ ```
26
+
27
+ ## Start the portal locally
28
+
29
+ Point `CONTENT_PATH` at the documentation repository you want to preview:
30
+
31
+ ```sh
32
+ make dev CONTENT_PATH=.
33
+ ```
34
+
35
+ Open the local URL printed by Astro. Changes to content and consumer configuration are reflected by the development server.
36
+
37
+ ## Build the static site
38
+
39
+ Build the same consumer without a development server:
40
+
41
+ ```sh
42
+ make build CONTENT_PATH=.
43
+ ```
44
+
45
+ The generated site is written to `dist/`. It contains HTML, assets, and the Pagefind search index. Preview the generated output with:
46
+
47
+ ```sh
48
+ pnpm exec astro preview
49
+ ```
50
+
51
+ ## Explore the example
52
+
53
+ Start with these pages:
54
+
55
+ - [Capability showcase](../../showcase/) shows rendering, content, customization, and workflows in one place.
56
+ - [Authoring content](../../guides/authoring-content/) explains the writing conventions used here.
57
+ - [Validate your site](../../guides/validate-your-site/) is the repeatable acceptance checklist.
58
+
59
+ ## Use another consumer repository
60
+
61
+ The portal can render content from a different directory without copying it into this repository:
62
+
63
+ ```sh
64
+ make dev CONTENT_PATH=/path/to/my-consumer-repo
65
+ ```
66
+
67
+ The consumer repository owns its Markdown, `.upcontent/config.json`, assets, and custom CSS. The portal repository owns the renderer and validation pipeline.
68
+
69
+ :::tip[The important boundary]
70
+ Treat `CONTENT_PATH` as the product boundary. If a change only works when files are added to the portal implementation, it is not yet a consumer customization.
71
+ :::
72
+
73
+ ## Next steps
74
+
75
+ 1. Read [Set up a consumer repository](../consumer-repository/).
76
+ 2. Add or review the consumer configuration in `.upcontent/config.json`.
77
+ 3. Follow [Authoring content](../../guides/authoring-content/) before adding new pages.
78
+ 4. Run [Validate your site](../../guides/validate-your-site/).
@@ -0,0 +1,105 @@
1
+ ---
2
+ title: Authoring content
3
+ description: Write clear, navigable Markdown for a static Starlight portal.
4
+ sidebar:
5
+ order: 1
6
+ ---
7
+
8
+ Good documentation is task-oriented, explicit about its audience, and easy to scan. This guide describes the conventions used in a clear technical documentation site.
9
+
10
+ ## Start with the reader's task
11
+
12
+ Prefer a page title that completes the sentence "I want to...":
13
+
14
+ - Good: `Configure a consumer repository`
15
+ - Weak: `Configuration`
16
+
17
+ Open with one or two sentences that explain the outcome. Put prerequisites before the first action. Keep each section focused on one decision or step.
18
+
19
+ ## Use frontmatter deliberately
20
+
21
+ Every page can declare metadata at the top of the file:
22
+
23
+ ```md
24
+ ---
25
+ title: Configure a consumer repository
26
+ sidebar:
27
+ order: 2
28
+ ---
29
+ ```
30
+
31
+ The title becomes the page heading and the default sidebar label. The description is used for page metadata and search context. Use `sidebar.order` only when ordering carries meaning; otherwise let the portal sort pages consistently.
32
+
33
+ ## Structure headings for scanning
34
+
35
+ The page title is the top-level heading generated by Starlight. Start body sections at `##`:
36
+
37
+ ```md
38
+ ## Before you begin
39
+
40
+ ## Configure the repository
41
+
42
+ ### Add the portal configuration
43
+
44
+ ### Verify the result
45
+ ```
46
+
47
+ Short sections, descriptive headings, and lists help readers find the answer without reading every paragraph.
48
+
49
+ ## Show commands in context
50
+
51
+ Use a language tag and explain what the reader should observe:
52
+
53
+ ```sh
54
+ make build CONTENT_PATH=.
55
+ ```
56
+
57
+ Do not show commands without saying where to run them, what they change, or how to verify the result. Use placeholders for values that readers must replace:
58
+
59
+ ```sh
60
+ make dev CONTENT_PATH=/path/to/your-consumer-repo
61
+ ```
62
+
63
+ ## Link to stable concepts
64
+
65
+ Use normal Markdown links for known pages. Use wiki links when the source repository needs filename-oriented references:
66
+
67
+ ```md
68
+ [Validate your site](../guides/validate-your-site/)
69
+ [Capability showcase](../showcase/)
70
+ ```
71
+
72
+ Wiki links must resolve to a document. The build fails when a target is missing, so a typo cannot silently become published broken navigation.
73
+
74
+ ## Use callouts for decisions
75
+
76
+ Callouts should contain short, consequential information:
77
+
78
+ :::tip[Prefer the smallest change]
79
+ Start with consumer configuration and CSS tokens before adding implementation code.
80
+ :::
81
+
82
+ :::caution
83
+ Static output is public wherever the selected host is public. Repository privacy does not automatically make the published portal private.
84
+ :::
85
+
86
+ Avoid turning every paragraph into a callout. If everything is highlighted, nothing is prioritized.
87
+
88
+ ## Make examples executable
89
+
90
+ The showcase uses real examples for Mermaid, JSON, YAML, CSV, callouts, and palette switching. Prefer examples that can be built and inspected over decorative snippets that are never exercised.
91
+
92
+ When an example depends on a file, keep that file in the repository and include the validation command in the surrounding text.
93
+
94
+ ## Content review checklist
95
+
96
+ Before publishing a page, check:
97
+
98
+ - The title describes the reader's outcome.
99
+ - The first paragraph explains why the page exists.
100
+ - Prerequisites appear before actions.
101
+ - Headings begin at `##` in the body.
102
+ - Commands include their working directory and expected result.
103
+ - Links use stable page paths and wiki links resolve.
104
+ - Warnings explain a real risk rather than adding visual noise.
105
+ - The page was built and inspected at desktop and mobile widths.