Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
a0f8f81
update all dependencies
bryantgillespie Apr 23, 2026
693035f
add packageManager back
bryantgillespie Apr 23, 2026
40b762b
remove hardcoded url
bryantgillespie Apr 23, 2026
12e54f4
wip
bryantgillespie Apr 26, 2026
fb43401
cleanup from review
bryantgillespie Apr 26, 2026
2e61cb1
cleanup again
bryantgillespie Apr 27, 2026
1c08e8b
switch to json for storing redirects
bryantgillespie Apr 27, 2026
f785c96
convert to ts
bryantgillespie Apr 28, 2026
23d0e7f
cleanup
bryantgillespie Apr 28, 2026
94d9c40
ai cleanup
bryantgillespie Apr 28, 2026
c8949ec
Update README.md
bryantgillespie Apr 28, 2026
4e55dfb
backfill all ids
bryantgillespie Apr 28, 2026
0c01c40
feat(nav): rename Connect→APIs, Automate→Flows, Manage→Hosting
bryantgillespie Apr 28, 2026
fb26a69
feat(llms): rename guide section titles to APIs and Flows
bryantgillespie Apr 28, 2026
853c5b3
docs: replace branded "Directus Connect"/"Directus Automate" with API…
bryantgillespie Apr 28, 2026
5411aef
docs(homepage): drop Data Engine/Data Studio framing
bryantgillespie Apr 28, 2026
0548d61
fix: fold 11.integrations into 12.integrations to clear numeric colli…
bryantgillespie Apr 28, 2026
8d9a727
fix sidebar
bryantgillespie Apr 28, 2026
e1a7980
docs(nav): rename Guides→Guide, Hosting→Deploy
bryantgillespie Apr 28, 2026
2064fcb
kill editor and explorer
bryantgillespie Apr 28, 2026
d6971b0
initial moves
bryantgillespie Apr 30, 2026
bf3949e
wippity
bryantgillespie Apr 30, 2026
13fa1e4
cleanup
bryantgillespie Apr 30, 2026
5d04c17
fix nav
bryantgillespie Apr 30, 2026
8e6cdb2
extract findNavNode
bryantgillespie Apr 30, 2026
1b1f78c
vanilla to vanilla js
bryantgillespie Apr 30, 2026
91eec5c
fix claude bs
bryantgillespie Apr 30, 2026
3039cb3
oops technologies is needed for the imaages
bryantgillespie Apr 30, 2026
45877f7
add chips to tutorials with framworks
bryantgillespie Apr 30, 2026
997dbc8
more cleanup
bryantgillespie Apr 30, 2026
1c32969
All Frameworks
bryantgillespie Apr 30, 2026
7e35e8e
feat(layout): redesign docs experience
bryantgillespie May 21, 2026
459d1ad
feat(layout): add prompt and shader debug components
bryantgillespie May 21, 2026
62c0b4e
fix(layout): restore reference content and skip API prerender
bryantgillespie May 22, 2026
747cfe3
fix(build): stop masking prerender errors
bryantgillespie May 22, 2026
e7e1665
feat(layout): use Directus docs typography
bryantgillespie May 22, 2026
8c19d67
fix(build): inline unhead for preview
bryantgillespie May 22, 2026
79aea9c
chore(layout): remove unused legacy helpers
bryantgillespie May 22, 2026
e17931d
Clean up docs navigation and icons
bryantgillespie May 22, 2026
56ee43f
fix layous
bryantgillespie May 22, 2026
0697c99
Update Railway tutorial image
bryantgillespie May 23, 2026
30b9c2c
Merge origin/main
bryantgillespie May 23, 2026
90cffc0
Skip base-prefixed API prerender
bryantgillespie May 23, 2026
cb79938
fix(build): lazy-load OAS spec to reduce prerender memory
bryantgillespie May 23, 2026
510ac87
increase concurrency
bryantgillespie May 23, 2026
45bbfb2
fix icon
bryantgillespie May 23, 2026
88890e0
feat(hero): painterly Kuwahara shader with fade-up painting layer
bryantgillespie May 26, 2026
e4ec734
Fix suggestions
LZylstra May 28, 2026
dd67526
Docs Updates #6 - Add Typesense docs search (#685)
bryantgillespie May 29, 2026
ca58772
Docs Updates #7 - MCP Server (#686)
bryantgillespie May 29, 2026
c7cbe38
Merge origin/main
bryantgillespie May 29, 2026
47a89b9
Fix pnpm setup in search workflow
bryantgillespie May 29, 2026
013c54f
Reduce prerender concurrency
bryantgillespie May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
ALGOLIA_API_KEY=algolia_api_key
ALGOLIA_APPLICATION_ID=algolia_application_id
TYPESENSE_URL=https://your-cluster.a1.typesense.net
TYPESENSE_PUBLIC_API_KEY=your_search_only_api_key
TYPESENSE_PRIVATE_API_KEY=typesense_private_api_key_required_for_indexing_only
# Optional. Overrides the branch-derived read alias.
# TYPESENSE_COLLECTION=directus-docs
DIRECTUS_URL=https://marketing-directus-url.com
GOOGLE_TAG_MANAGER_ID=GTM-PTLT3GH
POSTHOG_API_HOST=https://directus.io/ingest
POSTHOG_API_KEY=phc_secret_key_here
NUXT_PUBLIC_SITE_URL=https://directus.io
# Optional. Fine-grained PAT, public repos read-only. Required for code search and raises GitHub raw rate limits.
# GITHUB_TOKEN=github_pat_...
76 changes: 76 additions & 0 deletions .github/workflows/search-index.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Search Index

