Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
11111da
chore: expand gitignore and local preview tooling
ngarakapati Aug 19, 2026
9b81190
feat: add LLM markdown export and dual playbook build setup
ngarakapati Aug 19, 2026
e824d7e
docs(savanna): restructure navigation and refresh Savanna documentation
ngarakapati Aug 19, 2026
8393c91
docs(cloud): update Cloud Classic pages and replace broken cross-comp…
ngarakapati Aug 19, 2026
03da867
fix: include workgroup screenshots and latest cloud cross-reference u…
ngarakapati Aug 19, 2026
d3a1466
docs(savanna): add database secret walkthrough video
ngarakapati Aug 19, 2026
11324a0
docs(savanna): let database secret video use full content width
ngarakapati Aug 19, 2026
cbd0db2
build: point UI bundle at cloud-only ui-bundle-cloud.zip
ngarakapati Aug 19, 2026
73da191
ci: retrigger build/Netlify now that ui-bundle-cloud.zip is on antora…
ngarakapati Aug 19, 2026
f9660cf
docs(savanna): rework database secrets page for clarity
ngarakapati Aug 20, 2026
20e5dd1
fix(cloud): restore external links for cross-component xrefs
ngarakapati Aug 26, 2026
b9c8661
docs(savanna): add Aug 19 changelog entries from origin/main
ngarakapati Aug 26, 2026
b557011
docs(savanna): group Aug 19 workspace fixes under Bug fixes
ngarakapati Aug 26, 2026
8d58756
docs(savanna): keep live release-notes URL and alias changelog
ngarakapati Aug 26, 2026
78fde3b
docs(savanna): make changelog the public URL
ngarakapati Aug 26, 2026
01fe239
docs(savanna): use Release Notes for the page name, nav, and URL
ngarakapati Aug 26, 2026
54c297d
docs: keep the site title as Docs
ngarakapati Aug 26, 2026
1dd7db7
chore: keep the local Antora playbook out of the PR
ngarakapati Aug 26, 2026
51f501b
build: stop generating a Savanna-only /llms.txt
ngarakapati Aug 26, 2026
9526684
fix: map drop-style page URLs when publishing markdown twins
ngarakapati Aug 26, 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
31 changes: 28 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,29 @@
.idea/
# Dependencies
node_modules/

# Antora build output and cache
build/
.cache/
antora.log

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Lockfile — yarn.lock is the committed source of truth
package-lock.json

# Local-only Antora playbook (sibling antora-ui path)
antora-playbook.local.yml

# OS
.DS_Store
node_modules
build
Thumbs.db

# Editors / IDEs
.idea/
.vscode/
*.swp
*~
17 changes: 14 additions & 3 deletions antora-playbook.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
site:
title: "Cloud Doc Test"
start_page: "savanna:overview:index.adoc"
title: Docs
url: https://www.tigergraph.com/docs
start_page: savanna:overview:index.adoc

content:
sources:
- url: .
branches: HEAD
start_paths: [modules/savanna, modules/cloud]

antora:
extensions:
- ./lib/markdown-for-llm.js
# ./lib/llms-txt.js is kept in the repo for a later site-wide /llms.txt. Do not
# enable it here: this playbook only builds Savanna and Cloud Classic.

asciidoc:
extensions:
- '@asciidoctor/tabs'

output:
dir: ./build/site

