docs: Improve README for local development and standardize tab usage (#11865)

## Problem statement

- `<Tabs>` were not rendered in docs
- Missing steps in README for local dev

## How it was solved

- Enhance the README to better describe local development setup and
clean up formatting.
- Standardize the use of tabs across various components for consistency.

## Additional info

To not cause merge conflicts with
https://github.com/zitadel/zitadel/pull/11729 changes in
`/self-hosting/manage/configure/configure.mdx` were skipped
This commit is contained in:
Silvan
2026-03-23 14:39:07 +00:00
committed by GitHub
parent 70adaff793
commit 4bc899d052
9 changed files with 110 additions and 111 deletions
+47 -13
View File
@@ -8,6 +8,12 @@ Ensure you have followed the [root quick start](../../CONTRIBUTING.md#quick-star
### Local Development
Ensure all dependencies are installed:
```bash
pnpm install
```
Start the development server:
```bash
@@ -34,17 +40,50 @@ Key scripts for documentation workflows:
### Validation
* **Code Quality**: Run `pnpm lint` to check for syntax and style issues in JS/TS/MDX files.
* **Content Integrity**: Run `pnpm check:links` to validate content structure, including:
* **Code Quality**: Run `pnpm nx run @zitadel/docs:lint` to check for syntax and style issues in JS/TS/MDX files.
* **Content Integrity**: Run `pnpm nx run @zitadel/docs:check-links` to validate content structure, including:
* Broken internal links
* Missing required front-matter (e.g., `title`)
* Image references
### Troubleshooting
#### Issue: Nx configuration not found or "nx" command not found
If you see errors like:
```bash
NX Cannot find configuration for task @zitadel/zitadel:@zitadel/docs:generate
Pass --verbose to see the stacktrace.
```
or
```
pnpm nx run @zitadel/docs:dev
 ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL  Command "nx" not found
Did you mean "pnpm nx"?
```
**Root cause**: Your dependency cache or `node_modules` is out of sync.
**Solution**: Run these commands from the repository root in order:
1. **Clear node_modules**: `rm -rf node_modules` — removes the installed dependency folder
2. **Clear pnpm cache**: `pnpm cache delete` — clears pnpm's internal package cache
3. **Reinstall dependencies**: `pnpm install` — reinstalls all dependencies fresh
4. **Test the setup**: `pnpm nx run @zitadel/docs:generate` — verifies everything works
This resolves 99% of setup-related issues.
## Contributing
### Build Process
The docs build process automatically handling the following steps via `generate`:
The docs build process automatically handles the following steps via `generate`:
1. Downloads required protoc plugins.
2. Generates gRPC documentation from proto files.
3. Generates API documentation from OpenAPI specs.
@@ -52,10 +91,10 @@ The docs build process automatically handling the following steps via `generate`
### Style Guide
- **Variables**: Use environment variables in code snippets where possible.
- **Embedded Content**: Use `_filename.mdx` for content embedded in other pages (not indexed individually).
- **Code Embedding**: Use the `file` property in code blocks to embed code from the repo.
- **Voice**: Use active voice and sentence case for titles.
* **Variables**: Use environment variables in code snippets where possible.
* **Embedded Content**: Use `_filename.mdx` for content embedded in other pages (not indexed individually).
* **Code Embedding**: Use the `file` property in code blocks to embed code from the repo.
* **Voice**: Use active voice and sentence case for titles.
Refer to the [Google Developer Style Guide](https://developers.google.com/style) for general guidelines.
@@ -64,10 +103,10 @@ Refer to the [Google Developer Style Guide](https://developers.google.com/style)
All documentation content is located in the `content` directory. Note that the system strictly accepts **only `.mdx` files**.
To add a new page:
1. Create a `.mdx` file in the appropriate subdirectory of [`content`](./content).
2. Register the new page in the sidebar settings at [`lib/sidebar-data.ts`](./lib/sidebar-data.ts) to make it accessible in the navigation.
### Pull Requests
Use `docs(<scope>): <short summary>` for PR titles.
@@ -75,9 +114,4 @@ Pass quality checks before submitting:
```bash
pnpm nx run @zitadel/docs:build
pnpm nx run @zitadel/docs:check:links
```
You can also run specific steps individually:
* `pnpm fetch:remote-content`
* `pnpm generate:api-reference`
@@ -63,13 +63,8 @@ Depending on your authorization method you will have to provide additional param
<Tabs
groupId="token-auth-methods"
defaultValue="client_secret_basic"
values={[
{label: 'client_secret_basic', value: 'client_secret_basic'},
{label: 'client_secret_post', value: 'client_secret_post'},
{label: 'none (PKCE)', value: 'none'},
{label: 'private_key_jwt', value: 'private_key_jwt'},
]}
defaultIndex={0}
items={['client_secret_basic','client_secret_post','none (PKCE)','private_key_jwt']}
>
<Tab value="client_secret_basic">
no additional parameters required
@@ -77,7 +72,7 @@ no additional parameters required
<Tab value="client_secret_post">
no additional parameters required
</Tab>
<Tab value="none">
<Tab value="none (PKCE)">
| Parameter | Description |
| --------------------- | ----------------------------------------------------- |
@@ -192,13 +187,8 @@ Depending on your authorization method you will have to provide additional param
<Tabs
groupId="token-auth-methods"
defaultValue="client_secret_basic"
values={[
{label: 'client_secret_basic', value: 'client_secret_basic'},
{label: 'client_secret_post', value: 'client_secret_post'},
{label: 'none (PKCE)', value: 'none'},
{label: 'private_key_jwt', value: 'private_key_jwt'},
]}
defaultIndex={0}
items={['client_secret_basic','client_secret_post','none (PKCE)','private_key_jwt']}
>
<Tab value="client_secret_basic">
@@ -215,7 +205,7 @@ Send your `client_id` and `client_secret` as parameters in the body:
| client_secret | client_secret of the application |
</Tab>
<Tab value="none">
<Tab value="none (PKCE)">
Send your `client_id` and `code_verifier` for us to recompute the `code_challenge` of the authorization request.
@@ -292,13 +282,8 @@ Depending on your authorization method you will have to provide additional param
<Tabs
groupId="token-auth-methods"
defaultValue="client_secret_basic"
values={[
{label: 'client_secret_basic', value: 'client_secret_basic'},
{label: 'client_secret_post', value: 'client_secret_post'},
{label: 'none (PKCE)', value: 'none'},
{label: 'private_key_jwt', value: 'private_key_jwt'},
]}
defaultIndex={0}
items={['client_secret_basic','client_secret_post','none (PKCE)','private_key_jwt']}
>
<Tab value="client_secret_basic">
@@ -315,7 +300,7 @@ Send your `client_id` and `client_secret` as parameters in the body:
| client_secret | client_secret of the application |
</Tab>
<Tab value="none">
<Tab value="none (PKCE)">
Send your `client_id` as parameter in the body. No authentication is required.
@@ -402,13 +387,8 @@ Depending on your authorization method you will have to provide additional param
<Tabs
groupId="token-auth-methods"
defaultValue="client_secret_basic"
values={[
{label: 'client_secret_basic', value: 'client_secret_basic'},
{label: 'client_secret_post', value: 'client_secret_post'},
{label: 'none', value: 'none'},
{label: 'private_key_jwt', value: 'private_key_jwt'},
]}
defaultIndex={0}
items={['client_secret_basic','client_secret_post','none (PKCE)','private_key_jwt']}
>
<Tab value="client_secret_basic">
@@ -426,7 +406,7 @@ Send your `client_id` and `client_secret` as parameters in the body:
| client_secret | client_secret of the application |
</Tab>
<Tab value="none">
<Tab value="none (PKCE)">
Send your `client_id` as parameter in the body. No authentication is required.
@@ -478,11 +458,8 @@ Depending on your authorization method you will have to provide additional param
<Tabs
groupId="introspect-auth-methods"
defaultValue="client_secret_basic"
values={[
{label: 'client_secret_basic', value: 'client_secret_basic'},
{label: 'private_key_jwt', value: 'private_key_jwt'},
]}
defaultIndex={0}
items={['client_secret_basic','private_key_jwt']}
>
<Tab value="client_secret_basic">
@@ -586,13 +563,8 @@ Depending on your authorization method you will have to provide additional param
<Tabs
groupId="token-auth-methods"
defaultValue="client_secret_basic"
values={[
{label: 'client_secret_basic', value: 'client_secret_basic'},
{label: 'client_secret_post', value: 'client_secret_post'},
{label: 'none (PKCE)', value: 'none'},
{label: 'private_key_jwt', value: 'private_key_jwt'},
]}
defaultIndex={0}
items={['client_secret_basic','client_secret_post','none (PKCE)','private_key_jwt']}
>
<Tab value="client_secret_basic">
@@ -609,7 +581,7 @@ Send your `client_id` and `client_secret` as parameters in the body:
| client_secret | client_secret of the application |
</Tab>
<Tab value="none">
<Tab value="none (PKCE)">
Send your `client_id` as parameters in the body:
@@ -132,7 +132,7 @@ You will need to implement a listener that can receive HTTP requests.
For this example, we will use a simple Go HTTP server that will print the received request to standard output.
As mentioned before, this validation can and should be applied to any target implementation.
<Tabs>
<Tabs defaultIndex={0} items={['JSON', 'JWT', 'JWE']}>
<Tab value="JSON">
<DynamicCodeBlock lang="go" code={JsonGo} />
</Tab>
@@ -168,8 +168,12 @@ You can also activate the v2 login for your apps, so users are redirected to `/u
**Customizing the new login:** The easiest way to actually customizing it is to fork the https://github.com/zitadel/zitadel repo and use the [Deploy with Vercel button](https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#login-deploy) to run your login code on Vercel.
<Tabs queryString="deployment">
<Tab value="zitadel_cloud" label="Activate Zitadel Cloud V2 Login" default="true">
<Tabs
groupId="deployment"
defaultIndex={0}
items={['Activate Zitadel Cloud V2 Login', 'Vercel Custom Login Deployment']}
>
<Tab value="Activate Zitadel Cloud V2 Login">
Zitadel Cloud provides the V2 login at the fixed path `/ui/v2/login`.
<PreventLockout components={props.components} />
@@ -181,7 +185,7 @@ You can also activate the v2 login for your apps, so users are redirected to `/u
2. Enable the [loginV2 feature](/reference/api/feature/zitadel.feature.v2.FeatureService.SetInstanceFeatures) on the instance. Leave the base URI empty to use the default. If you enable this feature, the login will be used for every application configured in your Zitadel instance. (Example: https://your-zitadel-instance.zitadel.cloud/ui/v2/login)
</Tab>
<Tab value="vercel_custom" label="Vercel Custom Login Deployment">
<Tab value="Vercel Custom Login Deployment">
The simplest way to deploy the new login for yourself is by using the [Deploy with Vercel button](https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#login-deploy) to deploy the login directly to your Vercel.
@@ -10,20 +10,16 @@ export default function AuthMethods(props) {
<div>
<Tabs
groupId="auth-type"
default="pkce"
values={[
{ label: "PKCE", value: "pkce" },
{ label: "Basic Auth", value: "basic" },
{ label: "JWT with Private Key", value: "jwtpk" },
]}
defaultIndex={0}
items={["PKCE","Basic Auth","JWT with Private Key"]}
>
<Tab value="pkce">
<Tab value="PKCE">
<PKCE components={props.components} />
</Tab>
<Tab value="basic">
<Tab value="Basic Auth">
<Basic components={props.components} />
</Tab>
<Tab value="jwtpk">
<Tab value="JWT with Private Key">
<JWTPrivateKey components={props.components} />
</Tab>
</Tabs>
@@ -31,26 +27,23 @@ export default function AuthMethods(props) {
) : props.selected == "native" ? (
<Tabs
groupId="auth-type"
default="pkce"
values={[{ label: "PKCE", value: "pkce" }]}
defaultIndex={0}
items={["PKCE"]}
>
<Tab value="pkce">
<Tab value="PKCE">
<PKCE components={props.components} Native />
</Tab>
</Tabs>
) : props.selected == "spa" ? (
<Tabs
groupId="auth-type"
default="pkce"
values={[
{ label: "PKCE", value: "pkce" },
{ label: "Implicit", value: "implicit" },
]}
defaultIndex={0}
items={["PKCE","Implicit"]}
>
<Tab value="pkce">
<Tab value="PKCE">
<PKCE components={props.components} />
</Tab>
<Tab value="implicit">
<Tab value="Implicit">
<Implicit components={props.components} />
</Tab>
</Tabs>
@@ -53,14 +53,10 @@ This will start a wizard asking you for an application name and a type.
<Tabs
groupId="app-type"
default="web"
values={[
{'label': 'Web Application', 'value': 'web'},
{'label': 'Native Application', 'value': 'native'},
{'label': 'Single Page Application', 'value': 'spa'},
]}
defaultIndex={0}
items={['Web Application','Native Application','Single Page Application']}
>
<Tab value="web">
<Tab value="Web Application">
#### Authentication method
@@ -73,7 +69,7 @@ Please change the authentication method here as well, if you did so in the wizar
<AuthMethods components={props.components} selected="web" />
</Tab>
<Tab value="native">
<Tab value="Native Application">
#### Authentication method
@@ -82,7 +78,7 @@ When selecting Native the authentication method always needs to be PKCE.
<AuthMethods components={props.components} selected="native" />
</Tab>
<Tab value="spa">
<Tab value="Single Page Application">
#### Authentication method
@@ -5,8 +5,8 @@ If you started with Zitadel before version 3, you might have the "Human User [de
In this case please enable the Feature Flag "Use V2 Api in Management Console for User creation" in the Default Settings.
</Callout>
<Tabs>
<Tab value="human" label="Human User" default>
<Tabs groupId="create-user-types" defaultIndex={0} items={['Human User', 'Human User [deprecated]', 'Service Account']}>
<Tab value="Human User">
<img src="/docs/img/guides/console/invitehuman.png" width="680px" alt="Invite Human" />
When creating a new user you have different options.
@@ -21,7 +21,7 @@ In this case please enable the Feature Flag "Use V2 Api in Management Console fo
- **Set an initial password for the user**: The user will receive an email and be able to setup an authentication method (e.g Password, Passkey, External SSO)
</Tab>
<Tab value="human_deprecated" label="Human User [deprecated]">
<Tab value="Human User [deprecated]">
<img src="/docs/img/guides/console/addhuman.png" width="680px" alt="Add Human" />
After a user is created, by default, an initialization mail with a code is sent to the registered email. This code then has to be verified on first login.
@@ -29,7 +29,7 @@ In this case please enable the Feature Flag "Use V2 Api in Management Console fo
If no password is set initially, the initialization mail prompting the user to set his password is sent.
</Tab>
<Tab value="service" label="Service Account">
<Tab value="Service Account">
<img
src="/docs/img/guides/console/addmachine.png"
width="540px"
@@ -39,8 +39,8 @@ A provider with HTTP type will send the messages and the data to a pre-defined w
### Configuring a HTTP provider
<Tabs>
<Tab value="sms" label="SMS" default>
<Tabs groupId="http-provider-configuration" defaultIndex={0} items={['SMS', 'Email']}>
<Tab value="SMS">
First [add a new SMS Provider of type HTTP](/reference/api/admin/zitadel.admin.v1.AdminService.AddSMSProviderHTTP) to create a new HTTP provider that can be used to send SMS messages:
@@ -74,7 +74,7 @@ A provider with HTTP type will send the messages and the data to a pre-defined w
See full API reference for [SMS Providers](/reference/api/admin) for more details.
</Tab>
<Tab value="email" label="Email">
<Tab value="Email">
First [add a new Email Provider of type HTTP](/reference/api/admin/zitadel.admin.v1.AdminService.AddEmailProviderHTTP) to create a new HTTP provider that can be used to send Email messages:
@@ -169,11 +169,11 @@ Topics of the onboarding term may include
- Migration
- Security Best Practices & Go-Live Checkup
<Tabs>
<Tab value="in" label="Topics in scope">
<Tabs groupId="covered-topics" defaultIndex={1} items={['Topics in scope', 'Topics out of scope']}>
<Tab value="Topics in scope">
<ul>
<li>Instance Settings</li>
<li>Walk-though all features</li>
<li>Walk-through all features</li>
<li>Users / Manuals</li>
<li>Authentication & Management APIs</li>
<li>Validation of tokens</li>
@@ -189,7 +189,7 @@ Topics of the onboarding term may include
<li>Functional testing of the ZITADEL instance</li>
</ul>
</Tab>
<Tab value="out" label="Topics out of scope" default>
<Tab value="Topics out of scope">
<ul>
<li>Performance testing</li>
<li>Setting up or maintaining backup storage</li>