@lukoweb/apitogo 0.2.60 → 0.2.61

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 (43) hide show
  1. package/dist/cli/cli.js +893 -527
  2. package/docs/cli/commands.md +6 -6
  3. package/docs/cli/go-live.md +12 -12
  4. package/docs/cli/overview.md +26 -27
  5. package/docs/cli/setup.md +38 -46
  6. package/docs/cli/shape.md +32 -35
  7. package/docs/cli/walkthrough.md +19 -19
  8. package/docs/components/slot.mdx +116 -116
  9. package/docs/configuration/api-reference.md +1 -1
  10. package/docs/configuration/authentication.md +3 -3
  11. package/docs/configuration/footer.mdx +89 -89
  12. package/docs/configuration/gateway.md +8 -8
  13. package/docs/configuration/make-config.mdx +20 -10
  14. package/docs/configuration/overview.md +3 -3
  15. package/docs/configuration/plans.md +5 -5
  16. package/docs/configuration/portal.md +36 -0
  17. package/docs/customization/colors-theme.mdx +255 -255
  18. package/docs/customization/fonts.md +105 -105
  19. package/docs/customization/landing-page.md +1 -1
  20. package/docs/deploy/apitogo.md +3 -3
  21. package/docs/deployment.md +3 -3
  22. package/docs/guides/custom-pages.md +3 -3
  23. package/docs/guides/customer-account.md +1 -1
  24. package/docs/guides/stripe-setup.mdx +9 -9
  25. package/docs/markdown/frontmatter.md +2 -2
  26. package/docs/mcp/go-live.md +7 -7
  27. package/docs/mcp/overview.md +58 -58
  28. package/docs/mcp/setup.md +6 -6
  29. package/docs/mcp/shape.md +2 -2
  30. package/docs/mcp/tools.md +57 -57
  31. package/docs/quickstart.md +6 -4
  32. package/docs/writing.mdx +68 -68
  33. package/package.json +1 -1
  34. package/src/config/apitogo-config-core.ts +11 -1
  35. package/src/config/v2/resolve.ts +19 -0
  36. package/src/config/v2/rules.ts +88 -0
  37. package/src/config/v2/schema.ts +28 -0
  38. package/src/config/v2/wrapper.ts +76 -13
  39. package/src/vite/config.ts +278 -273
  40. package/src/vite/markdown-output-path.ts +48 -0
  41. package/src/vite/plugin-markdown-export.ts +210 -214
  42. package/src/vite/prerender/prerender.ts +4 -4
  43. package/src/vite/watch-ignore.ts +19 -0
