docs: Update writing documentation for starlight help center.

The help center documentation now uses astro/starlight, so the
contributor documentation is updated here for the general changes
to that documentation, such as where to find files, and features
and components used in that documentation.

Moves features that are still used for integrations and API docs,
to those guides, e.g., tabbed sections and our macros system, so
that we still have documentation for those systems/features.

Co-authored-by: Shubham Padia <shubham@zulip.com>
This commit is contained in:
Lauryn Menard
2025-09-05 18:07:31 +02:00
committed by Tim Abbott
parent 310a2323b6
commit 69f5aa787d
4 changed files with 411 additions and 148 deletions

View File

@@ -30,7 +30,7 @@ Our API documentation is defined by a few sets of files:
[OpenAPI description](openapi.md) at
`zerver/openapi/zulip.yaml`.
- The documentation is written the same Markdown framework that powers
our [help center docs](helpcenter.md), with some special
our [integration docs](integrations.md), with some special
extensions for rendering nice code blocks and example
responses. Most API endpoints share a common template,
`api_docs/api-doc-template.md`, which renders the
@@ -356,6 +356,52 @@ above.
all links! Unmerged changelog entries are conveniently previewed on
`/api/changelog`.
## Redirecting an existing article
From time to time, we might want to rename an article in the REST API
documentation. This change will break incoming links, including links
in published Zulip blog posts, links in other branches of the
repository that haven't been rebased, and more importantly links from
previous versions of Zulip.
To fix these broken links, you can easily add a URL redirect in:
`zerver/lib/url_redirects.py`.
For REST API documentation, you will either need to rename the file,
or you will need to update the endpoint's `operationId` in
`zerver/openapi/zulip.yaml`. Then, you need to add a new `URLRedirect`
to the `API_DOCUMENTATION_REDIRECTS` list in `url_redirects.py`:
```python
API_DOCUMENTATION_REDIRECTS: List[URLRedirect] = [
# Add URL redirects for REST API documentation here:
URLRedirect("/api/delete-stream", "/api/archive-stream"),
...
```
You should still check for references to the old URL in your branch
and replace those with the new URL (e.g., `git grep "/api/foo"`).
One exception to this are links with the old URL that were included
in the content of `zulip_update_announcements`, which can be found
in `zerver/lib/zulip_update_announcements.py`. It's preferable to
have the source code accurately reflect what was sent to users in
those [Zulip update announcements][zulip-updates], so these should
not be replaced with the new URL.
If you have the Zulip development environment set up, you can manually
test your changes by loading the old URL in your browser (e.g.,
`http://localhost:9991/api/foo`), and confirming that it redirects to
the new url (e.g., `http://localhost:9991/api`/bar`).
There is also an automated test in `zerver/tests/test_urls.py` that
checks all the URL redirects, which you can run from the command line:
```console
./tools/test-backend zerver.tests.test_urls.URLRedirectTest
```
[zulip-updates]: https://zulip.com/help/configure-automated-notices#zulip-update-announcements
## Why a custom system?
Given that our documentation is written in large part using the

View File

@@ -7,7 +7,7 @@ as setting up an organization.
There are two types of help center documents: articles about specific features,
and a handful of longer guides. The feature articles serve a few different purposes:
- Feature discovery, for someone browsing the `/help/` page, and looking at
- Feature discovery, for someone browsing the help center, and looking at
the set of articles and guides.
- Public documentation of our feature set, for someone googling "can zulip do ..."
@@ -18,6 +18,14 @@ and a handful of longer guides. The feature articles serve a few different purpo
- Feature explanations for new Zulip users and admins, especially for
organization settings.
The help center is built with [@astro/starlight](https://starlight.astro.build/).
Starlight is a full-featured documentation theme built on top of the
[Astro](https://astro.build/) framework. Astro is a web framework designed
for content driven websites. The content for the help center articles are
[MDX](https://mdxjs.com/) files, which live at `starlight_help/src/content/docs`
in the [main Zulip server repository](https://github.com/zulip/zulip).
Images are usually linked from `static/images/help/`.
Zulip help center documentation is available under `/help/` on any Zulip server;
(e.g., <https://zulip.com/help/> or `http://localhost:9991/help/` in
the Zulip development environment). The help center documentation is not hosted
@@ -25,19 +33,12 @@ on ReadTheDocs, since Zulip supports running a server completely disconnected
from the Internet, and we'd like the documentation to be available in that
environment.
The source for help center documentation is the Markdown files under
`help/` in the [main Zulip server repository](https://github.com/zulip/zulip).
The file `foo.md` is automatically rendered by the `render_markdown_path`
function in `zerver/templatetags/app_filters.py` when the user accesses a URL
of the form `/help/foo`; with special cases for `/help/` going to `index.md`
and `/help/unknown_article` going to `missing.md` (with a 404 response).
Images are usually linked from `static/images/help/`.
This means that you can contribute to the Zulip help center documentation
by just adding to or editing the collection of Markdown files under
`help/...`. If you have the Zulip development environment set up, you simply
need to reload your browser on `http://localhost:9991/help/foo` to see the
latest version of `foo.md` rendered.
by just adding to or editing the collection of MDX files under
`starlight_help/src/content/docs`. If you have the Zulip development
environment set up, you simply need to reload your browser on
`http://localhost:9991/help/foo` to see the latest version of `foo.mdx`
rendered.
This system is designed to make writing and maintaining such documentation
highly efficient. We link to the docs extensively from the landing pages and
@@ -54,21 +55,20 @@ There are over 100 feature articles and longer guides in the
[Zulip help center](https://zulip.com/help/), so make the most of
the current documentation as a resource and guide as you begin.
- Use the list on [Zulip help center home](https://zulip.com/help/)
to find the section of the docs (e.g., Preferences, Sending
messages, Reading messages, etc.) that relates to the new feature
you're documenting.
- Use the left sidebar in the help center documentation to find the
section of the docs (e.g., Preferences, Sending messages, Reading
messages, etc.) that relates to the new feature you're documenting.
- Read through the existing articles in that section and pay attention
to the [writing style](#writing-style) used, as well as any
[Markdown features](#markdown-features) used to enhance the
readability of the documentation.
[features and components](#mdx-features-and-custom-zulip-components)
used to enhance the readability of the documentation.
- Should the feature you're documenting be added or merged into an
existing article?
- If so, you can locate that article in `help/` and start working
on updating it with content about the new feature.
- If so, you can locate that article in `starlight_help/src/content/docs`
and start working on updating it with content about the new feature.
- If not, choose an existing article to use as a template for your
new article and make a list of which articles (or guides) would be
@@ -96,8 +96,9 @@ existing help center articles:
- Maintain the format and [writing style](#writing-style) of the
current article.
- Review the [Markdown features](#markdown-features) available and
pay attention to the ones already utilized in the article.
- Review the [features and components](#mdx-features-and-custom-zulip-components)
available and pay attention to the ones already utilized in the
article.
- Think about where inline links to other help center documentation
would be appropriate in the description of the feature. For example,
@@ -152,35 +153,36 @@ where the user will see it as they are interacting with the feature.
### Redirecting an existing article
From time to time, we might want to rename an article in the help
center, or REST API documentation. This change will break incoming
links, including links in published Zulip blog posts, links in other
branches of the repository that haven't been rebased, and more
importantly links from previous versions of Zulip.
center. This change will break incoming links, including links in
published Zulip blog posts, links in other branches of the repository
that haven't been rebased, and more importantly links from previous
versions of Zulip.
To fix these broken links, you can easily add a URL redirect in:
`zerver/lib/url_redirects.py`.
`starlight_help/astro.config.mjs`.
For help center documentation, once you've renamed the file in your
branch (e.g., `git mv path/to/foo.md path/to/bar.md`), go to
`url_redirects.py` and add a new `URLRedirect` to the
`HELP_DOCUMENTATION_REDIRECTS` list:
For help center article, once you've renamed the file in your
branch (e.g., `git mv path/to/foo.mdx path/to/bar.mdx`), go to
`astro.config.mjs` and add a new line to the `redirects` property:
```python
HELP_DOCUMENTATION_REDIRECTS: List[URLRedirect] = [
# Add URL redirects for help center documentation here:
URLRedirect("/help/foo", "/help/bar"),
```
// Redirects in astro are just directories with index.html inside
// them doing the redirect we define in the value. The base of
// /help/ will apply to the keys in the list below but we will
// have to prepend /help/ in the redirect URL.
redirects: {
"pm-mention-alert-notifications": "/help/dm-mention-alert-notifications",
...
```
Note that you will also need to add redirects when you're deleting
a help center article and adding its content to an existing article
as a section. In that case, the new URL will include the new section
header: `URLRedirect("/help/foo", "/help/bar#new-section-header"),`.
header:
For REST API documentation, you will either need to rename the file
as above, or you will need to update the endpoint's `operationId` in
`zerver/openapi/zulip.yaml`. Then, you would add a new `URLRedirect`
to the `API_DOCUMENTATION_REDIRECTS` list in `url_redirects.py`.
```
"add-an-alert-word": "/help/dm-mention-alert-notifications#alert-words"
```
You should still check for references to the old URL in your branch
and replace those with the new URL (e.g., `git grep "/help/foo"`).
@@ -200,13 +202,6 @@ test your changes by loading the old URL in your browser (e.g.,
`http://localhost:9991/help/foo`), and confirming that it redirects to
the new url (e.g., `http://localhost:9991/help/bar`).
There is also an automated test in `zerver/tests/test_urls.py` that
checks all the URL redirects, which you can run from the command line:
```console
./tools/test-backend zerver.tests.test_urls.URLRedirectTest
```
[help-zulip-updates]: https://zulip.com/help/configure-automated-notices#zulip-update-announcements
## Writing style
@@ -264,42 +259,16 @@ change `has_mac_keyboard` in `/web/src/common.ts` to always return `True`.
Then when you view your documentation changes in the development environment,
the keyboard shortcuts should be rendered with Mac keys where appropriate.
If you're adding a tip to an article about a keyboard shortcut, you
should use the more specific keyboard [tip macro](#tips-and-warnings),
`!!! keyboard_tip ""`. In general, all keyboard shortcuts should be
documented on the [keyboard
If you're adding a tip to an article about a keyboard shortcut, you should
use the more specific [keyboard tip](#asides) component. In general, all
keyboard shortcuts should be documented on the [keyboard
shortcuts](https://zulip.com/help/keyboard-shortcuts) help center
article.
## Markdown features
Zulip's Markdown processor allows you to include several special features in
your documentation to help improve its readability:
- Since raw HTML is supported in Markdown, you can include arbitrary
HTML/CSS in your documentation as needed.
- Code blocks allow you to highlight syntax, similar to
[Zulip's own Markdown](https://zulip.com/help/format-your-message-using-markdown).
- Anchor tags can be used to link to headers in other documents.
- [Images](#images) of Zulip UI can be added to documentation, if needed.
- Inline [icons](#icons) are used to refer to features in the Zulip UI.
- Utilize [macros](#macros) to limit repeated content in the documentation.
- Create special highlight warning blocks using
[tips and warnings](#tips-and-warnings).
- Format instructions with tabs using
[Markdown tab switcher](#tab-switcher).
### Images
Images and screenshots should be included in help center documentation
only if they will help guide the user in how to do something (e.g., if
_only_ if they will help guide the user in how to do something (e.g., if
the image will make it much clearer which element on the page the user
should interact with). For instance, an image of an element should
not be included if the element the user needs to interact with is the
@@ -315,104 +284,251 @@ Zulip browser window in a screenshot; instead, it should only show
relevant parts of the app. In addition, the screenshot should always
come _after_ the text that describes it, never before.
Images are often a part of a numbered step and must be indented four
spaces to be formatted correctly.
Images used in the help center can be found at `static/images/help`.
## MDX features and custom Zulip components
MDX supports standard markdown syntax. Some useful markdown features to
remember when writing help center documentation are:
- Since raw HTML is supported in Markdown, you can include arbitrary
HTML/CSS in your documentation as needed.
- Code blocks allow you to highlight syntax, similar to
[Zulip's own Markdown](https://zulip.com/help/format-your-message-using-markdown).
- Anchor tags can be used to link to headers in other documents.
Additionally, there are some useful MDX components implemented and used
throughout the help center documentation:
- [Icon](#icons) components allow documentation to use the exact icons
for a button or link that is used in the Zulip UI.
- [Include files](#include-files) allow us to reuse repeated content
in the documentation.
- Our custom [Aside](#asides) components create special highlighted
information and warning blocks for tips, keyboard shortcuts, and the
like.
- Instructions can be formatted with [Tab](#tabs),
[Steps/FlattenSteps](#steps-and-flattenedsteps) and
[NavigationSteps](#navigationsteps) components.
### Icons
See [icons documentation](../subsystems/icons.md). Icons should always be named
with their in-app tooltip or brief action name, _not_ the name of the icon in
the code.
See [icons documentation](../subsystems/icons.md). Icons should always be
referred to with their in-app tooltip or a brief action name, _not_ the
name of the icon in the code.
### Macros
When using these icons in an MDX file, they act as any other component:
**Macros** are elements in the format of `{!macro.md!}` that insert common
phrases and steps at the location of the macros. Macros help eliminate
repeated content in our documentation.
```
import SquarePlusIcon from "~icons/zulip-icon/square-plus"
The source for macros is the Markdown files under `help/include` in the
[main Zulip server repository](https://github.com/zulip/zulip).
Click the **new topic** (<SquarePlusIcon />) button next to the name of the channel.
```
- **Administrator only feature** `{!admin-only.md!}`: Notes that the feature
is only available to organization administrators.
For the import statement, the icon component should be named as the camel
case of the icon name, with any dashes removed, followed by `Icon`, e.g.,
in the example above `square-plus` is imported as `SquarePlusIcon`.
- **Message actions** `{!message-actions.md!}`: First step to navigating to
the on-hover message actions.
### Include files
- **Message actions menu** `{!message-actions-menu.md!}`: Navigate to the
message actions menu.
You can include any file inside another MDX file as a regular import, which
helps to eliminate repeated content in our documentation.
- **Save changes** `{!save-changes.md!}`: Save changes after modifying
organization settings.
All our include files live at `starlight_help/src/content/docs/include`,
and can be imported and used as a regular component:
- **Channel actions** `{!channel-actions.md!}`: Navigate to the channel actions
menu from the left sidebar.
```
import AdminOnly from "./include/_AdminOnly.mdx";
- **Start composing** `{!start-composing.md!}`: Open the compose box.
<AdminOnly />
```
### Tips and warnings
If you're adding a new include file, make sure to have an underscore at the
beginning of the file name as that ensures the file won't be considered a
standalone article in the help center.
A **tip** is any suggestion for the user that is not part of the main set of
instructions. For instance, it may address a common problem users may
A lot of our include files are list macros, i.e., they are partial lists
that are part of bigger lists. When the partial list is an ordered list,
it needs to be wrapped in a [FlattenedSteps](#steps-and-flattenedsteps)
component.
We recommend avoiding having any h2 or h3 headers (`##`, `###`) in an
include file because, when the file is imported into a help center article,
those headings will not be rendered in the "On this page" outline in the
right sidebar.
If it is necessary to have headers in the include file content, then the
work around for having them rendered in the right sidebar is to insert the
same headers into any file where you are importing and using that include
file. In example below, we add the two h3 headers from the include file so
that they are rendered in the right sidebar:
```
import AutomaticallyFollowTopics from "./include/_AutomaticallyFollowTopics.mdx";
<AutomaticallyFollowTopics>
### Follow topics you start or participate in
### Follow topics where you are mentioned
</AutomaticallyFollowTopics>
```
### Asides
We have customized aside components that are used for tips, warnings and
keyboard tips in the help center.
A **tip** is any suggestion for the user that is not part of the main set
of instructions. For instance, it may address a common problem users may
encounter while following the instructions, or point to an option for power
users.
```md
!!! tip ""
```
import ZulipTip from "../../components/ZulipTip.astro";
If you've forgotten your password, see the
[Change your password](/help/change-your-password) page for
instructions on how to reset it.
<ZulipTip>
The app will update automatically to future versions.
</ZulipTip>
```
A **keyboard tip** is a note for users to let them know that the same action
can also be accomplished via a [keyboard shortcut](#keyboard-shortcuts).
```md
!!! keyboard_tip ""
```
import KeyboardTip from "../../components/KeyboardTip.astro";
Use <kbd>D</kbd> to bring up your list of drafts.
<KeyboardTip>
You can also use <kbd>?</kbd> to open the keyboard shortcuts reference.
</KeyboardTip>
```
A **warning** is a note on what happens when there is some kind of problem.
Tips are more common than warnings.
```md
!!! warn ""
```
import ZulipNote from "../../../components/ZulipNote.astro";
**Note:** If you attempt to input a nonexistent channel name, an error
message will appear.
<ZulipNote>
This feature is only available to organization owners and administrators.
</ZulipNote>
```
All tips/warnings should appear inside tip/warning blocks. There
should be only one tip/warning inside each block, and they usually
should be formatted as a continuation of a numbered step.
There should be only one tip/warning inside each component. They usually
should be formatted as a continuation of a numbered step, if they are in
an ordered list.
### Tab switcher
You can find the code for these custom aside components at
`starlight_help/src/components`.
Our Markdown processor supports easily creating a tab switcher widget
design to easily show the instructions for different
[platforms](https://zulip.com/help/logging-out) in help center articles,
languages in API docs, etc. To create a tab switcher, write:
### Tabs
```md
{start_tabs}
{tab|desktop-web}
# First tab's content
{tab|ios}
# Second tab's content
{tab|android}
# Third tab's content
{end_tabs}
There are built-in [starlight/astro `Tab` and `TabItem`
components](https://starlight.astro.build/components/tabs/) for creating
tabbed instructions:
```
import {Steps, TabItem, Tabs} from "@astrojs/starlight/components";
import FlattenedSteps from "../../components/FlattenedSteps.astro";
import MobileSwitchAccount from "./include/_MobileSwitchAccount.mdx";
<Tabs>
<TabItem label="Mobile">
<FlattenedSteps>
<MobileSwitchAccount />
1. Tap **Add new account**.
1. Enter the Zulip URL of the organization, and tap **Continue**.
1. Follow the on-screen instructions.
</FlattenedSteps>
</TabItem>
<TabItem label="Web">
<Steps>
1. Go to the Zulip URL of the organization.
1. Follow the on-screen instructions.
</Steps>
</TabItem>
</Tabs>
```
The tab identifiers (e.g., `desktop-web` above) and their mappings to
the tabs' labels are declared in
[zerver/lib/markdown/tabbed_sections.py][tabbed-sections-code].
The above example has instructions for logging in for the mobile app
and the web app. Make sure you add a label for each `TabItem`.
[tabbed-sections-code]: https://github.com/zulip/zulip/blob/main/zerver/lib/markdown/tabbed_sections.py
#### Steps and FlattenedSteps
This widget can also be used just to create a nice box around a set of
instructions
([example](https://zulip.com/help/deactivate-your-account)) by
only declaring a single tab.
If you don't need multiple tabs, or a tabbed label, for your instructions,
then you can just wrap the ordered list of instructions in a [`Steps`
component](https://starlight.astro.build/components/steps/):
```
import {Steps} from "@astrojs/starlight/components";
<Steps>
1. Go to the Zulip URL of the organization.
1. Follow the on-screen instructions.
</Steps>
```
If you have an ordered list of instructions with a portion of the list in
an [include file](#include-files), then you need to wrap the instructions
in a `FlattenedSteps` component, so that the instructions are numbered
correctly when rendered (e.g., `1.`, `2.`, `3.`, `4.`, etc.):
```
import FlattenedSteps from "../../components/FlattenedSteps.astro";
import MobileSwitchAccount from "./include/_MobileSwitchAccount.mdx";
<FlattenedSteps>
<MobileSwitchAccount />
1. Tap **Add new account**.
1. Enter the Zulip URL of the organization, and tap **Continue**.
1. Follow the on-screen instructions.
</FlattenedSteps>
```
#### NavigationSteps
Many instructions begin with the same set of steps, some of which can have
relative links that directly go to the logged in session for the Zulip
organization of the user reading the documentation. For these partial
instruction lists, we use a custom `NavigationSteps` component, which needs
to be wrapped in a `FlattenedSteps` component ([see above](#steps-and-flattenedsteps)).
```
import NavigationSteps from "../../components/NavigationSteps.astro";
<FlattenedSteps>
<NavigationSteps target="settings/organization-permissions" />
1. Under **Joining the organization**, toggle **Invitations are required for
joining this organization**.
<SaveChanges />
</FlattenedSteps>
```
Each `NavigationStep` has a `target`, which can be one of two forms:
- Settings: `settings/{setting_key}`
- Relative: `relative/{link_type}/{key}`
The settings targets are for instructions that navigate to a section in
either the personal or organization settings overlay in the web app.
The relative targets are for instructions that navigate from the gear or
help menus to a particular location in the web app.
See `starlight_help/src/components/NavigationSteps.astro` for what values
for settings and relative targets are currently implemented.
You can find the code for any custom components used in the help center at:
`starlight_help/src/components`.

View File

@@ -253,3 +253,99 @@ to find. A few things to keep in mind:
the text is referring to that is difficult to locate.
- Screenshots should never include the entirety of a third-party websites page.
- Each screenshot should come after the step that refers to it.
## Markdown features
Zulip's Markdown processor allows you to include several special features in
your documentation to help improve its readability:
- Since raw HTML is supported in Markdown, you can include arbitrary
HTML/CSS in your documentation as needed.
- Code blocks allow you to highlight syntax, similar to
[Zulip's own Markdown](https://zulip.com/help/format-your-message-using-markdown).
- Anchor tags can be used to link to headers in other documents.
- Inline [icons](#icons) are used to refer to features in the Zulip UI.
- Utilize [macros](#markdown-macros) to limit repeated content in the documentation.
- Create special highlight warning blocks using
[tips and warnings](#tips-and-warnings).
- Format instructions with tabs using
[Markdown tab switcher](#tab-switcher).
### Icons
See [icons documentation](../subsystems/icons.md). Icons should always be
referred to with their in-app tooltip or a brief action name, _not_ the
name of the icon in the code.
### Tips and warnings
A **tip** is any suggestion for the user that is not part of the main set of
instructions. For instance, it may address a common problem users may
encounter while following the instructions, or point to an option for power
users.
```md
!!! tip ""
If you want notifications for issues, as well as events, you can
scroll down to **Webhooks** on the same page, and toggle the
**issue** checkbox.
```
A **keyboard tip** is a note for users to let them know that the same action
can also be accomplished via a [keyboard shortcut](https://zulip.com/help/keyboard-shortcuts).
```md
!!! keyboard_tip ""
Use <kbd>D</kbd> to bring up your list of drafts.
```
A **warning** is a note on what happens when there is some kind of problem.
Tips are more common than warnings.
```md
!!! warn ""
**Note**: Zulip also supports configuring this integration as a
webhook in Sentry.
```
All tips/warnings should appear inside tip/warning blocks. There
should be only one tip/warning inside each block, and they usually
should be formatted as a continuation of a numbered step.
### Tab switcher
Our Markdown processor supports easily creating a tab switcher widget
design to easily show the instructions for different languages in API
docs, etc. To create a tab switcher, write:
```md
{start_tabs}
{tab|python}
# First tab's content
{tab|js}
# Second tab's content
{tab|curl}
# Third tab's content
{end_tabs}
```
The tab identifiers (e.g., `python` above) and their mappings to
the tabs' labels are declared in
[zerver/lib/markdown/tabbed_sections.py][tabbed-sections-code].
This widget can also be used just to create a nice box around a set of
instructions
([example](https://zulip.com/help/deactivate-your-account)) by
only declaring a single tab, which is often used for the main set of
instructions for setting up an integration.
[tabbed-sections-code]: https://github.com/zulip/zulip/blob/main/zerver/lib/markdown/tabbed_sections.py

View File

@@ -12,11 +12,11 @@ Zulip has three major documentation systems:
might look at when deciding whether to use Zulip. We don't expect
to ever have more than about 10 pages written using this system.
- **User-facing documentation**: Our scalable system for documenting
Zulip's huge collection of specific features without a lot of
overhead or duplicated code/syntax, written in Markdown. We have
several hundred pages written using this system. There are 3
branches of this documentation:
- **User-facing documentation**: Zulip uses a scalable system for
documenting Zulip's integrations and REST API, without a lot of
overhead or duplicated code/syntax, written in Markdown. Zulip's
help center uses [@astro/starlight](https://starlight.astro.build/),
with most of the content written in MDX.
- [Help center documentation](#help-center-documentation)
(with a target audience of individual Zulip users)
- [Integrations documentation](#integrations-documentation)
@@ -90,11 +90,16 @@ important elements of the product clearly.
## User-facing documentation
All of these systems use a common Markdown-based framework with
various extensions for macros and variable interpolation,
Zulip's API and integrations documentation use a common Markdown-based
framework with various extensions for macros and variable interpolation,
(`render_markdown_path` in the code), designed to make it convenient
to do the things one does a lot in each type of documentation.
Zulip's help center is built with [@astro/starlight](https://starlight.astro.build/).
Starlight is a full-featured documentation theme built on top of the
[Astro](https://astro.build/) framework. Astro is a web framework designed
for content driven websites.
### Help center documentation
Zulip's [help center](https://zulip.com/help/) documentation is