HonoX documentation theme with semantic vector search for Cloudflare Workers.
A beautiful documentation theme powered by HonoX and Cloudflare AI Search for semantic search capabilities. Fully optimized for Cloudflare Workers with R2 storage.
Note: This is a HonoX port of semantic-docs. For the original Astro version, see the main repository.
- 🎨 Modern Dark UI - Sleek design with Tailwind CSS
- 🔍 Semantic Search - Cloudflare AI Search with automatic indexing (React island component)
- 📦 R2 Storage - Markdown content and static assets stored on Cloudflare R2
- 📱 Responsive - Mobile-friendly with collapsible sidebar
- 📑 Auto TOC - Table of contents generated from headings
- 🚀 Edge-Ready - Runs globally on Cloudflare Workers
- ⚡ Fast - SSR with Hono JSX and React islands for interactivity
- 🎯 Type-Safe - Full TypeScript support
- 🔄 Auto Deploy - GitHub Actions deploys on push to main
- 🤖 AI-Powered Search - Cloudflare AI Search with vector embeddings
- Framework: HonoX - File-based routing meta-framework for Hono
- Runtime: Cloudflare Workers
- Storage: Cloudflare R2 (two buckets: content and static)
- Search: Cloudflare AI Search with automatic markdown indexing
- Styling: Tailwind CSS 4 (Vite plugin)
- Interactivity: React islands (Search, ThemeSwitcher, DocsToc)
- SSR: Hono JSX for server-side rendering
┌─────────────────────────────────────────┐
│ Cloudflare Worker │
│ │
│ ┌────────────┐ ┌────────────┐ │
│ │ CONTENT │ │ STATIC │ │
│ │ binding │ │ binding │ │
│ └──────┬─────┘ └──────┬─────┘ │
└─────────┼──────────────────┼───────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ hono-content │ │ hono-static │
│ │ │ │
│ ✅ AI Search │ │ ❌ Not indexed │
│ scans this │ │ │
│ │ │ │
│ • *.md files │ │ • client.*.js │
│ • Indexed │ │ • manifest.json │
│ • Searchable │ │ • favicon, etc. │
└──────────────────┘ └──────────────────┘
Why two buckets?
hono-content: Only markdown files (indexed by AI Search)hono-static: JavaScript, CSS, manifest (not indexed, saves resources)
⚠️ Local Development Note: This project requires Cloudflare infrastructure (R2 buckets, AI Search). Traditional local development withpnpm devdoes not work. See DEVELOPMENT.md for details.
git clone https://github.com/llbbl/semantic-docs-hono.git
cd semantic-docs-honopnpm installFollow the detailed setup guide: docs/CLOUDFLARE_SETUP.md
Quick checklist:
- Create two R2 buckets:
hono-contentandhono-static - Create AI Search index pointing to
hono-contentbucket - Set GitHub secrets:
CLOUDFLARE_API_TOKEN,CLOUDFLARE_ACCOUNT_ID - Set GitHub variables:
R2_CONTENT_BUCKET,R2_STATIC_BUCKET - Set Worker env variable:
AI_SEARCH_INDEX
Create markdown files in ./content:
mkdir -p content/getting-started
cat > content/getting-started/intro.md << 'EOF'
---
title: Getting Started
tags: [tutorial, beginner]
---
# Getting Started
This is my first article!
EOFPush to GitHub to trigger automatic deployment:
git add .
git commit -m "Add content"
git push origin mainGitHub Actions will:
- Build the client and server bundles
- Upload markdown files to
hono-contentR2 bucket - Upload static assets to
hono-staticR2 bucket - Deploy the Worker to Cloudflare
After deployment, manually trigger AI Search indexing:
- Go to Cloudflare Dashboard → AI → AI Search → Your index
- Click Sync to re-index content
- Wait for indexing to complete (check Jobs tab)
Visit your Worker URL (e.g., https://your-worker.workers.dev) to see your docs!
For local development (requires Cloudflare setup):
# Remote development (recommended)
pnpm dev:remote
# Build locally
pnpm build
# Deploy manually
pnpm deploySee DEVELOPMENT.md for detailed development workflows.
semantic-docs-hono/
├── app/ # HonoX application
│ ├── routes/ # File-based routes
│ │ ├── index.tsx # Home page
│ │ ├── content/ # Article routes
│ │ │ └── [...slug].tsx # Catch-all article route (fetches from R2)
│ │ └── api/ # API routes
│ │ └── search.ts # Search API endpoint (AI Search)
│ ├── components/ # Hono JSX components
│ │ ├── DocsHeader.tsx
│ │ ├── DocsSidebar.tsx
│ │ └── ui/ # shadcn-style components
│ ├── islands/ # React islands (client-side)
│ │ ├── Search.tsx # Search dialog with ⌘K shortcut
│ │ ├── ThemeSwitcher.tsx
│ │ └── DocsToc.tsx # Table of contents
│ ├── _renderer.tsx # HonoX layout renderer
│ ├── client.tsx # Client-side hydration (createRoot)
│ ├── server.ts # Hono server entry
│ └── style.css # Tailwind styles
├── src/ # Core logic
│ ├── lib/
│ │ └── logger.ts # Logging utility
│ └── index.ts # Workers entry point
├── content/ # Markdown content
│ ├── getting-started/
│ ├── features/
│ └── guides/
├── scripts/ # Build scripts
│ └── generate-client-manifest.ts # Cache busting
├── docs/ # Setup documentation
│ ├── CLOUDFLARE_SETUP.md
│ └── RATE_LIMITING.md
├── vite.config.ts
├── wrangler.toml # Cloudflare Workers config (R2 bindings)
└── package.json
- Astro → HonoX: File-based routing with Hono
- Server adapter changes from
@astrojs/nodeto Cloudflare Workers
- Astro components → Hono JSX: Server-side rendering
- React components → React islands: Client-side hydration for interactivity
- Manual HTML wrapper with
c.html()orc.body()instead of Astro layouts
- File naming:
[...slug].tsxfor catch-all routes (HonoX convention) - Routes wrapped with
createRoute()fromhonox/factory - Content fetched from R2 at runtime (not pre-rendered)
- Turso/libSQL → Cloudflare R2 + AI Search
- No manual indexing required (AI Search auto-indexes R2)
- No database credentials needed (uses Worker bindings)
- Before: Turso credentials, embedding provider API keys
- Now: Only
AI_SEARCH_INDEX(set in Worker settings)
# Development
pnpm dev:remote # Start remote dev server (wrangler dev --remote)
pnpm build # Build for production
pnpm preview # Preview production build (wrangler dev --remote)
# Testing & Linting
pnpm test # Run tests with Vitest
pnpm test:ui # Run tests with UI
pnpm test:coverage # Generate coverage report
pnpm lint # Check code with Biome
pnpm lint:fix # Auto-fix linting issues
pnpm format # Format all files
# Deployment
pnpm deploy # Deploy to Cloudflare WorkersNote: pnpm dev is disabled because local development requires Cloudflare bindings (R2, AI Search) that aren't available locally. Use pnpm dev:remote instead.
Deploy to Cloudflare Workers using Wrangler:
# Deploy (builds automatically)
pnpm deploy
# Or directly with wrangler
npx wrangler deployThe wrangler.toml is configured to build the project automatically before deployment.
Set environment variables in Cloudflare Dashboard:
- Go to Workers & Pages → Your Worker
- Settings → Variables and Secrets
- Add Environment Variable:
- Variable name:
AI_SEARCH_INDEX - Value: Your AI Search index name (e.g.,
semantic-docs)
- Variable name:
- Click Deploy to apply changes
That's it! No database credentials or API keys needed for basic functionality.
- Go to Security → WAF → Rate Limiting Rules
- Create rule for
/api/searchendpoint - Recommended: 20 requests/minute per IP
📖 See docs/RATE_LIMITING.md for detailed setup instructions.
Required:
AI_SEARCH_INDEX: Your Cloudflare AI Search index name
GitHub Secrets (for deployment workflow):
CLOUDFLARE_API_TOKEN: API token with Workers edit permissionsCLOUDFLARE_ACCOUNT_ID: Your Cloudflare account ID
GitHub Variables:
R2_CONTENT_BUCKET: Content bucket name (default:hono-content)R2_STATIC_BUCKET: Static bucket name (default:hono-static)
The semantic search is powered by Cloudflare AI Search:
- Manual Indexing: After deploying content, click Sync in AI Search dashboard
- Embedding Generation: AI Search converts content to vector embeddings
- Query Processing: User searches are vectorized and matched against indexed content
- Reranking: Results are reranked for relevance
- Results: Returned via
/api/searchendpoint
Indexing workflow:
- Deploy content to R2 (via GitHub Actions or manual upload)
- Go to Cloudflare Dashboard → AI → AI Search → Your index
- Click Sync to trigger re-indexing
- Wait for job to complete (check Jobs tab)
- Search will now return updated results
Search features:
- ⌘K keyboard shortcut to open
- Real-time results as you type
- Debounced API calls (300ms)
- Understanding of synonyms and related concepts
- Typo tolerance
See content/features/semantic-search.md for detailed documentation.
- Create markdown file in
./content/folder/article.md - Add frontmatter:
--- title: Article Title tags: [tag1, tag2] ---
- Commit and push to GitHub
- GitHub Actions uploads to R2
- Manually trigger AI Search sync in Cloudflare dashboard
- Delete file from
./content - Commit and push
- Manually delete from R2:
npx wrangler r2 object delete hono-content/folder/article.md --remote
- Manually trigger AI Search sync in Cloudflare dashboard
See content/features/r2-storage.md for full deletion workflow.
- No local dev:
pnpm devis disabled because R2 and AI Search bindings aren't available locally - Use remote dev:
pnpm dev:remoteruns against Cloudflare infrastructure - See DEVELOPMENT.md for details
- Deleting files from
./contentdoesn't automatically delete from R2 - Must manually run
npx wrangler r2 object deletecommand - See R2 Storage documentation for details
- React islands (Search, ThemeSwitcher, DocsToc) use
createRoot()for client-side mounting - Islands are not server-rendered (client-only components)
- Server components use Hono JSX (imported from
hono/jsx) - Client islands use React (imported from
react) tsconfig.jsonuses"jsxImportSource": "hono/jsx"by default- Islands override with
/** @jsxImportSource react */pragma
.tsxfiles inapp/routes/andapp/components/use Hono JSX.tsxfiles inapp/islands/use React with pragma overrideapp/client.tsxhandles island hydration withcreateRoot()
- Tailw
96F5
ind CSS 4 via
@tailwindcss/viteplugin - CSS variables in
app/style.cssfor theming - Multiple theme support (dark, light, ocean, forest, sunset, purple)
- Client JavaScript uses timestamped filenames:
client.1731369600000.js - Generated during build via
scripts/generate-client-manifest.ts - Ensures users get latest code after deployments
Comprehensive guides available in content/features/:
- semantic-search.md - How AI Search works
- honox-framework.md - HonoX routing and SSR
- r2-storage.md - R2 architecture and file management
- react-islands.md - Islands architecture
Setup guides in docs/:
- CLOUDFLARE_SETUP.md - Complete Cloudflare setup
- RATE_LIMITING.md - Rate limiting configuration
- DEVELOPMENT.md - Development workflows
Contributions welcome! This is a community-driven project.
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linter:
pnpm lint && pnpm test - Submit a pull request
MIT License - see LICENSE file for details
- Built with HonoX
- Search powered by Cloudflare AI Search
- Storage via Cloudflare R2
- Inspired by semantic-docs (Astro version)
- GitHub Issues: Report bugs or request features
- Discussions: Share ideas and ask questions
- Documentation: Check
content/features/for comprehensive guides