@@ -1,116 +1,116 @@
1
- ---
2
- title: Slot
3
- sidebar_icon: between-horizontal-start
4
- description:
5
- Use the low-level Slot component for advanced slot management in custom pages and MDX content.
6
- ---
7
-
8
- The `Slot` component provides low-level access to APIToGo's slot system, allowing you to
9
- programmatically manage content injection in custom pages and React components.
10
-
11
- ## Import
12
-
13
- ```tsx
14
- import { Slot } from "@lukoweb/apitogo/components";
15
- ```
16
-
17
- ## Components
18
-
19
- The Slot system consists of two main components:
20
-
21
- ### Slot.Target
22
-
23
- Renders content that has been injected into a specific slot.
24
-
25
- ```tsx
26
- <Slot.Target name="my-slot" fallback={<div>No content</div>} />
27
- ```
28
-
29
- **Props:**
30
-
31
- - `name` (required): The slot name to render content for
32
- - `fallback` (optional): Content to show when no slot content is available
33
-
34
- ### Slot.Source
35
-
36
- Injects content into a specific slot. This component renders nothing but registers content to be
37
- displayed by `Slot.Target` components.
38
-
39
- ```tsx
40
- <Slot.Source name="my-slot" type="append">
41
- <div>Content to inject</div>
42
- </Slot.Source>
43
- ```
44
-
45
- **Props:**
46
-
47
- - `name` (required): The slot name to inject content into
48
- - `type` (optional): How to handle multiple content sources
49
- - `"replace"` (default): Replace existing content
50
- - `"prepend"`: Add before existing content
51
- - `"append"`: Add after existing content
52
- - `children`: The content to inject
53
-
54
- ## Usage Example
55
-
56
- ```tsx
57
- function MyCustomPage() {
58
- return (
59
- <div>
60
- <h1>My Page</h1>
61
-
62
- {/* Render slot content here */}
63
- <Slot.Target name="custom-page-header" />
64
-
65
- {/* Inject content into a slot */}
66
- <Slot.Source name="custom-page-header">
67
- <div className="bg-blue-100 p-4 rounded">Custom header content</div>
68
- </Slot.Source>
69
-
70
- <p>Page content here...</p>
71
- </div>
72
- );
73
- }
74
- ```
75
-
76
- ## Type Safety
77
-
78
- The Slot component is fully type-safe. All predefined slot names are available with autocomplete:
79
-
80
- ```tsx
81
- // These will show autocomplete for available slot names
82
- <Slot.Target name="head-navigation-end" />
83
- <Slot.Source name="footer-before">Content</Slot.Source>
84
- ```
85
-
86
- ### Adding Custom Slot Names
87
-
88
- To add your own slot names with full type safety, augment the `CustomSlotNames` type:
89
-
90
- ```tsx
91
- // types/slots.d.ts
92
- declare module "@lukoweb/apitogo" {
93
- type CustomSlotNames = "my-custom-header" | "sidebar-extra";
94
- }
95
- ```
96
-
97
- ## Integration with Configuration
98
-
99
- The Slot component works with configuration-based slots. Content defined in your
100
- `apitogo.config.json` and content injected via `Slot.Source` components will be combined according
101
- to the `type` parameter.
102
-
103
- ```tsx
104
- // In your site config
105
- slots: {
106
- "page-header": <div>Config header</div>
107
- }
108
-
109
- // In your component
110
- <Slot.Source name="page-header" type="append">
111
- <Button>Go Home</Button>
112
- </Slot.Source>
113
-
114
- // Renders both: Config header, then Component button
115
- <Slot.Target name="page-header" />
116
- ```
1
+ ---
2
+ title: Slot
3
+ sidebar_icon: between-horizontal-start
4
+ description:
5
+ Use the low-level Slot component for advanced slot management in custom pages and MDX content.
6
+ ---
7
+
8
+ The `Slot` component provides low-level access to APIToGo's slot system, allowing you to
9
+ programmatically manage content injection in custom pages and React components.
10
+
11
+ ## Import
12
+
13
+ ```tsx
14
+ import { Slot } from "@lukoweb/apitogo/components";
15
+ ```
16
+
17
+ ## Components
18
+
19
+ The Slot system consists of two main components:
20
+
21
+ ### Slot.Target
22
+
23
+ Renders content that has been injected into a specific slot.
24
+
25
+ ```tsx
26
+ <Slot.Target name="my-slot" fallback={<div>No content</div>} />
27
+ ```
28
+
29
+ **Props:**
30
+
31
+ - `name` (required): The slot name to render content for
32
+ - `fallback` (optional): Content to show when no slot content is available
33
+
34
+ ### Slot.Source
35
+
36
+ Injects content into a specific slot. This component renders nothing but registers content to be
37
+ displayed by `Slot.Target` components.
38
+
39
+ ```tsx
40
+ <Slot.Source name="my-slot" type="append">
41
+ <div>Content to inject</div>
42
+ </Slot.Source>
43
+ ```
44
+
45
+ **Props:**
46
+
47
+ - `name` (required): The slot name to inject content into
48
+ - `type` (optional): How to handle multiple content sources
49
+ - `"replace"` (default): Replace existing content
50
+ - `"prepend"`: Add before existing content
51
+ - `"append"`: Add after existing content
52
+ - `children`: The content to inject
53
+
54
+ ## Usage Example
55
+
56
+ ```tsx
57
+ function MyCustomPage() {
58
+ return (
59
+ <div>
60
+ <h1>My Page</h1>
61
+
62
+ {/* Render slot content here */}
63
+ <Slot.Target name="custom-page-header" />
64
+
65
+ {/* Inject content into a slot */}
66
+ <Slot.Source name="custom-page-header">
67
+ <div className="bg-blue-100 p-4 rounded">Custom header content</div>
68
+ </Slot.Source>
69
+
70
+ <p>Page content here...</p>
71
+ </div>
72
+ );
73
+ }
74
+ ```
75
+
76
+ ## Type Safety
77
+
78
+ The Slot component is fully type-safe. All predefined slot names are available with autocomplete:
79
+
80
+ ```tsx
81
+ // These will show autocomplete for available slot names
82
+ <Slot.Target name="head-navigation-end" />
83
+ <Slot.Source name="footer-before">Content</Slot.Source>
84
+ ```
85
+
86
+ ### Adding Custom Slot Names
87
+
88
+ To add your own slot names with full type safety, augment the `CustomSlotNames` type:
89
+
90
+ ```tsx
91
+ // types/slots.d.ts
92
+ declare module "@lukoweb/apitogo" {
93
+ type CustomSlotNames = "my-custom-header" | "sidebar-extra";
94
+ }
95
+ ```
96
+
97
+ ## Integration with Configuration
98
+
99
+ The Slot component works with configuration-based slots. Content defined in your
100
+ `apitogo.config.json` and content injected via `Slot.Source` components will be combined according
101
+ to the `type` parameter.
102
+
103
+ ```tsx
104
+ // In your site config
105
+ slots: {
106
+ "page-header": <div>Config header</div>
107
+ }
108
+
109
+ // In your component
110
+ <Slot.Source name="page-header" type="append">
111
+ <Button>Go Home</Button>
112
+ </Slot.Source>
113
+
114
+ // Renders both: Config header, then Component button
115
+ <Slot.Target name="page-header" />
116
+ ```
@@ -31,7 +31,7 @@ The page shows your API as people call it, through the gateway, not as it runs b
31
31
  - Operations in `gateway.policies.operations.public` show no security, since they need no key.
