# Docship Theme Development Checklist
## ⚠️ Critical Rules
### No Advertisements Policy
- **NEVER use any theme or plugin that contains ads**
- Some official themes (e.g., `@vuepress/theme-vue`) contain sponsor/advertisement content - DO NOT USE
- Always check if theme contains ads, sponsor links, or donation prompts before using
- When in doubt, use the framework's default theme
**Known themes/plugins with ads (DO NOT USE):**
| Framework | Theme/Plugin | Issue |
| --------- | --------------------- | -------------------------------------- |
| VuePress | `@vuepress/theme-vue` | Contains sponsor/advertisement content |
**Recommended ad-free alternatives:**
| Framework | Recommended Theme |
| --------- | -------------------------------------------------- |
| VuePress | Default theme (built-in `@vuepress/theme-default`) |
### User Content Respect
- Never restrict user filenames (e.g., `index.md`, `temp.md` are all valid)
- User markdown content must never break builds regardless of validity
- Invalid image paths, links, etc. should be ignored, not cause errors
## Markdown Compatibility
- [ ] Use `markdown.format: 'md'` instead of MDX to avoid JSX parsing errors (Docusaurus)
- Users may have `${}`, `<>`, `{}` in their markdown content
- MDX will treat these as JSX expressions and fail
- [ ] VitePress is more lenient with `${}` but double curly braces will be treated as Vue template
- [ ] Don't restrict filenames - users can use any name like `temp.md`
- [ ] Handle files with special characters in content gracefully
## Docusaurus Configuration
- [ ] Don't use `navbar.logo` without `logo.src` - it will throw validation error
- [ ] Remove `sidebarPath` to let Docusaurus auto-generate sidebar from file structure
- [ ] Use `onBrokenLinks: 'ignore'` to prevent build failures on broken links
- [ ] Use `markdown.hooks.onBrokenMarkdownLinks: 'ignore'` (new location in v3.9+)
- [ ] Don't include deprecated options like root-level `onBrokenMarkdownLinks`
- [ ] For local search, use `@easyops-cn/docusaurus-search-local` (no API key needed)
- [ ] Algolia search requires API key - not suitable for generic themes
## VitePress Configuration
- [ ] Use `ignoreDeadLinks: true` to prevent build failures on broken/dead links
- [ ] VitePress does NOT auto-generate sidebar - need custom script or manual config
- [ ] `sidebar: 'auto'` does NOT work like Docusaurus - only shows current page headings
- [ ] Output directory is `.vitepress/dist` (not `build`)
- [ ] Use `srcDir: 'docs'` to specify source directory
- [ ] Exclude `node_modules` in content backup
- [ ] For local search, use `search: { provider: 'local' }` (built-in)
- [ ] `logo.link` does NOT support external URLs - need custom theme to override
## Sidebar Generation (VitePress)
- [ ] Write custom Node.js script to scan directory and generate sidebar config
- [ ] Sort entries: files first, then directories (or vice versa for consistency)
- [ ] Skip files starting with `.` or `_`
- [ ] Skip `index.md` from sidebar items (it's the folder landing page)
- [ ] Capitalize first letter and replace `-` with spaces for display text
## Homepage Selection Logic
Priority order:
1. `docs/index.md` or `content/index.md` - explicit homepage
2. `docs/README.md` or `content/README.md` - common convention
3. First `.md` file (sorted alphabetically) - fallback
- [ ] Always use `sort` before `head -1` for consistent results
- [ ] For Docusaurus: check if `slug: /` already exists before adding frontmatter
- [ ] For VitePress: `index.md` is automatically the homepage, no frontmatter needed
## GitHub Actions / Reusable Workflows
- [ ] Reusable workflows MUST be in `.github/workflows/` directory
- [ ] Use `on: workflow_call` for workflows that should only be called by others
- [ ] Caller workflow must declare `permissions` for the called workflow to use
- [ ] Remove `push` and `workflow_dispatch` triggers if workflow should not run directly
## Content Backup
- [ ] Exclude `README.md` from root (usually not documentation)
- [ ] Exclude hidden directories (`.git`, `.github`, etc.)
- [ ] Exclude `node_modules` directory
- [ ] Copy all user folders to preserve structure
- [ ] Handle empty content directory - create default welcome page
## Build & Deploy
- [ ] GitHub Pages keeps old version online during build (atomic deployment)
- [ ] First deployment shows blank page until complete - this is normal
- [ ] Public repos have unlimited GitHub Actions minutes
- [ ] Add npm cache to speed up builds: `actions/cache@v4` with `~/.npm` path
## Shell Script Best Practices (GitHub Actions)
- [ ] Don't use `sed -i '1s/^/...\n.../'` - `\n` may not work on all systems
- [ ] Don't use heredoc (`<< EOF`) inside YAML `run:` blocks - causes syntax errors
- [ ] Use `printf '%s\n' 'line1' 'line2'` for multi-line content
- [ ] Use temp files + `cat` + `mv` to prepend content to files
- [ ] Always quote variables: `"$TARGET"` not `$TARGET`
## Logo & Branding
- [ ] Use `https://github.com/USERNAME.png` to get user/org avatar
- [ ] VitePress: need custom theme (`enhanceApp`) to make logo link to external URL
- [ ] Docusaurus: `logo.href` + `logo.target: '_blank'` works for external links
- [ ] Set favicon with `head: [['link', { rel: 'icon', href: '...' }]]` (VitePress)
- [ ] Docusaurus favicon can be external URL directly
## Testing Scenarios
Before releasing a theme, test with:
- [ ] Empty repository (no markdown files)
- [ ] Single markdown file
- [ ] Nested folder structure
- [ ] Files with `${}` syntax in content
- [ ] Files with JSX-like syntax ``
- [ ] Files with curly braces `{}`
- [ ] Files with Vue template syntax (VitePress specific)
- [ ] Unicode/special characters in filenames
- [ ] Very long filenames
- [ ] Files starting with `_` (usually ignored by default)
- [ ] Files containing `localhost` URLs (dead link check)
- [ ] Repository without `index.md` (homepage fallback logic)
## Starlight (Astro) Configuration
- [ ] Use `npm create astro@latest -- --template starlight` for correct project structure
- [ ] Starlight v0.33.0+ changed `social` config from object to array format
- Old: `social: { github: 'url' }`
- New: `social: [{ icon: 'github', label: 'GitHub', href: 'url' }]`
- [ ] Every `.md` file MUST have `title` in frontmatter - Starlight will fail without it
- [ ] Sidebar `slug` must be lowercase - uppercase will cause "slug does not exist" error
- [ ] `autogenerate: { directory: '.' }` doesn't work well - use specific directory names
- [ ] Content goes in `src/content/docs/` directory
- [ ] Output directory is `dist`
- [ ] Use `.mdx` extension for index file if needed
## Rspress Configuration
- [ ] Public assets go in `docs/public/` (not project root `public/`)
- [ ] Sidebar `items` must be an array, not `'auto'` string
- [ ] Output directory is `doc_build`
- [ ] Exclude `public` directory from sidebar generation
- [ ] Config file is `rspress.config.ts` (TypeScript)
## Common Errors & Solutions
| Error | Cause | Solution |
| ---------------------------------------------------- | ------------------------------------------------ | --------------------------------------------------------------------------------- |
| `navbar.logo.src is required` | Using `logo` without `src` | Remove `logo` or add `src` |
| `Could not parse expression with acorn` | MDX parsing `${}` as JSX | Use `markdown.format: 'md'` |
| `workflow is not reusable` | Missing `workflow_call` trigger | Add `on: workflow_call` |
| `requesting pages: write but only allowed none` | Caller missing permissions | Add `permissions` to caller |
| `onBrokenMarkdownLinks deprecated` | Old config location | Move to `markdown.hooks` |
| `Found dead link` (VitePress) | Broken links in markdown | Use `ignoreDeadLinks: true` |
| `sidebar: 'auto' not working` | VitePress doesn't auto-generate | Write custom sidebar script |
| `Page Not Found` on homepage | Missing `slug: /` frontmatter | Add frontmatter to first doc |
| `here-document delimited by end-of-file` | Heredoc in YAML run block | Use `printf` instead |
| `social: Expected array, received object` | Starlight v0.33.0+ API change | Use array format for social links |
| `title: Required` (Starlight) | Missing frontmatter title | Auto-add title from filename |
| `slug does not exist` (Starlight) | Uppercase slug in sidebar | Convert slug to lowercase |
| `Entry docs → 404 was not found` | No valid index page | Ensure index.md/mdx exists with frontmatter |
| `item.items.map is not a function` | Rspress sidebar `items: 'auto'` | Use array of items, not string |
| `Failed to read favicon` (Rspress) | Wrong public directory path | Put assets in `docs/public/` |
| `Module not found: Can't resolve './assets/...'` | Invalid image path in markdown | Set `remarkImageOptions: false` (Fumadocs) or `staticImage: false` (Nextra) |
| `Unrecognized keys: "theme", "themeConfig"` | Nextra v4 API changed | Use new `nextra()` config format |
| `Export doesn't exist in target module` | Simplified source.ts missing exports | Delete files that depend on removed exports (e.g., `app/og`, `app/llms-full.txt`) |
| `fatal: No url found for submodule path` | Downloaded repo folder treated as submodule | Add folder to `.gitignore` or `git rm -r --cached folder` |
| `shallow cloned, latest modified time not presented` | GitHub Actions shallow clone | Warning only, can ignore or use `fetch-depth: 0` |
| `InvalidTocFile: not a valid TOC File` (DocFX) | Empty or malformed toc.yml | Delete invalid toc.yml from subdirectories |
| Logo/favicon not showing (DocFX) | External URL in `_appLogoPath`/`_appFaviconPath` | Use custom template JS to inject external URLs |
| Homepage 404 (VuePress) | Using `index.md` instead of `README.md` | Rename `index.md` to `README.md` |
| `sidebar: 'auto'` not showing files (VuePress) | VuePress auto only shows headings | Generate sidebar config via Node.js script |
| Theme has ads/sponsors (VuePress) | Using `@vuepress/theme-vue` | Use default theme (built-in, no ads) |
| `Prerendered 5 routes` only (Docus) | Nuxt can't crawl to doc pages | Add routes to `nitro.prerender.routes` |
| 404 on `/docs/CHECKLIST` (Docus) | Uppercase filename in route | Convert routes to lowercase |
| Blank page on root (Docus) | `index` file without `.html` | Create `index.html` redirect after build |
| `@nuxtjs/mcp-toolkit not compatible` (Docus) | MCP needs server | Warning only, can ignore |
| `robots.txt with base URL` error (Docus) | robots module conflict | Set `robots: { robotsTxt: false }` |
| No sidebar on homepage (Docus) | `content/index.md` is landing page | Put docs in `content/1.docs/` subdirectory |
## Fumadocs Configuration
- [ ] Fumadocs is based on Next.js - requires `output: 'export'` for static build
- [ ] Use `basePath` for GitHub Pages deployment (e.g., `/${REPO_NAME}`)
- [ ] Set `images: { unoptimized: true }` for static export
- [ ] Content goes in `content/docs/` directory
- [ ] Output directory is `out` (Next.js static export default)
- [ ] Every `.mdx` file should have frontmatter with `title` and `description`
- [ ] Use `create-fumadocs-app` with `--template +next+fuma-docs-mdx+static` for static export
- [ ] Fumadocs MDX is the official content source
- [ ] Config file is `next.config.mjs` (ESM)
- [ ] Requires `fumadocs-mdx/next` plugin wrapper
- [ ] Set `remarkImageOptions: false` in `source.config.ts` to prevent build failures from invalid image paths
- [ ] Delete `app/llms-full.txt` and `app/og` directories (they depend on exports not in simplified source.ts)
- [ ] Clear template's default `content/docs/*` before copying user content (removes Hello World page)
## Nextra Configuration
- [ ] Nextra v4 uses App Router - structure is `src/app/` and `src/content/`
- [ ] Requires `output: 'export'` and `images: { unoptimized: true }` for static build
- [ ] Use `basePath` via environment variable for GitHub Pages
- [ ] Content goes in `src/content/` directory
- [ ] Output directory is `out`
- [ ] Need `mdx-components.js` at project root for MDX components
- [ ] Use `nextra-theme-docs` for documentation theme
- [ ] Config uses `nextra()` wrapper with `contentDirBasePath` option
- [ ] Homepage redirect to `/docs` since content is under `/docs` route
- [ ] Nextra uses MDX - user content with `${}`, `<>`, `{}` may cause JSX parsing errors
- [ ] Set `staticImage: false` to prevent build failures from invalid image paths
## VuePress Configuration
- [ ] VuePress 1.x is Vue 2 based - use `vuepress@^1.9.10`
- [ ] **⚠️ DO NOT USE `@vuepress/theme-vue`** - it contains sponsor/advertisement content
- [ ] Use default theme `@vuepress/theme-default` (built-in, no ads)
- [ ] Content goes in `docs/` directory
- [ ] Output directory is `docs/.vuepress/dist`
- [ ] Config file is `docs/.vuepress/config.js`
- [ ] Use `base: '/${REPO_NAME}/'` for GitHub Pages subdirectory
- [ ] `themeConfig.logo` supports external URLs directly
- [ ] `themeConfig.sidebar: 'auto'` only shows current page headings - need Node.js script for full sidebar
- [ ] Homepage is `docs/README.md` (not `index.md`) - must rename `index.md` to `README.md`
- [ ] Use `themeConfig.repo` for GitHub link in navbar
- [ ] Custom styles go in `docs/.vuepress/styles/index.styl` (Stylus)
- [ ] Use `enhanceApp.js` for client-side customizations (e.g., footer injection)
- [ ] Favicon via `head: [['link', { rel: 'icon', href: 'URL' }]]` - supports external URLs
- [ ] VuePress uses Vue template syntax - double curly braces in markdown will be parsed as Vue expressions
- [ ] Use `@vuepress/plugin-back-to-top` for back-to-top button (built-in plugin)
- [ ] VuePress 1.x does NOT have native dark mode toggle - custom implementation is complex
- [ ] Green scrollbar: apply only to `.sidebar` selector, not whole page
## DocFX Configuration
- [ ] DocFX is a .NET-based documentation framework - uses `dotnet tool install -g docfx`
- [ ] Content goes in `docs/` directory
- [ ] Output directory is `_site`
- [ ] Config file is `docfx.json`
- [ ] Uses `toc.yml` for navigation structure (root for navbar, docs/ for sidebar)
- [ ] `_appLogoPath` and `_appFaviconPath` do NOT support external URLs - need custom template
- [ ] Use custom template with JavaScript to inject external avatar as logo/favicon
- [ ] Remove root `toc.yml` to hide navbar tabs (e.g., "Docs" tab) when only one section
- [ ] Use `redirect_url` frontmatter in `index.md` to redirect homepage to docs
- [ ] Set `_disableContribution: true` to hide "Edit this page" link
- [ ] Set `_appFooter` to customize or remove footer
- [ ] Sidebar toc.yml format: `- name: Title` + `href: file.md`
- [ ] Delete invalid `toc.yml` files from user content subdirectories
- [ ] Exclude framework source folders in backup (fumadocs/, nextra/, docute/, etc.)
## Docute Configuration
- [ ] Docute is a pure frontend framework - no build process needed
- [ ] Only needs `index.html` + markdown files
- [ ] Uses CDN for docute.js and docute.css (`unpkg.com/docute@4`)
- [ ] URL routing: `/` => `/README.md`, `/foo` => `/foo.md`, `/foo/` => `/foo/README.md`
- [ ] Sidebar must be manually configured or auto-generated via script
- [ ] Logo is a Vue template string - use `` wrapper with flex layout for avatar + text
- [ ] Use `darkThemeToggler: true` for dark mode toggle
- [ ] No npm cache needed since no build process
## mdBook Configuration
- [ ] mdBook is a Rust-based documentation tool - install via pre-built binary or `cargo install mdbook`
- [ ] Content goes in `src/` directory
- [ ] Output directory is `book/`
- [ ] Config file is `book.toml` (TOML format)
- [ ] Requires `src/SUMMARY.md` to define table of contents structure
- [ ] Homepage is `src/README.md` (linked as `[Introduction](README.md)` in SUMMARY.md)
- [ ] SUMMARY.md format: `- [Title](path/to/file.md)` for chapters
- [ ] Use `#` headers in SUMMARY.md to create section separators
- [ ] `[output.html]` section in book.toml for HTML output settings
- [ ] `site-url` in book.toml for base path (GitHub Pages subdirectory)
- [ ] Custom theme via `theme/` directory - can override `index.hbs`, `head.hbs`, CSS files
- [ ] Favicon and logo require custom theme modifications (no direct config option)
- [ ] Built-in themes: light, rust, coal, navy, ayu
- [ ] `default-theme` and `preferred-dark-theme` in `[output.html]` section
- [ ] Supports MathJax via `mathjax-support = true`
- [ ] Built-in search functionality (no additional config needed)
## Eleventy Configuration
- [ ] Eleventy (11ty) is a JavaScript-based static site generator
- [ ] Install via `npm install @11ty/eleventy`
- [ ] Config file is `eleventy.config.js` or `.eleventy.js`
- [ ] Default input directory is `.` (project root)
- [ ] Default output directory is `_site`
- [ ] Supports multiple template languages: Liquid, Nunjucks, Markdown, HTML, JavaScript
- [ ] Use `dir.input` and `dir.output` in config to customize directories
- [ ] Use `pathPrefix` for GitHub Pages subdirectory deployment
- [ ] Layouts go in `_includes/` directory by default
- [ ] Data files go in `_data/` directory (JSON, JS, or YAML)
- [ ] Use frontmatter `layout` to specify template layout
- [ ] Collections are auto-generated from tags or can be custom defined
- [ ] Use `eleventyConfig.addPassthroughCopy()` for static assets
- [ ] Markdown files need frontmatter with `layout` to use templates
- [ ] No built-in theme - requires custom CSS/layout
## Sphinx Configuration
- [ ] Sphinx is a Python-based documentation generator
- [ ] Install via `pip install sphinx furo myst-parser`
- [ ] Config file is `conf.py` (Python)
- [ ] Default source directory is `docs/` or project root
- [ ] Default output directory is `_build/html/`
- [ ] Use `myst-parser` extension to support Markdown (default is reStructuredText)
- [ ] Furo is a modern, clean theme (BSD license)
- [ ] Use `toctree` directive to define navigation structure
- [ ] `html_theme = 'furo'` to use Furo theme
- [ ] `html_logo` and `html_favicon` for branding
- [ ] `html_theme_options` for theme customization
- [ ] Custom CSS goes in `_static/` directory
- [ ] Build with `sphinx-build -b html docs docs/_build/html`
- [ ] License is BSD (Sphinx) + MIT (Furo) - very permissive
## Docus Configuration
- [ ] Docus is a Nuxt 4-based documentation framework (MIT license)
- [ ] Install via `npm install docus nuxt better-sqlite3`
- [ ] Config file is `nuxt.config.ts` with `extends: ['docus']`
- [ ] Content goes in `content/` directory with number prefixes for ordering (e.g., `1.docs/`, `2.guide/`)
- [ ] Output directory is `.output/public/`
- [ ] Use `nuxt generate` for static build
- [ ] **Homepage is special** - `content/index.md` renders as landing page without sidebar
- [ ] **Documentation pages need subdirectory** - put docs in `content/1.docs/` to get sidebar layout
- [ ] Number prefixes in filenames control order: `1.index.md`, `2.guide.md` → `/index`, `/guide`
- [ ] Use `.navigation.yml` in directories to set section titles
- [ ] Frontmatter `title` is required for each page
- [ ] `app.config.ts` goes in `app/` directory for theme configuration
- [ ] `header.title` and `header.logo` for branding
- [ ] `socials.github` for GitHub link in header
- [ ] Custom components override defaults - put in `app/components/app/`
- [ ] `AppHeaderLogo.vue` - customize logo + title display
- [ ] `AppFooterLeft.vue` - customize footer left (attribution)
- [ ] `AppFooterRight.vue` - customize footer right (social icons, theme toggle)
- [ ] Set empty `AppFooterRight.vue` to remove duplicate theme toggle
- [ ] Logo click should link to `/docs` not `/` (override `AppHeaderLogo.vue` with ``)
- [ ] Favicon via `app.head.link` in `nuxt.config.ts`
- [ ] **Prerendering issue**: Nuxt only prerenders routes it can crawl from homepage
- [ ] Must explicitly list routes in `nitro.prerender.routes` or generate dynamically
- [ ] Convert filenames to lowercase for routes (uppercase causes 404)
- [ ] Create `index.html` redirect after build for root → `/docs`
- [ ] `robots: { robotsTxt: false }` to avoid base URL error
- [ ] `@nuxtjs/mcp-toolkit` warning is normal - not compatible with static generate
## General Lessons Learned
### Framework Categories
1. **Build-required frameworks** (need npm install + build):
- Docusaurus, VitePress, Starlight, Rspress, Fumadocs, Nextra
- Need npm cache for faster builds
- Output to specific directories (build/, dist/, out/, doc\_build/)
2. **Pure frontend frameworks** (no build, CDN-based):
- Docsify, Docute
- Just HTML + markdown files
- Faster deployment, simpler setup
3. **Next.js-based frameworks**:
- Fumadocs, Nextra
- Require `output: 'export'` for static build
- Require `images: { unoptimized: true }` for static export
- Use `basePath` for GitHub Pages subdirectory
### Common Pitfalls
- [ ] **Image handling**: MDX/Next.js frameworks try to import images - disable with `remarkImageOptions: false` or `staticImage: false`
- [ ] **Template default content**: Many templates include "Hello World" or demo content - clear before copying user content
- [ ] **CLI argument changes**: Framework CLIs change frequently - check latest docs (e.g., `create-fumadocs-app` changed from `--name --template --src` to `--template +next+fuma-docs-mdx+static`)
- [ ] **API version changes**: Check for breaking changes (e.g., Starlight social config changed from object to array)
- [ ] **Sidebar in sidebar**: Some frameworks show index page in sidebar - use `index: true` frontmatter to hide it
### Branding Consistency
For all frameworks, implement:
- [ ] Logo: User avatar + `username/reponame` in top-left
- [ ] Favicon: User's GitHub avatar (`https://github.com/USERNAME.png`)
- [ ] GitHub link: Icon or text link to repository (right side of navbar)
- [ ] Title: `username/reponame` in browser tab
- [ ] Footer: `Powered by NekoTick · {Framework}` with links to both projects
### Footer Format
All workflows must include a footer with attribution: `Powered by NekoTick · {Framework}`
- [ ] NekoTick link: `https://github.com/NekoTick/NekoTick`
- [ ] Framework link: GitHub repository of the framework (not official website)
- [ ] NekoTick comes first (deployment service provider)
- [ ] Framework comes second (underlying tool)
- [ ] Use `·` as separator
- [ ] Links should open in new tab (`target="_blank"`)
| Framework | GitHub Link |
| --------------- | ---------------------------------------------- |
| Docusaurus | `https://github.com/facebook/docusaurus` |
| VitePress | `https://github.com/vuejs/vitepress` |
| Starlight | `https://github.com/withastro/starlight` |
| Rspress | `https://github.com/web-infra-dev/rspress` |
| Fumadocs | `https://github.com/fuma-nama/fumadocs` |
| Nextra | `https://github.com/shuding/nextra` |
| Docute | `https://github.com/egoist/docute` |
| DocFX | `https://github.com/dotnet/docfx` |
| Docsify | `https://github.com/docsifyjs/docsify` |
| MkDocs Material | `https://github.com/squidfunk/mkdocs-material` |
| VuePress | `https://github.com/vuejs/vuepress` |
| mdBook | `https://github.com/rust-lang/mdBook` |
| Eleventy | `https://github.com/11ty/eleventy` |
| Hugo | `https://github.com/gohugoio/hugo` |
| Sphinx | `https://github.com/sphinx-doc/sphinx` |
| Docus | `https://github.com/nuxt-content/docus` |
### Logo Implementation Patterns
| Framework | Logo Config |
| ---------- | ----------------------------------------------------------------------------- |
| Docusaurus | `navbar.logo.src` + `navbar.title` |
| VitePress | `themeConfig.logo` + `themeConfig.siteTitle` |
| Fumadocs | `nav.title` as JSX with `
` + `` |
| Nextra | `Navbar logo` prop as JSX |
| Docute | `logo` as Vue template string |
| DocFX | Custom template JS to replace `#logo` element |
| VuePress | `themeConfig.logo` (external URL supported) |
| Starlight | `logo.src` + `title` |
| Docus | Custom `AppHeaderLogo.vue` with `` + `` + `` |
| Hugo | `params.BookLogo` in hugo.yaml (external URL supported) |
### Sidebar Generation
- [ ] Auto-generate from directory structure when possible
- [ ] Convert filenames to titles: `my-file.md` → `My File`
- [ ] Handle nested directories as collapsible groups
- [ ] Skip `README.md` / `index.md` from sidebar items (they're folder landing pages)
- [ ] Use `sort` for consistent ordering
### Testing Checklist (Updated)
- [ ] Files with invalid image paths (should not break build)
- [ ] Files with special markdown syntax (`${}`, `<>`, `{}`)
- [ ] Empty repository (should show welcome page)
- [ ] Nested folder structure (should generate proper sidebar)
- [ ] Repository without index.md (should use first doc as homepage)
## Multi-Language Support
- [ ] VitePress/Docusaurus i18n is static - requires manual translation files
- [ ] No automatic translation built-in
- [ ] Options: browser translation, or integrate translation API (costs money)
- [ ] Structure: `docs/en/`, `docs/zh/` etc. for each language
## Adding New Framework
When adding a new documentation framework to Docship:
### 1. Create Workflow File
- [ ] Create `.github/workflows/{framework}.yml`
- [ ] Use `on: workflow_call` with `base_path_suffix` and `deploy` inputs
- [ ] Follow existing workflow structure for consistency
### 2. Add Footer Attribution
Every framework MUST include a footer with: `Powered by NekoTick · {Framework}`
- [ ] NekoTick link: `https://github.com/NekoTick/NekoTick`
- [ ] Framework link: GitHub repository of the framework
- [ ] Use `·` (middle dot) as separator
- [ ] Links should open in new tab (`target="_blank"`)
**Footer implementation by framework type:**
| Framework Type | Implementation Method |
| --------------- | --------------------------------------------------------- |
| Docusaurus | `themeConfig.footer.copyright` |
| VitePress | `themeConfig.footer.message` |
| Docsify | Plugin with `hook.afterEach` |
| Docute | `footer` config option |
| Starlight | Custom Footer.astro component |
| Rspress | `themeConfig.footer.message` |
| MkDocs Material | `copyright` in mkdocs.yml |
| HonKit | JS injection in HTML files |
| DocFX | `_appFooter` in globalMetadata |
| Fumadocs | Footer element in app/layout.tsx |
| Nextra | `footer` prop in Layout component |
| VuePress | enhanceApp.js DOM injection |
| mdBook | Custom theme/index.hbs or theme/head.hbs |
| Eleventy | Custom layout template with footer |
| Sphinx | Custom CSS in \_static/custom.css |
| Docus | `footer.credits` in app.config.ts |
| Hugo | Custom partial `layouts/partials/docs/inject/footer.html` |
| Jekyll | `footer_content` in \_config.yml |
### 3. Update Showcase
- [ ] Add build job in `showcase.yml` with `name: {framework}`
- [ ] Add to `needs` array in `combine` job
- [ ] Add build result env variable (e.g., `BUILD_FRAMEWORK`)
- [ ] Add to `RESULTS` array in combine step
- [ ] Add entry in `showcase/frameworks.json` with GitHub link(s)
**frameworks.json format:**
```json
{
"framework-name": {
"links": ["https://github.com/org/repo"]
},
"framework-with-theme": {
"links": ["https://github.com/org/framework", "https://github.com/org/theme"]
}
}
```
### 4. Update Documentation
- [ ] Add framework to README.md supported frameworks table
- [ ] Add framework-specific notes to CHECKLIST.md if needed