on:
push:
branches:
- main
paths: &index-paths
- 'content/**'
- 'scripts/index-docs.ts'
- 'scripts/index-docs-chunker.ts'
- 'shared/utils/parseTypesenseUrl.ts'
- 'shared/utils/docsSections.ts'
- 'app/utils/slugify.ts'
- 'server/data/synonyms.ts'
- 'lib/typesenseAlias.ts'
- 'pnpm-lock.yaml'
- '.github/workflows/search-index.yml'
pull_request:
branches:
- main
paths: *index-paths
workflow_dispatch:

concurrency:
group: search-index-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: read

jobs:
preview-index:
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
env:
TYPESENSE_URL: ${{ secrets.TYPESENSE_URL }}
TYPESENSE_PUBLIC_API_KEY: ${{ secrets.TYPESENSE_PUBLIC_API_KEY }}
TYPESENSE_PRIVATE_API_KEY: ${{ secrets.TYPESENSE_PRIVATE_API_KEY }}
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Index preview collection
run: pnpm index:docs

prod-index:
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
env:
TYPESENSE_URL: ${{ secrets.TYPESENSE_URL }}
TYPESENSE_PUBLIC_API_KEY: ${{ secrets.TYPESENSE_PUBLIC_API_KEY }}
TYPESENSE_PRIVATE_API_KEY: ${{ secrets.TYPESENSE_PRIVATE_API_KEY }}
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Index production collection
run: pnpm index:docs
1 change: 1 addition & 0 deletions .nuxtrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
setups.@nuxt/test-utils="4.0.3"
43 changes: 40 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,14 @@ pnpm build

### Repository Tooling

The repository includes scripts that keep docs routes stable when files move.
The repository includes scripts that keep docs routes stable when files move and that index the docs into Typesense.

```bash
pnpm stable-ids:ensure # Add missing stableId frontmatter
pnpm stable-ids:check # Validate stableId frontmatter
pnpm redirects:sync # Update redirects.json for moved pages
pnpm redirects:check # Check redirect coverage without writing files
pnpm index:docs # Build the search index in Typesense
pnpm typecheck:scripts # Type check repository scripts
```