32
32
  - Operations in `gateway.policies.operations.deny` are left out.
33
33
 
34
- Before the first deploy the gateway has no address yet, so `npx apitogo run` leaves the page out and
34
+ Before the first deploy the gateway has no address yet, so `apitogo run` leaves the page out and
35
35
  says so. It appears once the gateway is deployed.
36
36
 
37
37
  ## Try it
@@ -72,7 +72,7 @@ Add an OpenID Connect provider next to email and password. Its client secret is
72
72
  ```
73
73
 
74
74
  ```bash
75
- npx apitogo secrets set MICROSOFT_CLIENT_SECRET
75
+ apitogo secrets set MICROSOFT_CLIENT_SECRET
76
76
  ```
77
77
 
78
78
  Set `"native": false` to offer only the connections.
@@ -108,8 +108,8 @@ The API reference's Try it then also offers **Signed-in user**, which sends that
108
108
 
109
109
  ## Local preview
110
110
 
111
- `npx apitogo run` before the first deploy has no sign-in service yet. The console then signs in with
112
- a demo account, so you can try every page:
111
+ `apitogo run` before the first deploy has no sign-in service yet. The console then signs in with a
112
+ demo account, so you can try every page:
113
113
 
114
114
  ```text
115
115
  demo@apitogo.local / password