ui:
bundle:
url: https://github.com/tigergraph/antora-ui/blob/main/build/ui-bundle.zip?raw=true
snapshot: true
snapshot: true
4 changes: 2 additions & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const { reload: livereload } = process.env.LIVERELOAD === 'true' ? require('gulp
const { series, src, watch } = require('gulp')
const yaml = require('js-yaml')

const playbookFilename = 'antora-playbook.yml'
const playbookFilename = process.env.PLAYBOOK || 'antora-playbook.yml'
const playbook = yaml.load(fs.readFileSync(playbookFilename, 'utf8'))
const outputDir = (playbook.output || {}).dir || './build/site'
const serverConfig = { name: 'Preview Site', livereload, port: 5000, root: outputDir }
const serverConfig = { name: 'Preview Site', livereload, port: Number(process.env.PORT) || 5000, root: outputDir }
const antoraArgs = ['--playbook', playbookFilename]
const watchPatterns = playbook.content.sources.filter((source) => !source.url.includes(':')).reduce((accum, source) => {
accum.push(`${source.url}/${source.start_path ? source.start_path + '/' : ''}antora.yml`)
Expand Down
32 changes: 32 additions & 0 deletions lib/llm-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict'

/**
* Shared helpers for LLM-oriented Antora extensions.
*/

function stripTags (html) {
return String(html || '')
.replace(/<[^>]+>/g, '')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'")
.replace(/&nbsp;/g, ' ')
.replace(/\s+/g, ' ')
.trim()
}

function htmlToMdUrl (url) {
if (typeof url !== 'string') return url
const match = /^(.*?)([?#].*)?$/.exec(url)
const path = match[1]
const rest = match[2] || ''
if (/\.md$/i.test(path)) return url
if (/\.html$/i.test(path)) return path.replace(/\.html$/i, '.md') + rest
if (path.endsWith('/')) return path + 'index.md' + rest
if (!path) return url
return path + '.md' + rest
}

module.exports = { stripTags, htmlToMdUrl }
132 changes: 132 additions & 0 deletions lib/llms-txt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
'use strict'

/**
* Antora extension: generate /llms.txt from the site navigation model.
*
* Not registered in antora-playbook.yml. This playbook only builds Savanna and
* Cloud Classic; the live site-wide index is tigergraph.com/docs/llms.txt.
* Re-enable later when this can feed the full docs set (or a product subpath).
*
* Inspired by Couchbase's llms-txt.js, but adapted for this dual HTML+Markdown
* site: navigation links point at the generated `.md` twins rather than HTML,
* and we walk Antora's navigationCatalog directly (no separate nav-data JSON).
*
* Spec: https://llmstxt.org/
*/

const { htmlToMdUrl, stripTags } = require('./llm-utils')

function absoluteUrl (siteUrl, path) {
if (!path) return path
if (/^https?:\/\//i.test(path)) return htmlToMdUrl(path)
const base = (siteUrl || '').replace(/\/$/, '')
const rel = path.startsWith('/') ? path : `/${path}`
return htmlToMdUrl(base ? `${base}${rel}` : rel)
}

function navLabel (item) {
return stripTags(item.content) || stripTags(item.title) || 'Untitled'
}

function renderNavItems (items, siteUrl, lines, depth) {
if (!items || !items.length) return

for (const item of items) {
const label = navLabel(item)
const indent = ' '.repeat(depth)
const hasChildren = item.items && item.items.length

if (item.url && item.urlType !== 'fragment') {
lines.push(`${indent}- [${label}](${absoluteUrl(siteUrl, item.url)})`)
if (hasChildren) renderNavItems(item.items, siteUrl, lines, depth + 1)
continue
}

// Section heading without its own page
if (depth === 0 && hasChildren) {
lines.push('')
lines.push(`### ${label}`)
lines.push('')
renderNavItems(item.items, siteUrl, lines, 0)
continue
}

if (label) lines.push(`${indent}- ${label}`)
if (hasChildren) renderNavItems(item.items, siteUrl, lines, depth + 1)
}
}

function buildLlmsTxt (playbook, contentCatalog, navigationCatalog) {
const siteTitle = (playbook.site && playbook.site.title) || 'TigerGraph Documentation'
const siteUrl = (playbook.site && playbook.site.url) || ''
const lines = []

lines.push(`# ${siteTitle}`)
lines.push('')
lines.push(
'> TigerGraph developer documentation for Savanna (cloud-native graph database) and Cloud Classic. ' +
'Prefer the Markdown (`.md`) links below when loading pages into an LLM or coding agent.'
)
lines.push('')
lines.push(`- [HTML site](${siteUrl || '/'})`)
lines.push('')

const components = contentCatalog.getComponents().slice().sort((a, b) => {
// Prefer Savanna first, then alphabetical
if (a.name === 'savanna') return -1
if (b.name === 'savanna') return 1
return a.name.localeCompare(b.name)
})

for (const component of components) {
// Latest / only version for each component (both currently use version "main")
const version = component.latest || component.versions[0]
if (!version) continue

const navTrees = navigationCatalog.getNavigation(component.name, version.version) || []
if (!navTrees.length) continue

const versionLabel =
version.displayVersion && version.displayVersion !== 'default'
? ` (${version.displayVersion})`
: version.version && version.version !== 'main'
? ` (${version.version})`
: ''

lines.push(`## ${version.title}${versionLabel}`)
lines.push('')

for (const tree of navTrees) {
renderNavItems(tree.items || [tree], siteUrl, lines, 0)
}

lines.push('')
}

return `${lines.join('\n').replace(/\n{3,}/g, '\n\n').trim()}\n`
}

module.exports.register = function () {
let snapshot

this.on('navigationBuilt', ({ playbook, contentCatalog, navigationCatalog }) => {
snapshot = { playbook, contentCatalog, navigationCatalog }
})

this.on('beforePublish', ({ siteCatalog }) => {
if (!snapshot) return

const contents = Buffer.from(
buildLlmsTxt(snapshot.playbook, snapshot.contentCatalog, snapshot.navigationCatalog)
)

siteCatalog.addFile({
contents,
mediaType: 'text/plain',
out: { path: 'llms.txt' },
path: 'llms.txt',
pub: { url: '/llms.txt' },
src: { stem: 'llms' },
})
})
}
Loading
Loading