Expand Down Expand Up @@ -109,9 +110,45 @@ The documentation automatically deploys to Vercel when changes are merged into t
- [GitHub Issues](https://github.com/directus/docs/issues) (Report Bugs)
- [Roadmap](https://roadmap.directus.io) (Roadmap & Feature Requests)

## Making changes to Algolia Search
## 🔍 Search

The docs make use of the Algolia Crawler to index the content. The crawler is found at the bottom left in the Algolia dashboard under `Data Sources > Crawler > directus`. To make changes on how the crawler works, go to the `Editor` tab and make your changes. By default the crawler runs once a day but you can also manually run it. In order to tweak the ranking of search results, go to the `Search > Configure > Index > Configuration > Ranking and Sorting` tab.
Search is powered by [Typesense](https://typesense.org). The browser palette (`UCommandPalette`-based) lives at `app/components/DocsSearchPalette.vue` and queries Typesense directly via `app/services/typesenseService.ts`. The official `typesense` npm client is used by the indexer only.

### Indexing

The indexer at `scripts/index-docs.ts` walks `/content`, chunks each Markdown page, attaches synonyms, and pushes everything to Typesense. OpenAPI indexing is deferred to a later branch. Run it locally with:

```bash
pnpm index:docs
```

CI runs the same command on every push to `main` (production index) and on every PR commit (per-branch preview index). See `.github/workflows/search-index.yml`.

### Collection naming

Indexes use a blue/green slot pattern with a stable alias:

- `main` -> alias `directus-docs`, slots `directus-docs-a` / `directus-docs-b`
- Branch `bry/foo` -> alias `directus-docs-preview-bry-foo`, slots `...-a` / `...-b`
- Local branch runs use the same branch-derived alias as CI

Each indexer run writes to whichever slot the alias is not currently pointing at, swaps the alias, then deletes the previous slot.

For one-off writes, override the index target with `TYPESENSE_INDEX_TARGET=...`.

The browser reads from `TYPESENSE_COLLECTION` when set. Otherwise it derives the same branch alias as the indexer. The app reads the alias, never the `-a` / `-b` slot name.

### Ranking

Section boosts and personalization live in `buildPersonalizedSortBy` in `app/composables/useDocsSearch.ts`. The same `sectionPriority` array drives both the Typesense `_eval` boost order and the chip-bar render order in the palette.

### Synonyms

Search synonyms live in `server/data/synonyms.ts` and are pushed to Typesense on every indexer run. Two formats: `multiway` (equivalent terms) and `oneway` (directional shorthand -> canonical, e.g. `db -> database`). Header comment in the file explains both.

### Search-friendly content

Write H2s and first paragraphs so they work as standalone search results.

<br />

Expand Down
66 changes: 54 additions & 12 deletions app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,69 @@
export default defineAppConfig({
search: {
backend: 'algolia',
backend: 'typesense',
},

ui: {
colors: {
primary: 'purple',
secondary: 'pink',
neutral: 'slate',
neutral: 'neutral',
},

button: {
slots: {
base: 'rounded-l-full rounded-r-full',
},
},

container: {
base: '@max-[40rem]/docs-pane:px-4! @min-[40rem]/docs-pane:px-6! @min-[64rem]/docs-pane:px-8!',
},
header: {
slots: {
left: '@max-[40rem]/docs-pane:flex-none! @min-[40rem]/docs-pane:flex-1!',
center: '@max-[40rem]/docs-pane:hidden! @min-[40rem]/docs-pane:flex!',
right: '@max-[40rem]/docs-pane:flex-none! @min-[40rem]/docs-pane:flex-1!',
toggle: '@max-[40rem]/docs-pane:flex! @min-[40rem]/docs-pane:hidden!',
content: '@max-[40rem]/docs-pane:block! @min-[40rem]/docs-pane:hidden!',
overlay: '@max-[40rem]/docs-pane:block! @min-[40rem]/docs-pane:hidden!',
},
},
contentToc: {
slots: {
bottom: '@max-[64rem]/docs-pane:hidden! @min-[64rem]/docs-pane:flex!',
},
},
content: {
callout: {
// Fix background color of pre > code blocks
wrapper: '[&_pre>code]:!bg-transparent',
},
},
page: {
contentSurround: {
slots: {
root: 'flex flex-col-reverse sm:grid sm:grid-cols-2 gap-8',
},
},
pageHeader: {
slots: {
root: 'lg:gap-8',
wrapper: '@max-[40rem]/docs-pane:flex-col! @max-[40rem]/docs-pane:items-stretch! @max-[40rem]/docs-pane:justify-start! @min-[40rem]/docs-pane:flex-row! @min-[40rem]/docs-pane:items-center! @min-[40rem]/docs-pane:justify-between!',
title: 'text-3xl sm:text-4xl text-pretty font-display font-medium text-highlighted',
},
},
prose: {
h1: {
base: 'font-display font-medium',
},
h2: {
base: 'font-display font-medium',
},
h3: {
base: 'font-display font-medium',
},
h4: {
base: 'font-display font-medium',
},
pre: {
slots: {
base: 'text-xs/4',
Expand Down Expand Up @@ -92,7 +134,7 @@ export default defineAppConfig({
{
label: 'Security',
to: '/guides/security/best-practices',
icon: 'i-ph-shield-check',
icon: 'material-symbols:verified-user-outline',
},
{
label: 'AI',
Expand All @@ -112,17 +154,17 @@ export default defineAppConfig({
{
label: 'Cloud',
to: '/cloud/getting-started/introduction',
icon: 'i-ph-cloud',
icon: 'material-symbols:cloud-outline',
},
{
label: 'Self-Hosting',
to: '/self-hosting/overview',
icon: 'i-ph-hard-drives',
icon: 'material-symbols:dns-outline',
},
{
label: 'Configuration',
to: '/configuration/intro',
icon: 'i-ph-gear',
icon: 'material-symbols:settings-outline',
},
],
},
Expand All @@ -132,22 +174,22 @@ export default defineAppConfig({
{
label: 'Frameworks',
to: '/frameworks',
icon: 'i-ph-brackets-curly',
icon: 'material-symbols:data-object',
},
{
label: 'Tutorials',
to: '/tutorials',
icon: 'i-ph-article',
icon: 'material-symbols:article-outline',
},
{
label: 'Community',
to: '/community/overview/welcome',
icon: 'i-ph-hand-heart',
icon: 'material-symbols:volunteer-activism-outline',
},
{
label: 'Releases',
to: '/releases',
icon: 'i-ph-notebook',
icon: 'material-symbols:menu-book-outline',
},
],
},
Expand Down
18 changes: 7 additions & 11 deletions app/app.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<script setup lang="ts">
import type { ContentNavigationItem } from '@nuxt/content';
import { spec } from '@directus/openapi';

const { data: navigation } = useAsyncData('content-navigation', () => queryCollectionNavigation('content', ['title', 'description', 'icon', 'links']));
const { data: navigation } = await useAsyncData('content-navigation', () => queryCollectionNavigation('content', ['title', 'description', 'icon', 'links']));

provide('openapi', spec);
provide('navigation', navigation as Ref<ContentNavigationItem[]>);

defineOgImage('Default', {
Expand All @@ -15,13 +13,11 @@ defineOgImage('Default', {
<template>
<UApp>
<NuxtLoadingIndicator color="var(--color-primary)" />
<DocsBanner />
<DocsHeader />
<UMain>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</UMain>
<DocsFooter />
<div
id="docs-scroll"
class="h-screen min-w-0 overflow-y-auto overflow-x-hidden scroll-smooth"
>
<DocsShell />
</div>
</UApp>
</template>
30 changes: 0 additions & 30 deletions app/assets/css/algolia.css

This file was deleted.

Loading
Loading