@@ -1,89 +1,89 @@
1
- ---
2
- title: Footer
3
- sidebar_label: Footer
4
- sidebar_icon: panel-bottom-dashed
5
- description: >-
6
- The portal's footer is a React file you own, named by portal.footer. It shows under every page
7
- except the console's.
8
- ---
9
-
10
- The footer is a React file in your folder, **`apitogo/portal/footer/Footer.tsx`**, named by
11
- `portal.footer` in `apitogo.config.json`:
12
-
13
- ```json title=apitogo.config.json
14
- {
15
- "portal": {
16
- "footer": "apitogo/portal/footer/Footer.tsx"
17
- }
18
- }
19
- ```
20
-
21
- It shows under the home page, the docs, the API reference and the pricing page. It is not shown on
22
- the console's pages (`/account`, `/login`, `/signup`).
23
-
24
- `apitogo add portal` writes a starter footer and the setting. Remove `portal.footer` to have no
25
- footer.
26
-
27
- ## The starter footer
28
-
29
- The starter uses `FooterSection` from `@lukoweb/apitogo-module-landing`, so it matches the home
30
- page. Change anything in it:
31
-
32
- ```tsx title=apitogo/portal/footer/Footer.tsx
33
- import { FooterSection } from "@lukoweb/apitogo-module-landing";
34
-
35
- const NAME = "Books API";
36
-
37
- export default function Footer() {
38
- return (
39
- <FooterSection
40
- footer={{
41
- brand: { name: NAME, tagline: "Documentation, API keys and plans for the Books API." },
42
- columns: [
43
- {
44
- title: "Developers",
45
- links: [
46
- { label: "Documentation", href: "/introduction" },
47
- { label: "API Reference", href: "/api" },
48
- { label: "Pricing", href: "/pricing" },
49
- ],
50
- },
51
- {
52
- title: "Company",
53
- links: [{ label: "Contact", href: "mailto:hello@example.com" }],
54
- },
55
- ],
56
- social: [{ icon: "github", href: "https://github.com/example", label: "GitHub" }],
57
- copyright: `© ${new Date().getFullYear()} ${NAME}`,
58
- }}
59
- />
60
- );
61
- }
62
- ```
63
-
64
- `FooterSection` takes:
65
-
66
- | Field | What it is |
67
- | ----------- | --------------------------------------------------------------------------- |
68
- | `brand` | `name`, an optional `tagline`, and an optional `logoSrc` (an image address) |
69
- | `columns` | Link columns: a `title` and `links` of `{ label, href }` |
70
- | `social` | Icon links: `icon` (`github`, `x`), `href` and an optional `label` |
71
- | `copyright` | The last line; by default `© <year> <name>. All rights reserved.` |
72
-
73
- ## Your own footer
74
-
75
- The file can render anything: it is a React component, and its default export is the footer. Use the
76
- theme's classes (`bg-background`, `text-muted-foreground`, `border-t`) so it follows light and dark
77
- mode:
78
-
79
- ```tsx title=apitogo/portal/footer/Footer.tsx
80
- export default function Footer() {
81
- return (
82
- <footer className="border-t bg-background py-8 text-center text-sm text-muted-foreground">
83
- © {new Date().getFullYear()} Books API · <a href="/pricing">Pricing</a>
84
- </footer>
85
- );
86
- }
87
- ```
88
-
89
- `apitogo check` reports a `portal.footer` that names a file that does not exist.
1
+ ---
2
+ title: Footer
3
+ sidebar_label: Footer
4
+ sidebar_icon: panel-bottom-dashed
5
+ description: >-
6
+ The portal's footer is a React file you own, named by portal.footer. It shows under every page
7
+ except the console's.
8
+ ---
9
+
10
+ The footer is a React file in your folder, **`apitogo/portal/footer/Footer.tsx`**, named by
11
+ `portal.footer` in `apitogo.config.json`:
12
+
13
+ ```json title=apitogo.config.json
14
+ {
15
+ "portal": {
16
+ "footer": "apitogo/portal/footer/Footer.tsx"
17
+ }
18
+ }
19
+ ```
20
+
21
+ It shows under the home page, the docs, the API reference and the pricing page. It is not shown on
22
+ the console's pages (`/account`, `/login`, `/signup`).
23
+
24
+ `apitogo add portal` writes a starter footer and the setting. Remove `portal.footer` to have no
25
+ footer.
26
+
27
+ ## The starter footer
28
+
29
+ The starter uses `FooterSection` from `@lukoweb/apitogo-module-landing`, so it matches the home
30
+ page. Change anything in it:
31
+
32
+ ```tsx title=apitogo/portal/footer/Footer.tsx
33
+ import { FooterSection } from "@lukoweb/apitogo-module-landing";
34
+
35
+ const NAME = "Books API";
36
+
37
+ export default function Footer() {
38
+ return (
39
+ <FooterSection
40
+ footer={{
41
+ brand: { name: NAME, tagline: "Documentation, API keys and plans for the Books API." },
42
+ columns: [
43
+ {
44
+ title: "Developers",
45
+ links: [
46
+ { label: "Documentation", href: "/introduction" },
47
+ { label: "API Reference", href: "/api" },
48
+ { label: "Pricing", href: "/pricing" },
49
+ ],
50
+ },
51
+ {
52
+ title: "Company",
53
+ links: [{ label: "Contact", href: "mailto:hello@example.com" }],
54
+ },
55
+ ],
56
+ social: [{ icon: "github", href: "https://github.com/example", label: "GitHub" }],
57
+ copyright: `© ${new Date().getFullYear()} ${NAME}`,
58
+ }}
59
+ />
60
+ );
61
+ }
62
+ ```
63
+
64
+ `FooterSection` takes:
65
+
66
+ | Field | What it is |
67
+ | ----------- | --------------------------------------------------------------------------- |
68
+ | `brand` | `name`, an optional `tagline`, and an optional `logoSrc` (an image address) |
69
+ | `columns` | Link columns: a `title` and `links` of `{ label, href }` |
70
+ | `social` | Icon links: `icon` (`github`, `x`), `href` and an optional `label` |
71
+ | `copyright` | The last line; by default `© <year> <name>. All rights reserved.` |
72
+
73
+ ## Your own footer
74
+
75
+ The file can render anything: it is a React component, and its default export is the footer. Use the
76
+ theme's classes (`bg-background`, `text-muted-foreground`, `border-t`) so it follows light and dark
77
+ mode:
78
+
79
+ ```tsx title=apitogo/portal/footer/Footer.tsx
80
+ export default function Footer() {
81
+ return (
82
+ <footer className="border-t bg-background py-8 text-center text-sm text-muted-foreground">
83
+ © {new Date().getFullYear()} Books API · <a href="/pricing">Pricing</a>
84
+ </footer>
85
+ );
86
+ }
87
+ ```
88
+
89
+ `apitogo check` reports a `portal.footer` that names a file that does not exist.
@@ -188,7 +188,7 @@ with a secret that only the gateway sends:
188
188
  ```
189
189
 
190
190
  ```bash
