zuplo 6.70.70 → 6.71.0
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.
- package/docs/ai-gateway/getting-started.mdx +2 -1
- package/docs/ai-gateway/integrations/ai-sdk.mdx +17 -0
- package/docs/ai-gateway/introduction.mdx +5 -5
- package/docs/ai-gateway/providers.mdx +2 -0
- package/docs/analytics/access-and-entitlements.md +71 -0
- package/docs/analytics/overview.md +67 -0
- package/docs/analytics/reference/metrics-glossary.md +105 -0
- package/docs/analytics/reference/url-parameters.md +66 -0
- package/docs/analytics/shared-controls.md +122 -0
- package/docs/analytics/tabs/agents.md +88 -0
- package/docs/analytics/tabs/consumers.md +73 -0
- package/docs/analytics/tabs/graphql.md +78 -0
- package/docs/analytics/tabs/mcp.md +80 -0
- package/docs/analytics/tabs/origins.md +83 -0
- package/docs/analytics/tabs/requests.md +97 -0
- package/docs/articles/accounts/enterprise-sso.mdx +8 -6
- package/docs/articles/api-key-administration.mdx +4 -0
- package/docs/articles/bypass-policy-for-testing.mdx +4 -0
- package/docs/articles/ci-cd-github/basic-deployment.mdx +10 -1
- package/docs/articles/ci-cd-github/deploy-and-test.mdx +14 -1
- package/docs/articles/ci-cd-github/local-testing.mdx +3 -1
- package/docs/articles/ci-cd-github/pr-preview-environments.mdx +36 -4
- package/docs/articles/custom-ci-cd-github.mdx +11 -2
- package/docs/articles/environment-variables.mdx +5 -1
- package/docs/articles/environments.mdx +2 -2
- package/docs/articles/graphql.mdx +23 -39
- package/docs/articles/mcp-quickstart-local.mdx +2 -1
- package/docs/articles/mcp-quickstart.mdx +6 -1
- package/docs/articles/monetization/api-access.mdx +184 -0
- package/docs/articles/monetization/meters.mdx +4 -4
- package/docs/articles/monetization/monetization-policy.md +4 -1
- package/docs/articles/monetization/private-plans.md +3 -4
- package/docs/articles/monetization/stripe-integration.md +9 -0
- package/docs/articles/monetization/subscription-lifecycle.md +12 -11
- package/docs/articles/monorepo-deployment.mdx +20 -2
- package/docs/articles/multiple-auth-policies.mdx +2 -2
- package/docs/articles/openapi.mdx +6 -1
- package/docs/articles/rename-or-move-project.mdx +4 -0
- package/docs/articles/securing-your-backend.mdx +11 -3
- package/docs/articles/source-control-setup-github.mdx +4 -0
- package/docs/articles/troubleshooting-slow-responses.mdx +2 -2
- package/docs/articles/troubleshooting.md +3 -3
- package/docs/cli/deploy.mdx +32 -0
- package/docs/cli/deploy.partial.mdx +32 -0
- package/docs/concepts/api-keys.md +2 -2
- package/docs/dedicated/akamai/architecture.mdx +9 -9
- package/docs/dev-portal/zudoku/components/browser-window.mdx +94 -0
- package/docs/dev-portal/zudoku/components/callout.mdx +11 -18
- package/docs/dev-portal/zudoku/components/landing-page.mdx +283 -0
- package/docs/dev-portal/zudoku/configuration/search.md +36 -0
- package/docs/dev-portal/zudoku/configuration/site.md +38 -0
- package/docs/dev-portal/zudoku/customization/colors-theme.mdx +51 -40
- package/docs/errors/rate-limit-exceeded.mdx +30 -3
- package/docs/handlers/system-handlers.mdx +2 -1
- package/docs/mcp-gateway/how-to/connect-upstream-api-key.mdx +2 -2
- package/docs/mcp-gateway/observability/analytics.mdx +17 -13
- package/docs/mcp-gateway/quickstart.mdx +4 -3
- package/docs/mcp-gateway/troubleshooting.mdx +4 -4
- package/docs/policies/_index.md +3 -0
- package/docs/policies/data-loss-prevention-inbound/doc.md +115 -0
- package/docs/policies/data-loss-prevention-inbound/intro.md +15 -0
- package/docs/policies/data-loss-prevention-inbound/schema.json +220 -0
- package/docs/policies/data-loss-prevention-outbound/doc.md +115 -0
- package/docs/policies/data-loss-prevention-outbound/intro.md +18 -0
- package/docs/policies/data-loss-prevention-outbound/schema.json +220 -0
- package/docs/policies/graphql-analytics-outbound/doc.md +93 -0
- package/docs/policies/graphql-analytics-outbound/intro.md +12 -0
- package/docs/policies/graphql-analytics-outbound/schema.json +93 -0
- package/docs/programmable-api/background-dispatcher.mdx +6 -8
- package/docs/programmable-api/zone-cache.mdx +1 -1
- package/docs/programmable-api/zuplo-context.mdx +3 -2
- package/docs/rate-limiting/combining-policies.mdx +293 -0
- package/docs/rate-limiting/dynamic-rate-limiting.mdx +240 -0
- package/docs/rate-limiting/getting-started.mdx +339 -0
- package/docs/rate-limiting/how-it-works.md +225 -0
- package/docs/rate-limiting/monitoring-and-troubleshooting.mdx +243 -0
- package/docs/{articles → rate-limiting}/per-user-rate-limits-using-db.mdx +39 -27
- package/package.json +4 -4
- package/docs/concepts/rate-limiting.md +0 -246
|
@@ -25,6 +25,38 @@ zuplo deploy --project my-project
|
|
|
25
25
|
zuplo deploy --project my-project --environment my-env-name
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
### Deploying from CI/CD
|
|
29
|
+
|
|
30
|
+
Without `--environment`, the CLI names the environment after the current git
|
|
31
|
+
branch. CI systems usually check out a detached HEAD, in which case the CLI
|
|
32
|
+
resolves the branch from the remote branches that contain the checked-out
|
|
33
|
+
commit. Two cases break this inference:
|
|
34
|
+
|
|
35
|
+
- On GitHub Actions `pull_request` events, the checkout is the pull request
|
|
36
|
+
merge ref (`refs/pull/<number>/merge`) — a commit that doesn't exist on any
|
|
37
|
+
branch — so the environment is named after that ref instead of your branch.
|
|
38
|
+
- When the checked-out commit exists on more than one branch, the first match
|
|
39
|
+
wins, which may not be the branch that triggered the build.
|
|
40
|
+
|
|
41
|
+
Always pass `--environment` explicitly in CI so that every trigger deploys the
|
|
42
|
+
same, predictably named environment:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# GitHub Actions: github.head_ref is the source branch on pull_request
|
|
46
|
+
# events; github.ref_name is the branch on push events
|
|
47
|
+
zuplo deploy --project my-project --environment "$BRANCH_NAME"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Deploying the same environment name always updates the same environment and
|
|
51
|
+
keeps its URL stable across deploys. This matters whenever an external system
|
|
52
|
+
must match the URL exactly — an OIDC token audience, a webhook registration, or
|
|
53
|
+
an allowlist. Capture the URL from the deploy output (`Deployed to
|
|
54
|
+
https://...`) rather than constructing it from the branch name: the URL
|
|
55
|
+
hostname uses a normalized, truncated form of the environment name plus a
|
|
56
|
+
unique identifier. See
|
|
57
|
+
[Branch-Based Deployments](../articles/branch-based-deployments.mdx) for the
|
|
58
|
+
naming rules.
|
|
59
|
+
|
|
28
60
|
## Polling timeout
|
|
29
61
|
|
|
30
62
|
By default, the deploy command polls the status of the deployment every second
|
|
@@ -50,8 +50,8 @@ After successful validation, the policy populates `request.user`:
|
|
|
50
50
|
- `request.user.data` contains the consumer's metadata (plan, customerId, etc.)
|
|
51
51
|
|
|
52
52
|
This lets downstream policies and handlers make authorization decisions, apply
|
|
53
|
-
per-consumer [rate limits](
|
|
54
|
-
backend.
|
|
53
|
+
per-consumer [rate limits](../rate-limiting/how-it-works.md), or forward
|
|
54
|
+
identity to your backend.
|
|
55
55
|
|
|
56
56
|
:::note
|
|
57
57
|
|
|
@@ -229,7 +229,7 @@ Zuplo and your backend services. For complete documentation, see
|
|
|
229
229
|
| **Shared Secret / API Key** | Add a secret header to requests that only the gateway knows. Simple to implement and widely used by companies like Stripe and Supabase. |
|
|
230
230
|
| **Zuplo JWT Service** | Issue signed JWTs that your backend validates using Zuplo's JWKS endpoint. Provides cryptographic proof that requests originate from your gateway. |
|
|
231
231
|
| **mTLS (Mutual TLS)** | Certificate-based authentication where both gateway and backend present certificates. Provides zero-trust security for enterprise requirements. |
|
|
232
|
-
| **Cloud Provider IAM** | Use AWS IAM, GCP Identity-Aware Proxy, or
|
|
232
|
+
| **Cloud Provider IAM** | Use AWS IAM, GCP Identity-Aware Proxy, or Microsoft Entra ID to authorize requests. No credentials to manage - uses federated identity. |
|
|
233
233
|
| **Secure Tunnel (VPN)** | WireGuard-based tunnel for backends that can't be exposed to the internet. Useful for on-premise or bare-metal deployments. |
|
|
234
234
|
| **Private Network** | VPC peering, PrivateLink, or Transit Gateway for private connectivity without traversing the public internet. |
|
|
235
235
|
|
|
@@ -238,14 +238,14 @@ Zuplo and your backend services. For complete documentation, see
|
|
|
238
238
|
While most authentication methods work anywhere, some approaches are better
|
|
239
239
|
suited for specific scenarios:
|
|
240
240
|
|
|
241
|
-
| Backend Location | Recommended Methods
|
|
242
|
-
| ---------------------------- |
|
|
243
|
-
| **Akamai Connected Cloud** | Shared secret, Zuplo JWT, mTLS
|
|
244
|
-
| **AWS** | AWS IAM (federated identity), mTLS, shared secret
|
|
245
|
-
| **GCP** | GCP Identity-Aware Proxy, GCP Service Auth, mTLS
|
|
246
|
-
| **Azure** |
|
|
247
|
-
| **On-Premise / Data Center** | Secure tunnel, mTLS, shared secret
|
|
248
|
-
| **Third-Party APIs** | Shared secret, API keys, mTLS
|
|
241
|
+
| Backend Location | Recommended Methods | Notes |
|
|
242
|
+
| ---------------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
243
|
+
| **Akamai Connected Cloud** | Shared secret, Zuplo JWT, mTLS | All methods work well; choose based on your security requirements |
|
|
244
|
+
| **AWS** | AWS IAM (federated identity), mTLS, shared secret | IAM provides credential-free auth; works with Lambda, API Gateway, ECS, EKS |
|
|
245
|
+
| **GCP** | GCP Identity-Aware Proxy, GCP Service Auth, mTLS | IAP provides zero-trust access to Cloud Run, GKE, and Compute Engine |
|
|
246
|
+
| **Azure** | Microsoft Entra ID Service Auth, mTLS, shared secret | Microsoft Entra ID integrates with App Service, Functions, and AKS |
|
|
247
|
+
| **On-Premise / Data Center** | Secure tunnel, mTLS, shared secret | Tunnel allows private connectivity; mTLS provides strong authentication |
|
|
248
|
+
| **Third-Party APIs** | Shared secret, API keys, mTLS | Use whatever the third-party API supports |
|
|
249
249
|
|
|
250
250
|
### Choosing an authentication method
|
|
251
251
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Browser Window
|
|
3
|
+
sidebar_icon: app-window
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { BrowserWindow } from "zudoku/components";
|
|
7
|
+
import { Button } from "zudoku/ui/Button";
|
|
8
|
+
|
|
9
|
+
A mock browser window for presenting UI previews, screenshots-as-code, or full page layouts in your
|
|
10
|
+
documentation. It renders its children inside a browser-style frame with a URL bar and an optional
|
|
11
|
+
zoom control — the current scale is displayed like in a real browser and readers can zoom in and out
|
|
12
|
+
themselves.
|
|
13
|
+
|
|
14
|
+
## Import
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { BrowserWindow } from "zudoku/components";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
<BrowserWindow>
|
|
23
|
+
<div className="flex flex-col items-center gap-3 p-10 text-center">
|
|
24
|
+
<span className="text-2xl font-bold">Hello, world!</span>
|
|
25
|
+
<p className="text-muted-foreground">Any content renders inside the browser frame.</p>
|
|
26
|
+
<Button>Get started</Button>
|
|
27
|
+
</div>
|
|
28
|
+
</BrowserWindow>
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<BrowserWindow>
|
|
32
|
+
<div className="flex flex-col items-center gap-3 p-10 text-center">
|
|
33
|
+
<span className="text-2xl font-bold">Hello, world!</span>
|
|
34
|
+
<p className="text-muted-foreground">Any content renders inside the browser frame.</p>
|
|
35
|
+
<Button>Get started</Button>
|
|
36
|
+
</div>
|
|
37
|
+
</BrowserWindow>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Scale
|
|
41
|
+
|
|
42
|
+
Use the `scale` prop to set the initial zoom of the content. This is useful for presenting
|
|
43
|
+
full-width layouts, like a landing page, at a reduced size. Passing a `scale` enables the zoom
|
|
44
|
+
control in the toolbar showing the current scale — readers can change it with the `+`/`-` buttons or
|
|
45
|
+
click the percentage to reset it, just like in a real browser. Without a `scale`, the zoom control
|
|
46
|
+
is hidden and the content renders at full size (pass `scale={1}` to start at 100% with the control
|
|
47
|
+
enabled).
|
|
48
|
+
|
|
49
|
+
<BrowserWindow scale={0.5}>
|
|
50
|
+
<div className="flex flex-col items-center gap-3 p-10 text-center">
|
|
51
|
+
<span className="text-4xl font-bold">Scaled to 50%</span>
|
|
52
|
+
<p className="text-muted-foreground">
|
|
53
|
+
The content is laid out at full width and scaled down to fit.
|
|
54
|
+
</p>
|
|
55
|
+
</div>
|
|
56
|
+
</BrowserWindow>
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<BrowserWindow scale={0.5}>
|
|
60
|
+
<div className="flex flex-col items-center gap-3 p-10 text-center">
|
|
61
|
+
<span className="text-4xl font-bold">Scaled to 50%</span>
|
|
62
|
+
<p className="text-muted-foreground">
|
|
63
|
+
The content is laid out at full width and scaled down to fit.
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
</BrowserWindow>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Scaling affects layout, not just size: at `scale={0.5}` the content is laid out at twice the
|
|
70
|
+
container width and scaled down, so responsive layouts behave as if viewed on a larger screen.
|
|
71
|
+
|
|
72
|
+
## URL
|
|
73
|
+
|
|
74
|
+
Set the `url` prop to change the address shown in the URL bar (defaults to `localhost:3000`):
|
|
75
|
+
|
|
76
|
+
<BrowserWindow url="https://developers.example.com">
|
|
77
|
+
<p className="p-10 text-center text-muted-foreground">Your developer portal</p>
|
|
78
|
+
</BrowserWindow>
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
<BrowserWindow url="https://developers.example.com">
|
|
82
|
+
<p className="p-10 text-center text-muted-foreground">Your developer portal</p>
|
|
83
|
+
</BrowserWindow>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Props
|
|
87
|
+
|
|
88
|
+
| Prop | Type | Description |
|
|
89
|
+
| ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
90
|
+
| `url` | `string` | Address displayed in the URL bar. Defaults to `localhost:3000`. |
|
|
91
|
+
| `scale` | `number` | Initial zoom of the content (e.g. `0.75` for 75%). Enables the zoom control; if omitted, the control is hidden and content renders at full size. |
|
|
92
|
+
| `className` | `string` | Additional classes for the outer frame. |
|
|
93
|
+
| `contentClassName` | `string` | Additional classes for the content viewport. |
|
|
94
|
+
| `children` | `ReactNode` | The content rendered inside the browser window. |
|
|
@@ -193,24 +193,17 @@ Or pass any React node as the `icon` to override the default for the chosen `typ
|
|
|
193
193
|
## Customize colors
|
|
194
194
|
|
|
195
195
|
Each callout type is driven by a single CSS variable that determines the icon, border tint, and
|
|
196
|
-
background tint via `color-mix`. Override any of them in your
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
.dark {
|
|
208
|
-
--callout-tip: oklch(0.78 0.18 160);
|
|
209
|
-
--callout-sparkles: oklch(0.75 0.2 320);
|
|
210
|
-
}
|
|
211
|
-
`,
|
|
212
|
-
},
|
|
213
|
-
};
|
|
196
|
+
background tint via `color-mix`. Override any of them in your stylesheet to recolor a type globally:
|
|
197
|
+
|
|
198
|
+
```css title=styles.css
|
|
199
|
+
:root {
|
|
200
|
+
--callout-tip: oklch(0.65 0.18 160);
|
|
201
|
+
--callout-sparkles: oklch(0.6 0.22 320);
|
|
202
|
+
}
|
|
203
|
+
.dark {
|
|
204
|
+
--callout-tip: oklch(0.78 0.18 160);
|
|
205
|
+
--callout-sparkles: oklch(0.75 0.2 320);
|
|
206
|
+
}
|
|
214
207
|
```
|
|
215
208
|
|
|
216
209
|
All available variables:
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Landing Page
|
|
3
|
+
sidebar_icon: layout-template
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { BrowserWindow, LandingPage } from "zudoku/components";
|
|
7
|
+
import { BookOpenIcon, CodeIcon, KeyIcon, RocketIcon, WebhookIcon, ZapIcon } from "zudoku/icons";
|
|
8
|
+
|
|
9
|
+
A ready-made, customizable landing page for your developer portal. It comes in three variants
|
|
10
|
+
covering the most common layouts: a centered hero, a two-column split hero, and a compact
|
|
11
|
+
documentation hub.
|
|
12
|
+
|
|
13
|
+
Use it as the `element` of a [custom page](/dev-portal/zudoku/custom-pages) — typically your home page:
|
|
14
|
+
|
|
15
|
+
```tsx title=zudoku.config.tsx
|
|
16
|
+
import { LandingPage } from "zudoku/components";
|
|
17
|
+
|
|
18
|
+
const config = {
|
|
19
|
+
navigation: [
|
|
20
|
+
{
|
|
21
|
+
type: "custom-page",
|
|
22
|
+
path: "/",
|
|
23
|
+
element: (
|
|
24
|
+
<LandingPage
|
|
25
|
+
title="Build with our API"
|
|
26
|
+
description="Everything you need to integrate in minutes."
|
|
27
|
+
actions={[
|
|
28
|
+
{ label: "Get started", href: "/getting-started" },
|
|
29
|
+
{ label: "API Reference", href: "/api" },
|
|
30
|
+
]}
|
|
31
|
+
/>
|
|
32
|
+
),
|
|
33
|
+
},
|
|
34
|
+
// ...
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Import
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { LandingPage } from "zudoku/components";
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Variants
|
|
46
|
+
|
|
47
|
+
### Hero (default)
|
|
48
|
+
|
|
49
|
+
A centered hero with call-to-action buttons and an optional feature grid below. The classic landing
|
|
50
|
+
page for product-focused portals. The previews on this page are presented in a
|
|
51
|
+
[Browser Window](./browser-window) component.
|
|
52
|
+
|
|
53
|
+
<BrowserWindow url="https://developers.example.com" scale={0.75} contentClassName="px-8">
|
|
54
|
+
<LandingPage
|
|
55
|
+
eyebrow="Developer Platform"
|
|
56
|
+
title="Build with our API"
|
|
57
|
+
description="Everything you need to integrate payments, webhooks, and more — in minutes, not days."
|
|
58
|
+
actions={[
|
|
59
|
+
{ label: "Get started", href: "/docs/getting-started" },
|
|
60
|
+
{ label: "API Reference", href: "/docs", variant: "outline" },
|
|
61
|
+
]}
|
|
62
|
+
features={[
|
|
63
|
+
{
|
|
64
|
+
icon: <ZapIcon />,
|
|
65
|
+
title: "Fast integration",
|
|
66
|
+
description: "Go from zero to your first API call in under five minutes.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
icon: <KeyIcon />,
|
|
70
|
+
title: "API keys built in",
|
|
71
|
+
description: "Issue, rotate, and revoke keys right from the portal.",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
icon: <WebhookIcon />,
|
|
75
|
+
title: "Webhooks",
|
|
76
|
+
description: "Subscribe to events and react to changes in real time.",
|
|
77
|
+
},
|
|
78
|
+
]}
|
|
79
|
+
/>
|
|
80
|
+
</BrowserWindow>
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<LandingPage
|
|
84
|
+
eyebrow="Developer Platform"
|
|
85
|
+
title="Build with our API"
|
|
86
|
+
description="Everything you need to integrate payments, webhooks, and more — in minutes, not days."
|
|
87
|
+
actions={[
|
|
88
|
+
{ label: "Get started", href: "/getting-started" },
|
|
89
|
+
{ label: "API Reference", href: "/api", variant: "outline" },
|
|
90
|
+
]}
|
|
91
|
+
features={[
|
|
92
|
+
{
|
|
93
|
+
icon: <ZapIcon />,
|
|
94
|
+
title: "Fast integration",
|
|
95
|
+
description: "Go from zero to your first API call in under five minutes.",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
icon: <KeyIcon />,
|
|
99
|
+
title: "API keys built in",
|
|
100
|
+
description: "Issue, rotate, and revoke keys right from the portal.",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
icon: <WebhookIcon />,
|
|
104
|
+
title: "Webhooks",
|
|
105
|
+
description: "Subscribe to events and react to changes in real time.",
|
|
106
|
+
},
|
|
107
|
+
]}
|
|
108
|
+
/>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Split
|
|
112
|
+
|
|
113
|
+
A two-column hero with your own content on the side — an illustration, screenshot, or code sample
|
|
114
|
+
passed via the `aside` prop. A great fit for developer-oriented portals that want to show code up
|
|
115
|
+
front.
|
|
116
|
+
|
|
117
|
+
<BrowserWindow url="https://shipping.example.com" scale={0.75} contentClassName="px-8">
|
|
118
|
+
<LandingPage
|
|
119
|
+
variant="split"
|
|
120
|
+
eyebrow="Shipping API"
|
|
121
|
+
title="Ship anywhere in the whole universe"
|
|
122
|
+
description="Create and manage shipments, track packages in real-time, and integrate with multiple carriers through a single interface."
|
|
123
|
+
actions={[
|
|
124
|
+
{ label: "Get started", href: "/docs/getting-started" },
|
|
125
|
+
{ label: "View on GitHub", href: "https://github.com/zuplo/zudoku", variant: "outline" },
|
|
126
|
+
]}
|
|
127
|
+
aside={
|
|
128
|
+
<div className="rounded-xl border bg-card p-4 font-mono text-sm">
|
|
129
|
+
<pre>{`curl https://api.example.com/v1/shipments \\
|
|
130
|
+
-H "Authorization: Bearer $API_KEY" \\
|
|
131
|
+
-d destination="alpha-centauri"`}</pre>
|
|
132
|
+
</div>
|
|
133
|
+
}
|
|
134
|
+
/>
|
|
135
|
+
</BrowserWindow>
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
<LandingPage
|
|
139
|
+
variant="split"
|
|
140
|
+
eyebrow="Shipping API"
|
|
141
|
+
title="Ship anywhere in the whole universe"
|
|
142
|
+
description="Create and manage shipments, track packages in real-time, and integrate with multiple carriers through a single interface."
|
|
143
|
+
actions={[
|
|
144
|
+
{ label: "Get started", href: "/getting-started" },
|
|
145
|
+
{
|
|
146
|
+
label: "View on GitHub",
|
|
147
|
+
href: "https://github.com/zuplo/zudoku",
|
|
148
|
+
variant: "outline",
|
|
149
|
+
},
|
|
150
|
+
]}
|
|
151
|
+
aside={
|
|
152
|
+
<div className="rounded-xl border bg-card p-4 font-mono text-sm">
|
|
153
|
+
<pre>{`curl https://api.example.com/v1/shipments \\
|
|
154
|
+
-H "Authorization: Bearer $API_KEY" \\
|
|
155
|
+
-d destination="alpha-centauri"`}</pre>
|
|
156
|
+
</div>
|
|
157
|
+
}
|
|
158
|
+
/>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The `aside` accepts any React node — use an `<img />` for an illustration instead of code:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<LandingPage
|
|
165
|
+
variant="split"
|
|
166
|
+
title="Ship anywhere"
|
|
167
|
+
aside={<img src="/hero.webp" alt="Hero" className="rounded-3xl" />}
|
|
168
|
+
/>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Grid
|
|
172
|
+
|
|
173
|
+
A compact header followed by prominent, clickable feature cards. Ideal as a documentation hub that
|
|
174
|
+
routes visitors to the right section quickly.
|
|
175
|
+
|
|
176
|
+
<BrowserWindow url="https://developers.example.com/docs" scale={0.75} contentClassName="px-8">
|
|
177
|
+
<LandingPage
|
|
178
|
+
variant="grid"
|
|
179
|
+
title="Documentation"
|
|
180
|
+
description="Explore guides, API references, and examples to get the most out of the platform."
|
|
181
|
+
features={[
|
|
182
|
+
{
|
|
183
|
+
icon: <RocketIcon />,
|
|
184
|
+
title: "Getting Started",
|
|
185
|
+
description: "Set up your account and make your first request.",
|
|
186
|
+
href: "/docs/getting-started",
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
icon: <BookOpenIcon />,
|
|
190
|
+
title: "Guides",
|
|
191
|
+
description: "Step-by-step tutorials for common use cases.",
|
|
192
|
+
href: "/docs",
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
icon: <CodeIcon />,
|
|
196
|
+
title: "API Reference",
|
|
197
|
+
description: "Complete reference for every endpoint and type.",
|
|
198
|
+
href: "/docs",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
icon: <WebhookIcon />,
|
|
202
|
+
title: "Webhooks",
|
|
203
|
+
description: "Listen to events and build real-time integrations.",
|
|
204
|
+
href: "/docs",
|
|
205
|
+
},
|
|
206
|
+
]}
|
|
207
|
+
/>
|
|
208
|
+
</BrowserWindow>
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
<LandingPage
|
|
212
|
+
variant="grid"
|
|
213
|
+
title="Documentation"
|
|
214
|
+
description="Explore guides, API references, and examples to get the most out of the platform."
|
|
215
|
+
features={[
|
|
216
|
+
{
|
|
217
|
+
icon: <RocketIcon />,
|
|
218
|
+
title: "Getting Started",
|
|
219
|
+
description: "Set up your account and make your first request.",
|
|
220
|
+
href: "/getting-started",
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
icon: <BookOpenIcon />,
|
|
224
|
+
title: "Guides",
|
|
225
|
+
description: "Step-by-step tutorials for common use cases.",
|
|
226
|
+
href: "/guides",
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
icon: <CodeIcon />,
|
|
230
|
+
title: "API Reference",
|
|
231
|
+
description: "Complete reference for every endpoint and type.",
|
|
232
|
+
href: "/api",
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
icon: <WebhookIcon />,
|
|
236
|
+
title: "Webhooks",
|
|
237
|
+
description: "Listen to events and build real-time integrations.",
|
|
238
|
+
href: "/webhooks",
|
|
239
|
+
},
|
|
240
|
+
]}
|
|
241
|
+
/>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Props
|
|
245
|
+
|
|
246
|
+
| Prop | Type | Description |
|
|
247
|
+
| ------------- | ----------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
248
|
+
| `variant` | `"hero" \| "split" \| "grid"` | Layout variant. Defaults to `"hero"`. |
|
|
249
|
+
| `title` | `ReactNode` | Main headline. Required. |
|
|
250
|
+
| `eyebrow` | `ReactNode` | Short label displayed above the title. |
|
|
251
|
+
| `description` | `ReactNode` | Supporting text below the title. |
|
|
252
|
+
| `actions` | `LandingPageAction[]` | Call-to-action buttons. Each action has `label`, `href`, and an optional Button `variant`. |
|
|
253
|
+
| `features` | `LandingPageFeature[]` | Feature cards with optional `icon`, `title`, `description`, and `href` (making the card a link). |
|
|
254
|
+
| `aside` | `ReactNode` | Side content for the `split` variant (image, code sample, …). |
|
|
255
|
+
| `children` | `ReactNode` | Additional content rendered below the built-in sections. |
|
|
256
|
+
| `className` | `string` | Additional classes for the outer `<section>`. |
|
|
257
|
+
|
|
258
|
+
### Links
|
|
259
|
+
|
|
260
|
+
`href` values in `actions` and `features` are rendered as client-side router links for internal
|
|
261
|
+
paths (e.g. `/getting-started`) and as regular links opening in a new tab for external URLs (e.g.
|
|
262
|
+
`https://github.com/...`).
|
|
263
|
+
|
|
264
|
+
## Customization
|
|
265
|
+
|
|
266
|
+
- **Buttons**: The first action defaults to the primary button style, all following actions to
|
|
267
|
+
`outline`. Override per action with `variant` (any [Button](/dev-portal/zudoku/components/button) variant).
|
|
268
|
+
- **Rich titles**: `title`, `description`, and `eyebrow` accept any React node, so you can use
|
|
269
|
+
custom markup like highlighted words:
|
|
270
|
+
`title={<>Ship <span className="text-primary">faster</span></>}`.
|
|
271
|
+
- **Extra sections**: Pass `children` to append your own sections (testimonials, pricing, …) below
|
|
272
|
+
the built-in layout.
|
|
273
|
+
- **Page metadata**: Combine with the [Head](/dev-portal/zudoku/components/head) component to set the page title:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { Head, LandingPage } from "zudoku/components";
|
|
277
|
+
|
|
278
|
+
<LandingPage title="Build with our API">
|
|
279
|
+
<Head>
|
|
280
|
+
<title>Home</title>
|
|
281
|
+
</Head>
|
|
282
|
+
</LandingPage>;
|
|
283
|
+
```
|
|
@@ -167,3 +167,39 @@ your [Dev Portal Configuration](./overview.md):
|
|
|
167
167
|
// ...
|
|
168
168
|
}
|
|
169
169
|
```
|
|
170
|
+
|
|
171
|
+
### Customizing Inkeep
|
|
172
|
+
|
|
173
|
+
Any other [base settings](https://docs.inkeep.com/cloud/ui-components/common-settings/base) can be
|
|
174
|
+
set alongside the required fields, for example `filters` to scope results or `transformSource` to
|
|
175
|
+
customize how sources are displayed.
|
|
176
|
+
|
|
177
|
+
You can also pass
|
|
178
|
+
[`searchSettings`](https://docs.inkeep.com/cloud/ui-components/common-settings/search),
|
|
179
|
+
[`aiChatSettings`](https://docs.inkeep.com/cloud/ui-components/common-settings/ai-chat), and
|
|
180
|
+
`modalSettings` to customize the respective parts of the search experience. They are merged with
|
|
181
|
+
Zudoku's defaults and passed through to Inkeep as-is, so any option Inkeep supports can be used —
|
|
182
|
+
including ones added after this Dev Portal version was released.
|
|
183
|
+
|
|
184
|
+
For example, to categorize results into tabs based on their URL:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
{
|
|
188
|
+
// ...
|
|
189
|
+
search: {
|
|
190
|
+
type: "inkeep",
|
|
191
|
+
// ...required fields from above
|
|
192
|
+
transformSource: (source) => {
|
|
193
|
+
if (!source.url.includes("/blog/")) return source;
|
|
194
|
+
return { ...source, tabs: [...(source.tabs ?? []), "Blog"] };
|
|
195
|
+
},
|
|
196
|
+
searchSettings: {
|
|
197
|
+
tabs: [["All", { isAlwaysVisible: true }], "Blog"],
|
|
198
|
+
},
|
|
199
|
+
aiChatSettings: {
|
|
200
|
+
aiAssistantName: "My Assistant",
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
// ...
|
|
204
|
+
}
|
|
205
|
+
```
|
|
@@ -127,6 +127,44 @@ export const NotFound = () => (
|
|
|
127
127
|
|
|
128
128
|
## Layout
|
|
129
129
|
|
|
130
|
+
### Collapsible Sidebar
|
|
131
|
+
|
|
132
|
+
The navigation sidebar is collapsible by default. A small toggle button on the sidebar's right
|
|
133
|
+
border lets users hide and reveal it. Configure the behavior under `site.sidebar`:
|
|
134
|
+
|
|
135
|
+
```tsx title=zudoku.config.tsx
|
|
136
|
+
{
|
|
137
|
+
site: {
|
|
138
|
+
sidebar: {
|
|
139
|
+
collapsible: true, // default: true. Set to false to disable the toggle entirely.
|
|
140
|
+
toggleVisibility: "always", // "always" (default) or "hover" — show button only when hovering the sidebar's right edge
|
|
141
|
+
togglePosition: "bottom", // "top", "center", or "bottom" (default)
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
For finer vertical placement, override the `--sidebar-toggle-y` CSS variable in your stylesheet:
|
|
148
|
+
|
|
149
|
+
```css
|
|
150
|
+
:root {
|
|
151
|
+
--sidebar-toggle-y: 30%;
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The toggle button carries `aria-expanded="true"` when the sidebar is open and `"false"` when
|
|
156
|
+
collapsed. Combine it with the `[data-sidebar-toggle]` selector to position the button differently
|
|
157
|
+
per state:
|
|
158
|
+
|
|
159
|
+
```css
|
|
160
|
+
[data-sidebar-toggle][aria-expanded="true"] {
|
|
161
|
+
--sidebar-toggle-y: 20%;
|
|
162
|
+
}
|
|
163
|
+
[data-sidebar-toggle][aria-expanded="false"] {
|
|
164
|
+
--sidebar-toggle-y: 80%;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
130
168
|
### Banner
|
|
131
169
|
|
|
132
170
|
Add a banner message to the top of the page:
|