@hillnote/publish
v2.4.2
Published
Transform your Hillnote workspace into a beautiful documentation or Blog with Next.js. Usage: npx @hillnote/publish init
Downloads
275
Maintainers
Readme
@hillnote/publish
Transform your Hillnote workspace into a beautiful, SEO-optimized documentation website with Next.js and modern UI components.
🚀 Overview
@hillnote/publish is a complete documentation generation system that converts your Hillnote markdown workspace into a production-ready Next.js website. Simply run one command to set up the entire documentation system in your Next.js project.
✨ Features
- 📚 Beautiful documentation UI with hierarchical navigation sidebar
- 🎨 Dark/Light theme support with next-themes
- 📱 Fully responsive design
- 🔍 Built-in search functionality across all documents
- 🤖 AI-crawler optimized with llms.txt and structured data
- 📄 Automatic sitemap.xml and robots.txt generation
- 📁 Auto-expanding navigation for active documents
- 🔗 Smart URL routing with SEO-friendly slugs
- 📝 Advanced markdown rendering with syntax highlighting
- 🏷️ Support for document metadata, related documents, and author's notes
- ⚡ Static page generation for optimal performance
- 🛠️ Simple CLI setup - one command to install everything
🎯 Quick Start (Recommended)
Install in Your Next.js Project
# Navigate to your Next.js project
cd your-nextjs-project
# Run the initialization command
npx @hillnote/publish init
# Or if using src/app structure
npx @hillnote/publish init --srcThat's it! The CLI will automatically:
- ✓ Copy the
hillnoteDocsystem to your project - ✓ Set up API routes for search and document fetching
- ✓ Add the page generation script
- ✓ Update your package.json with necessary scripts
- ✓ Configure everything based on your project structure
Next Steps
Add your Hillnote workspace:
cp -r "/path/to/Welcome to Hillnote!" public/Configure your site: Edit
hillnoteDoc/config/site.config.js(orsrc/hillnoteDoc/config/site.config.js)Generate pages:
npm run generate-pagesStart your dev server:
npm run dev
Your documentation site will be live at http://localhost:3000/doc
📦 What Gets Installed
When you run npx @hillnote/publish init, the following structure is added to your project:
your-project/
├── hillnoteDoc/ # Documentation system (or src/hillnoteDoc/)
│ ├── components/ # UI components
│ ├── config/ # Configuration
│ ├── lib/ # Utilities
│ └── styles/ # Styles
├── app/api/ # API routes (or src/app/api/)
│ ├── ai-sitemap/
│ ├── docs/
│ └── search/
└── scripts/
└── generate-pages.mjs # Page generation script🔧 Installation & Setup
Prerequisites
- Node.js 18+
- Next.js 15+ project (with App Router)
- A Hillnote workspace exported with markdown files
Step 1: Initialize
npx @hillnote/publish initStep 2: Add Your Workspace
Copy your Hillnote workspace folder to public/:
cp -r "/path/to/Welcome to Hillnote!" public/Step 3: Configure
Edit hillnoteDoc/config/site.config.js:
- Set your site name and description
- Update the workspace path to match your folder name
- Customize routing, SEO, and UI settings
Step 4: Generate & Run
npm run generate-pages
npm run dev📦 Alternative: Manual Setup (For Advanced Users)
If you prefer not to use the CLI or want more control:
Option 1: Use the NextJS Boilerplate
Copy the boilerplate to your project location:
cp -r "NextJS Boilerplate" /path/to/your-project-name cd /path/to/your-project-nameInstall dependencies:
npm installAdd your Hillnote workspace:
# Copy your exported Hillnote workspace to the public folder cp -r "/path/to/Welcome to Hillnote!" public/Configure your site: Edit
hillnoteDoc/config/site.config.jswith your site details (see Configuration section below)Generate pages and start:
npm run generate-pages npm run devYour site will be live at
http://localhost:3000
Option 2: Add to Existing Next.js Project
Copy the hillnoteDoc folder to your project root:
cp -r hillnoteDoc /path/to/your-nextjs-project/Copy the necessary files:
# Copy API routes cp -r "hillnoteDoc/-- TO BE MOVED --/api/"* your-project/app/api/ # OR if using src folder: cp -r "hillnoteDoc/-- TO BE MOVED --/api/"* your-project/src/app/api/ # Copy the generation script cp "hillnoteDoc/-- TO BE MOVED --/scripts/generate-pages-app.mjs" your-project/scripts/generate-pages.mjs # OR if using src folder: cp "hillnoteDoc/-- TO BE MOVED --/scripts/generate-pages-src.mjs" your-project/scripts/generate-pages.mjsInstall required dependencies:
npm install @radix-ui/react-accordion @radix-ui/react-checkbox @radix-ui/react-dialog \ @radix-ui/react-scroll-area @radix-ui/react-separator @radix-ui/react-slot \ @radix-ui/react-tabs class-variance-authority clsx gray-matter lucide-react \ marked marked-gfm-heading-id next-themes tailwind-mergeAdd the generation script to package.json:
{ "scripts": { "generate-pages": "node scripts/generate-pages.mjs", "prebuild": "node scripts/generate-pages.mjs" } }Copy your Hillnote workspace to public folder and configure site.config.js
⚙️ Configuration
Edit hillnoteDoc/config/site.config.js:
export const siteConfig = {
// Basic site information
siteName: "Your Documentation Site",
siteDescription: "Your site description",
siteUrl: "https://your-domain.com",
// Project Structure
projectStructure: {
useSrcFolder: false, // true if using src/app, false if using app/
},
// SEO Configuration
seo: {
titleTemplate: "%s | Your Site",
defaultTitle: "Your Documentation",
defaultDescription: "Default meta description",
keywords: "your, keywords, here",
author: "Your Name",
publisher: "Your Organization",
llmsIntro: "Introduction for AI crawlers",
allowAIBots: true,
crawlDelay: null,
},
// Routing Configuration
routing: {
docBase: "doc", // Base path for docs (e.g., /doc, /docs, /wiki)
trailingSlash: false,
},
// Workspace Configuration
workspace: {
path: "/Welcome to Hillnote! /", // Your workspace folder name in public/
enabled: true,
documentsFolder: "documents",
registryFile: "documents-registry.json",
initialFile: "documents/Start Here .md",
},
// UI Configuration
ui: {
navigationMode: "wiki", // "emoji" or "wiki"
showHeaders: true,
authorsNotes: {
enabled: true,
title: "Author's Notes",
},
relatedDocuments: {
enabled: true,
title: "Related Documents",
}
}
}📁 Project Structure
your-project/
├── app/ (or src/app/) # Next.js app directory
│ ├── api/ # API routes
│ │ ├── ai-sitemap/ # AI-readable sitemap
│ │ ├── docs/ # Document fetch API
│ │ └── search/ # Search API
│ └── doc/ # Generated static pages (auto-generated)
├── hillnoteDoc/ # Documentation system
│ ├── components/ # UI components
│ │ ├── ask-ai-dialog.jsx
│ │ ├── navigation-sidebar.jsx
│ │ ├── search-dialog.jsx
│ │ ├── table-of-contents.jsx
│ │ ├── theme-provider.jsx
│ │ └── theme-toggle.jsx
│ ├── config/
│ │ └── site.config.js # Main configuration file
│ ├── lib/ # Utility functions
│ │ ├── debounce.js
│ │ ├── documents-server.js
│ │ ├── slug-utils.js
│ │ ├── static-routes.js
│ │ └── workspace.js
│ ├── styles/
│ │ └── markdown.css # Markdown styling
│ └── -- TO BE MOVED --/ # Files to copy to your project
│ ├── api/ # API routes templates
│ └── scripts/ # Generation scripts
├── components/
│ └── ui/ # Shadcn UI components
├── public/
│ ├── Welcome to Hillnote!/ # Your Hillnote workspace
│ ├── robots.txt # Auto-generated
│ ├── sitemap.xml # Auto-generated
│ └── llms.txt # Auto-generated
├── scripts/
│ └── generate-pages.mjs # Page generation script
└── package.json🔧 Components
Navigation Components
NavigationSidebar
Hierarchical sidebar with collapsible sections.
import { NavigationSidebar } from '@/hillnoteDoc/components/navigation-sidebar'
<NavigationSidebar />TableOfContents
Automatically generated from document headings.
import { TableOfContents } from '@/hillnoteDoc/components/table-of-contents'
<TableOfContents />Interactive Components
SearchDialog
Full-text search across all documents.
import { SearchDialog } from '@/hillnoteDoc/components/search-dialog'
<SearchDialog />AskAIDialog
AI-powered question answering (requires API integration).
import { AskAIDialog } from '@/hillnoteDoc/components/ask-ai-dialog'
<AskAIDialog />ThemeToggle
Dark/light theme switcher.
import { ThemeToggle } from '@/hillnoteDoc/components/theme-toggle'
<ThemeToggle />🛠️ Utilities
Workspace Functions
import {
getWorkspaceFileTree,
buildFileTree,
fetchWorkspaceRegistry
} from '@/hillnoteDoc/lib/workspace'Document Functions
import {
getDocumentRegistry,
getDocumentByPath,
findDocumentBySlug
} from '@/hillnoteDoc/lib/documents-server'Slug Utilities
import {
pathToSlug,
documentPathToStaticUrl
} from '@/hillnoteDoc/lib/slug-utils'📝 Page Generation
The generate-pages.mjs script automatically:
- Scans your Hillnote workspace for markdown files
- Generates static Next.js pages in
app/doc/(orsrc/app/doc/) - Creates SEO files:
public/sitemap.xml- XML sitemap for search enginespublic/robots.txt- Robot crawling rulespublic/llms.txt- AI-readable content indexpublic/llms-txt.txt- Extended AI crawler content
Running Generation
# Manual generation
npm run generate-pages
# Automatic on build (configured in package.json prebuild)
npm run buildCommand Line Options
node scripts/generate-pages.mjs [options]
Options:
--no-sitemap Do not generate sitemap.xml
--no-robots Do not generate robots.txt
--no-llms Do not generate llms.txt and llms-txt.txt files
-h, --help Show help messageNote: doc/page.* and doc/layout.* files are always preserved if they exist, allowing you to customize the root documentation page and layout without them being overwritten.
Examples
# Generate everything (default)
npm run generate-pages
# Skip sitemap and robots.txt generation
node scripts/generate-pages.mjs --no-sitemap --no-robots
# Only generate document pages (no SEO files)
node scripts/generate-pages.mjs --no-sitemap --no-robots --no-llms📰 Blog Support
@hillnote/publish includes a full-featured blog system that integrates seamlessly with your documentation site.
Setting Up the Blog
# Initialize the blog system in your project
node scripts/generate-blog.mjs --setupThis creates the following structure:
your-project/
├── public/
│ └── blog/
│ ├── draft/ # Draft posts (not published)
│ ├── published/ # Published posts (live on site)
│ └── resources/ # Images and assets
│ └── images/
├── app/ (or src/app/)
│ ├── api/
│ │ └── blog/
│ │ └── route.js # Blog API endpoint
│ └── blog/
│ ├── page.jsx # Blog listing page
│ └── [slug]/
│ └── page.jsx # Individual blog post page
└── hillnoteDoc/
└── components/
└── blog/ # Blog UI componentsBlog Workflow: Draft → Published
Create a draft: Write your blog post in
public/blog/draft/my-post.mdAdd YAML frontmatter at the top of your markdown file:
--- title: "Your Blog Post Title" author: "Your Name" publishDate: "2025-01-15" description: "A brief description for SEO and previews" coverImage: "my-cover-image.jpg" # or full URL tags: - Tutorial - Feature --- Your blog content starts here...Publish the post: Move the file to
public/blog/published/mv public/blog/draft/my-post.md public/blog/published/Generate the blog:
node scripts/generate-blog.mjs --publish
Blog Commands
# Initial setup - creates blog folder structure and components
node scripts/generate-blog.mjs --setup
# Publish - generates blog pages and updates registry
node scripts/generate-blog.mjs --publish
# Update - regenerates pages after editing posts
# Note: Does NOT update sitemap.xml - run --publish for full regeneration
node scripts/generate-blog.mjs --update
# Help - show all available options
node scripts/generate-blog.mjs --helpAdding Images to Blog Posts
For images in your blog posts:
Place images in
public/blog/resources/images/Reference in frontmatter (for cover images):
coverImage: "my-image.jpg" # Resolves to /blog/resources/images/my-image.jpgOr use a full URL:
coverImage: "https://example.com/image.jpg"Reference in content (for inline images):

Blog Templates
Three pre-built blog templates are available:
- featured-grid - Hero post with grid layout
- minimal-list - Clean, simple list view
- magazine - Publication-style layout
Specify the template during setup or edit the generated page.
Blog Components
BlogSection - Embeddable Homepage Component
Display recent blog posts on your homepage or landing pages:
import { BlogSection } from '@/hillnoteDoc/components/blog'
// Basic usage - shows 3 posts
<BlogSection />
// Customized
<BlogSection
limit={6}
title="Latest Articles"
description="News and updates from our team"
showViewAll={true}
className="bg-muted/50"
/>Props:
limit(number, default: 3) - Number of posts to displaytitle(string) - Section headingdescription(string) - Subheading textshowViewAll(boolean, default: true) - Show "View all posts" linkclassName(string) - Additional CSS classes
Other Blog Components
import {
BlogHeader, // Post header with title, author, date
BlogFooter, // Post footer with tags and sharing
BlogCoverImage, // Responsive cover image
BlogContent, // Markdown content renderer
RelatedArticles, // Related posts section
BlogArticle, // Full article wrapper
BackToBlog // Navigation back to blog list
} from '@/hillnoteDoc/components/blog'Blog API
The blog API is available at /api/blog:
// Get all posts
fetch('/api/blog')
.then(res => res.json())
.then(data => console.log(data.posts))
// Get single post by slug
fetch('/api/blog?slug=my-post-title')
.then(res => res.json())
.then(data => console.log(data.post))Blog Registry
For performance, the blog system generates a blog-registry.json file containing metadata for all posts. This is automatically updated when you run --publish or --update.
🎨 Customization
Styling
The package uses Tailwind CSS. Customize by:
- Edit Tailwind config in
tailwind.config.js - Modify markdown styles in
hillnoteDoc/styles/markdown.css - Customize component styles directly in component files
Navigation Modes
wikimode: Clean accordion-style navigationemojimode: Shows emoji icons from document titles
Set in site.config.js:
ui: {
navigationMode: "wiki" // or "emoji"
}URL Customization
Change the base documentation path:
routing: {
docBase: "docs" // Changes /doc/* to /docs/*
}🚢 Deployment
Vercel (Recommended)
- Push your code to GitHub
- Import project in Vercel
- Vercel automatically detects Next.js and configures build
- Deploy!
Other Platforms
- Netlify: Supports Next.js with adapter
- AWS Amplify: Full Next.js support
- Self-hosted:
npm run build && npm start
Pre-deployment Checklist
- [ ] Update
siteUrlinsite.config.js - [ ] Run
npm run generate-pages - [ ] Test build locally with
npm run build - [ ] Verify all images and assets are in
public/
🔍 SEO Features
- Automatic sitemap generation - Search engines discover all pages
- Structured metadata - Rich snippets in search results
- Open Graph tags - Beautiful social media previews
- AI crawler optimization - llms.txt for AI search engines
- Semantic HTML - Proper heading hierarchy
- Fast page loads - Static generation for optimal performance
📋 Requirements
Dependencies
{
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-checkbox": "^1.1.3",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"gray-matter": "^4.0.3",
"lucide-react": "^0.468.0",
"marked": "^16.1.0",
"marked-gfm-heading-id": "^5.1.0",
"next": "^15.5.2",
"next-themes": "^0.5.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^2.6.0"
}System Requirements
- Node.js 18+
- Next.js 15+
- A Hillnote workspace exported with:
documents/folder with markdown filesdocuments-registry.jsonmetadata file- Optional:
resources/folder for images
🐛 Troubleshooting
Pages not generating?
- Verify workspace folder is in
public/ - Check
documents-registry.jsonexists - Ensure
workspace.pathin config matches folder name
Import errors?
- All imports should use
@/hillnoteDocalias - Check
jsconfig.jsonortsconfig.jsonhas correct paths
Styling issues?
- Clear
.nextcache:rm -rf .next - Rebuild:
npm run dev
API routes not working?
- Ensure API files are in
app/api/(orsrc/app/api/) - Check Next.js console for errors
- Verify
projectStructure.useSrcFoldersetting
📄 License
MIT License - Free to use, modify, and distribute.
🤝 Support
- Issues: Report bugs or request features in your repository
- Documentation: Check the example site in NextJS Boilerplate
- Community: Join the Hillnote community
Built with ❤️ for the Hillnote ecosystem using Next.js, Tailwind CSS, and Radix UI