191
- npx apitogo secrets set GATEWAY_SECRET
191
+ apitogo secrets set GATEWAY_SECRET
192
192
  ```
193
193
 
194
194
  The value is a reference, never the secret itself. The secret is stored encrypted and never shown
@@ -221,11 +221,11 @@ If you have no place to host your API, the platform can run your code. Set the o
221
221
  | `healthPath` | Path the platform probes to check that your API is up. |
222
222
  | `exclude` | More paths to leave out, in `.gitignore` syntax. |
223
223
 
224
- `npx apitogo add gateway --origin managed` makes the `source` folder when it does not exist and
225
- tells you it is empty; put your code there. `npx apitogo check` warns while the folder has no code.
224
+ `apitogo add gateway --origin managed` makes the `source` folder when it does not exist and tells
225
+ you it is empty; put your code there. `apitogo check` warns while the folder has no code.
226
226
 
227
- `npx apitogo project create` prepares the hosting for your code. `npx apitogo deploy` then uploads
228
- the OpenAPI file and the config, uploads your code and waits until it runs, and the gateway starts
227
+ `apitogo project create` prepares the hosting for your code. `apitogo deploy` then uploads the
228
+ OpenAPI file and the config, uploads your code and waits until it runs, and the gateway starts
229
229
  sending calls to it. A deploy with the same code uploads nothing. A .NET project is published for
230
230
  you (this needs the .NET SDK on your machine), or you can point `source` at a folder that is already
231
231
  published.
@@ -249,15 +249,15 @@ if (req.headers[header] !== process.env.APITOGO_ORIGIN_SECRET) {
249
249
  Run these before you deploy:
250
250
 
251
251
  ```bash
252
- npx apitogo check
253
- npx apitogo plan
252
+ apitogo check
253
+ apitogo plan
254
254
  ```
255
255
 
256
256
  `check` finds mistakes in the file, offline. `plan` shows what a deploy would change and changes
257
257
  nothing. Then deploy and test the address that `apitogo status` shows:
258
258
 
259
259
  ```bash
260
- npx apitogo deploy --only gateway
260
+ apitogo deploy --only gateway
261
261
  curl -i https://YOUR-GATEWAY-ADDRESS/health
262
262
  curl -i https://YOUR-GATEWAY-ADDRESS/orders
263
263
  ```
@@ -7,7 +7,7 @@ description: >-
7
7
  and plans.
8
8
  ---
9
9
 
10
- The **`npx apitogo config`** command changes a project made by `apitogo create` or `apitogo init`
10
+ The **`apitogo config`** command changes a project made by `apitogo create` or `apitogo init`
11
11
  (config version 2). It edits **`apitogo.config.json`**, writes docs pages under
12
12
  **`apitogo/portal/pages/`**, and keeps plans in **`apitogo/plans.json`**.
13
13
 
@@ -32,13 +32,22 @@ page in `guides/quickstart.tsx` shows under a **Guides** section at `/guides/qui
32
32
  are React components by default; pass `--page-format mdx` for a Markdown page. See
33
33
  [Custom pages](../guides/custom-pages.md).
34
34
 
35
+ A page that belongs in the header's top menu instead of the sidebar (Partners, About, Contact) takes
36
+ `--page-header`: the React page goes to `apitogo/portal/header-pages/<slug>.tsx` (`.mdx` with
37
+ `--page-format mdx`) and a link is added to `portal.header.links`. See
38
+ [Header links](./portal.md#header-links).
39
+
40
+ ```bash
41
+ apitogo config --page-slug partners --page-title Partners --page-header
42
+ ```
43
+
35
44
  Changing a gateway or plan needs that service in the project. Add it first with
36
45
  `apitogo add gateway` or `apitogo add plans`.
37
46
 
38
47
  ## Interactive wizard
39
48
 
40
- On a TTY, bare `npx apitogo config` opens the wizard. Each answer is applied at once. Type `done`
41
- (the default) to finish.
49
+ On a TTY, bare `apitogo config` opens the wizard. Each answer is applied at once. Type `done` (the
50
+ default) to finish.
42
51
 
43
52
  - **`backend`**: folder of your API code, runtime (`nodejs` / `python` / `dotnet`) and version
44
53
  - **`openapi`**: an OpenAPI file to add to `gateway.specs`
@@ -46,7 +55,7 @@ On a TTY, bare `npx apitogo config` opens the wizard. Each answer is applied at
46
55
  - **`plan`**: title, fixed or custom price, rate limit per minute, quota per 30 days; added to
47
56
  `plans.json`
48
57
 
49
- Payments go through Stripe. When you add a **paid** plan, `npx apitogo deploy` asks for your Stripe
58
+ Payments go through Stripe. When you add a **paid** plan, `apitogo deploy` asks for your Stripe
50
59
  secret key the first time (if the project has none yet). Free and contact-us plans need no key. Paid
51
60
  plans also need Starter or Professional platform hosting.
52
61
 
@@ -65,6 +74,7 @@ plans also need Starter or Professional platform hosting.
65
74
  | `--page-title <title>` | Title of the page (required when adding) |
66
75
  | `--page-content <markdown>` | Markdown body of the page |
67
76
  | `--page-update` | Change an existing page instead of adding one |
77
+ | `--page-header` | Link the page from the header's top menu instead of the sidebar |
68
78
  | `--plan <json>` | Add a plan to `plans.json`, or replace the plan with the same `sku` |
69
79
  | `--patch <json>` | Deep-merge a JSON object into `apitogo.config.json` |
70
80
  | `--json` | Print a JSON summary on stdout |
@@ -85,12 +95,12 @@ A plan uses the `plans.json` shape:
85
95
  Examples:
86
96
 
87
97
  ```bash
88
- npx apitogo config
89
- npx apitogo config --title "Books API"
90
- npx apitogo config --page-slug guides/quickstart --page-title "Quickstart"
91
- npx apitogo config --plan '{"sku":"free","displayName":"Free"}'
92
- npx apitogo config --source server --runtime nodejs --runtime-version NODE_22_LTS
93
- npx apitogo config --patch '{"portal":{"search":"none"}}'
98
+ apitogo config
99
+ apitogo config --title "Books API"
100
+ apitogo config --page-slug guides/quickstart --page-title "Quickstart"
101
+ apitogo config --plan '{"sku":"free","displayName":"Free"}'
102
+ apitogo config --source server --runtime nodejs --runtime-version NODE_22_LTS
103
+ apitogo config --patch '{"portal":{"search":"none"}}'
94
104
  ```
95
105
 
96
106
  ## See also
@@ -84,13 +84,13 @@ names a project secret:
84
84
  "plans": { "billing": { "apiKey": "secret:STRIPE_API_KEY" } }
85
85
  ```
86
86
 
87
- Store the value with `npx apitogo secrets set STRIPE_API_KEY`. Deploy asks for the secrets it needs
88
- and stores them for you. A value written straight into the config is refused.
87
+ Store the value with `apitogo secrets set STRIPE_API_KEY`. Deploy asks for the secrets it needs and
88
+ stores them for you. A value written straight into the config is refused.
89
89
 
90
90
  ## Check before you deploy
91
91
 
92
92
  ```bash
93
- npx apitogo check
93
+ apitogo check
94
94
  ```
95
95
 
96
96
  `check` reads the config and the files it names, and says what is missing or wrong, with a hint for
@@ -25,7 +25,7 @@ The plans themselves live in **`apitogo/plans.json`**. `apitogo add plans` creat
25
25
  `apitogo config` adds plans interactively or with `--plan` (a plan with the same `sku` is replaced):
26
26
 
27
27
  ```bash
28
- npx apitogo config --plan '{"sku":"free","displayName":"Free"}'
28
+ apitogo config --plan '{"sku":"free","displayName":"Free"}'
29
29
  ```
30
30
 
31
31
  ## plans.json
@@ -89,7 +89,7 @@ Each card lists, in this order:
89
89
  2. The plan's `features`
90
90
  3. The endpoints it includes: the ones in `includedActions`, or every operation of the gateway
91
91
 
92
- `npx apitogo run` shows the same cards as the deployed portal.
92
+ `apitogo run` shows the same cards as the deployed portal.
93
93
 
94
94
  ## Paid plans
95
95
 
@@ -124,11 +124,11 @@ request is emailed to the project's sales contact, or to its owner.
124
124
  ## Deploy
125
125
 
126
126
  ```bash
127
- npx apitogo deploy --only plans
127
+ apitogo deploy --only plans
128
128
  ```
129
129
 
130
- deploys the plans, their limits on the gateway and the pricing page. A plain `npx apitogo deploy`
131
- does it together with everything else.
130
+ deploys the plans, their limits on the gateway and the pricing page. A plain `apitogo deploy` does
131
+ it together with everything else.
132
132
 
133
133
  ## Hosting plans are something else
134
134
 
@@ -36,6 +36,7 @@ its starter files.
36
36
  | `landing` | none | A React file shown at `/`, the home page |
37
37
  | `footer` | none | A React file shown under every page except the console's |
38
38
  | `logo` | none (the header shows `name`) | The header logo ([below](#logo)) |
39
+ | `header` | none | Your own links in the header's top menu ([below](#header-links)) |
39
40
  | `theme` | `apitogo/portal/theme.json` | Colors and fonts ([Colors & theme](../customization/colors-theme.mdx)) |
40
41
  | `console` | `{ "enabled": true }` | The sign-in, plans, keys and usage pages, when identity or plans is on |
41
42
  | `search` | `pagefind` | `pagefind`, `inkeep` or `none` |
@@ -71,6 +72,41 @@ setting to have none. See [Landing page](../customization/landing-page.md) and
71
72
 
72
73
  When there is a home page, `/` shows it, and an `index` page of the docs opens at `/index`.
73
74
 
75
+ ## Header links
76
+
77
+ `header.links` adds your own links to the top menu, after **Documentation** and **API Reference**
78
+ (the plans service adds **Pricing** itself). A link is either a page of its own or an address:
79
+
80
+ ```json
81
+ "header": {
82
+ "links": [
83
+ { "label": "Partners", "page": "apitogo/portal/header-pages/partners.tsx" },
84
+ { "label": "Status", "to": "https://status.example.com" }
85
+ ]
86
+ }
87
+ ```
88
+
89
+ - **`page`**: a React page (`.tsx`, its default export is the page) or a Markdown page (`.md`,
90
+ `.mdx`), served at `/<file name>` (`partners.tsx` is `/partners`). It is a page of its own: the
91
+ docs sidebar does not list it. It needs hosted docs, and a portal with `requireAuth` keeps it
92
+ behind sign-in like the docs.
93
+ - **`to`**: a path on the portal (`/blog`) or an `https://` address, which opens in a new tab.
94
+
95
+ The CLI makes the file and the link in one step:
96
+
97
+ ```bash
98
+ apitogo config --page-slug partners --page-title Partners --page-header
99
+ ```
100
+
101
+ The page is a React component in `apitogo/portal/header-pages/partners.tsx`; add `--page-format mdx`
102
+ for a Markdown page instead. Its title (`export const title`) is the link's label.
103
+ `--page-update --page-title` with `--page-header` renames the page and its link and leaves your code
104
+ as it is. Links show in the order of the list; edit it to reorder them.
105
+
106
+ `apitogo check` refuses a page that is missing, is not `.tsx`, `.md` or `.mdx`, or would take an
107
+ address the portal already uses (`/pricing`, `/account`, `/api`, `/login`, `/signup` or a docs
108
+ page).
109
+
74
110
  ## logo
75
111
 
76
112
  An image in the portal's `public/` folder, or an `https://` address: