This project demonstrates how to integrate TailwindCSS and Shadcn/UI with Docusaurus V3, creating a modern documentation website with beautiful, accessible UI components. Perfect for technical documentation, api docs, blogs, and project websites.
- β‘οΈ Docusaurus V3
- π¨ TailwindCSS for styling (Support v3 and v4)
- π§© Shadcn/UI components
- π
@easyops-cn/docusaurus-search-localfor search functionality - π Support generation API Docs by
@PaloAltoNetworks/docusaurus-openapi-docsplugin - π± Fully responsive design
- π Light/dark mode support
- Modern Component Library: Shadcn/UI integration provides beautiful, accessible components
- Customizable Styling: TailwindCSS enables rapid styling and customization
- Full-Text Search: Local search functionality powered by @easyops-cn/docusaurus-search-local
- Dark Mode: Seamless dark mode support with Docusaurus and Shadcn/UI
- Performance Optimized: Built with performance best practices
The website also features a new blog UI was built using TailwindCSS & Shadcn/UI components and provides a modern, clean interface for displaying blog posts. The blog posts are managed by a custom blog plugin, defined in src/plugins/blog-plugin.js and homepage config in components/Homepage/index.js.
Website has integrated OpenAPI Docs by @PaloAltoNetworks/docusaurus-openapi-docs plugin. You can see the API Docs in API Docs.
- To use this template (docs/blog) with Tailwind v3, switch to the
feature/docusaurus-tailwind-v3branch.
git clone -b feature/docusaurus-tailwind-v3 https://github.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template.git- To use this template (docs, api docs and blog) with Tailwind v3, switch to the
feature/docusaurus-tailwind-v3-openapi-docsbranch.
git clone -b feature/docusaurus-tailwind-v3-openapi-docs https://github.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template.git- To use this template (docs/blog) with Tailwind v4, switch to the
feature/docusaurus-tailwind-v4branch.
git clone -b feature/docusaurus-tailwind-v4 https://github.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template.git- To use this template (docs, api docs and blog) with Tailwind v4, use
mainbranch or switch to thefeature/docusaurus-tailwind-v4-openapi-docsbranch.
git clone -b feature/docusaurus-tailwind-v4-openapi-docs https://github.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template.gitYou can get started by creating your own Docusaurus website and deploy to Vercel by clicking the link:
Vercel will copy the Docusaurus TailwindCSS Shadcn/ui and deploy the website for you. Once completed, every commit in the repo will be deployed automatically.
Go to the platform of your choice and follow the instructions to deploy a new site from a Git repository.
Notice: Use yarn instead of npm for Cloudflare Pages.
Go to the platform of your choice and follow the instructions to deploy a new site from a Git repository.
- Clone the repository:
git clone https://github.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template.git
cd docusaurus-tailwind-shadcn-template- Install dependencies:
yarn install or npm install- Start the development server:
yarn start or npm start- Build for production:
yarn build or npm run build- Serve the production build:
yarn serve or npm run servedocusaurus-tailwind-shadcn-template/
βββ api-swagger/ # API Swagger files - generate API Docs (if using @PaloAltoNetworks/docusaurus-openapi-docs)
βββ blog/
βββ docs/
βββ src/
β βββ components/
β β βββ ui/ # Shadcn/UI components
β βββ css/
β β βββ custom.css # TailwindCSS config and custom styles
β βββ lib/
β β βββ utils.ts # Utility functions
β βββ pages/ # React pages
β βββ plugins/ # Docusaurus plugins
β βββ theme/ # Docusaurus theme customization
βββ static/ # Static assets
βββ tailwind.config.js # TailwindCSS configuration (if using v3, removed in v4)
βββ postcss.config.js # PostCSS configuration
βββ docusaurus.config.js # Docusaurus configurationThe project includes a custom TailwindCSS configuration optimized for Docusaurus:
In v3, you can customize the TailwindCSS configuration in tailwind.config.js.
// tailwind.config.js
module.exports = {
corePlugins: {
preflight: false
},
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./docs/**/*.{js,jsx,ts,tsx}',
'./blog/**/*.{js,jsx,ts,tsx}'
],
darkMode: ['class', '[data-theme="dark"]'] // Support Docusaurus dark mode
// ... rest of the configuration
}In v4, you can customize the TailwindCSS configuration in custom.css. The tailwind.config.js file is removed in v4.
Read more about TailwindCSS v4.
All Shadcn/UI components are located in src/components/ui/. To use a component:
import { Button } from '@/components/ui/button'
function MyComponent() {
return <Button variant='outline'>Click me</Button>
}Note: Because Docusaurus doesn't support CLI installation for Shadcn/UI, you'll need to manually copy the components and adjust the import paths.
This project includes configured path aliases to simplify imports and improve code organization. The aliases are set up in two places:
The jsconfig.json file provides TypeScript-like path mapping for better IDE support and IntelliSense:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@css/*": ["src/css/*"],
"@lib/*": ["src/lib/*"],
"@pages/*": ["src/pages/*"],
"@plugins/*": ["src/plugins/*"],
"@theme/*": ["src/theme/*"]
}
}
}The webpack alias plugin ensures that these paths work at build time:
const path = require('path')
module.exports = function () {
return {
name: 'webpack-alias-plugin',
configureWebpack() {
return {
resolve: {
alias: {
'@': path.resolve(__dirname, '../'),
'@components': path.resolve(__dirname, '../components'),
'@css': path.resolve(__dirname, '../css'),
'@lib': path.resolve(__dirname, '../lib'),
'@pages': path.resolve(__dirname, '../pages'),
'@plugins': path.resolve(__dirname, '../plugins'),
'@theme': path.resolve(__dirname, '../theme')
}
}
}
}
}
}With these aliases, you can use cleaner import statements:
// Instead of relative imports like this:
import { Button } from '../../../components/ui/button'
import { cn } from '../../../lib/utils'
// You can use alias imports:
import { Button } from '@components/ui/button'
import { cn } from '@lib/utils'The local search is configured in docusaurus.config.js:
themes: [
[
require.resolve('@easyops-cn/docusaurus-search-local'),
{
indexPages: true,
docsRouteBasePath: '/docs',
hashed: true,
language: ['en'],
highlightSearchTermsOnTargetPage: false,
searchResultContextMaxLength: 50,
searchResultLimits: 8,
searchBarShortcut: true,
searchBarShortcutHint: true
}
]
],The docusaurus-plugin-openapi-docs package extends the Docusaurus CLI with commands for generating MDX using the OpenAPI specification as the source. The resulting MDX is fully compatible with plugin-content-docs and can be used to render beautiful reference API docs when combined with the docusaurus-theme-openapi-docs theme.
If you don't have docusaurus-plugin-openapi-docs and docusaurus-theme-openapi-docs installed, you can install it by running:
yarn install docusaurus-openapi-docs docusaurus-theme-openapi-docsor
npm install docusaurus-openapi-docs docusaurus-theme-openapi-docsRequired: You must have .yaml files in the api-swagger directory. The plugin will generate API docs based on these files.
Here is an example of properly configuring docusaurus.config.js for docusaurus-plugin-openapi-docs and docusaurus-theme-openapi-docs usage.
// docusaurus.config.js
{
presets: [
[
'classic',
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: './sidebars.js',
docItemComponent: '@theme/ApiItem' // Derived from docusaurus-theme-openapi
},
blog: false,
theme: { customCss: './src/css/custom.css' }
})
]
],
plugins: [
[
'docusaurus-plugin-openapi-docs',
{
id: 'openapi',
docsPluginId: 'classic',
config: {
// if your API spec has multiple versions, you can use the following configuration
petstore_versioned: {
specPath: 'api-swagger/petstore.yaml', // Path to your API spec
outputDir: 'docs/petstore_versioned', // No trailing slash
sidebarOptions: {
groupPathsBy: 'tag',
categoryLinkSource: 'tag'
},
version: '2.0.0', // Current version
label: 'v2.0.0', // Current version label
baseUrl: '/docs/petstore_versioned/swagger-petstore-yaml', // Leading slash is important
downloadUrl:
'https://raw.githubusercontent.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template/main/api-swagger/petstore.yaml',
versions: {
'1.0.0': {
specPath: 'api-swagger/petstore-1.0.0.yaml', // Path to your API spec
outputDir: 'docs/petstore_versioned/1.0.0', // No trailing slash
label: 'v1.0.0',
baseUrl: '/docs/petstore_versioned/1.0.0/swagger-petstore-yaml', // Leading slash is important
downloadUrl:
'https://raw.githubusercontent.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template/main/api-swagger/petstore-1.0.0.yaml'
}
}
}
// if your API spec is a single version, you can use the following configuration
petstore: {
specPath: 'api-swagger/petstore.yaml', // Path to your API spec
outputDir: 'docs/petstore', // No trailing slash
sidebarOptions: { groupPathsBy: 'tag', categoryLinkSource: 'tag' },
downloadUrl: '/petstore.yaml',
hideSendButton: false,
showSchemas: true
}
}
}
],
],
themes: ["docusaurus-theme-openapi-docs"], // export theme components
}Add prism and language support in docusaurus.config.js: see sample code in docusaurus.config.js - themeConfig.
Add scripts to package.json if not exist:
"scripts": {
"gen-api-docs": "docusaurus gen-api-docs",
"clean-api-docs": "docusaurus clean-api-docs",
"gen-api-docs:version": "docusaurus gen-api-docs:version",
"clean-api-docs:version": "docusaurus clean-api-docs:version"
}Generating versioned API docs example (current version):
yarn gen-api-docs <id config>or
npm run gen-api-docs <id config>Generating all Petstore versioned API docs (exclude current version):
yarn gen-api-docs:version petstore:allor
npm run gen-api-docs:version petstore:allCleaning versioned API docs example:
yarn clean-api-docs <id config>or
npm run clean-api-docs <id config>or delete the docs/<id> directory manually.
You can customize the API Docs sidebar by editing the sidebars.js file.
// sidebars.js
import petstoreVersions from './docs/petstore_versioned/versions.json' // import if using multi versioned sidebar
import { versionCrumb, versionSelector } from 'docusaurus-plugin-openapi-docs/lib/sidebars/utils'
import petstoreVersionedSidebar from './docs/petstore_versioned/sidebar' // import when run generate API Docs command
import petstoreVersionSidebar from './docs/petstore_versioned/1.0.0/sidebar' // import when run generate API Docs command
const sidebars = {
// sidebar for docs
'tutorialSidebar': [
'intro',
{
type: 'category',
label: 'Tutorial - Basics',
items: [
'tutorial-basics/create-a-page',
'tutorial-basics/create-a-document',
'tutorial-basics/create-a-blog-post',
'tutorial-basics/markdown-features',
'tutorial-basics/deploy-your-site',
'tutorial-basics/congratulations'
]
},
{
type: 'category',
label: 'Tutorial - Extras',
items: ['tutorial-extras/manage-docs-versions', 'tutorial-extras/translate-your-site']
}
],
// sidebar for api docs
// single versioned sidebar
// 'openApiSidebar': [
// {
// type: 'category',
// label: 'Petstore',
// link: {
// type: 'generated-index',
// title: 'Petstore API',
// description:
// 'This is a sample server Petstore server. You can find out more about Swagger at http://swagger.io or on irc.freenode.net, #swagger. For this sample, you can use the api key special-key to test the authorization filters.',
// slug: '/category/petstore-api'
// },
// items: petstoreVersionedSidebar // import when run generate API Docs command
// }
// ],
// multi versioned sidebar
'petstore-2.0.0': [
{
type: 'html',
defaultStyle: true,
value: versionSelector(petstoreVersions), // import if using multi versioned sidebar
className: 'version-button'
},
{
type: 'html',
defaultStyle: true,
value: versionCrumb(`v2.0.0`)
},
{
type: 'category',
label: 'Petstore',
link: {
type: 'generated-index',
title: 'Petstore API (latest)',
description:
'This is a sample server Petstore server. Generated by @docusaurus-plugin-openapi-docs plugin. Read more: https://github.com/PaloAltoNetworks/docusaurus-openapi-docs',
slug: '/category/petstore-versioned-api'
},
items: petstoreVersionedSidebar // import when run generate API Docs command
}
],
'petstore-1.0.0': [
{
type: 'html',
defaultStyle: true,
value: versionSelector(petstoreVersions), // import if using multi versioned sidebar
className: 'version-button'
},
{
type: 'html',
defaultStyle: true,
value: versionCrumb(`v1.0.0`)
},
{
type: 'category',
label: 'Petstore',
link: {
type: 'generated-index',
title: 'Petstore API (v1.0.0)',
description:
'This is a sample server Petstore server. You can find out more about Swagger at http://swagger.io or on irc.freenode.net, #swagger. For this sample, you can use the api key special-key to test the authorization filters.',
slug: '/category/petstore-api-1.0.0'
},
items: petstoreVersionSidebar // import when run generate API Docs command
}
]
}
export default sidebarsπ Read more config about docusaurus-plugin-openapi-docs
- Modify colors in
tailwind.config.js(v3) orsrc/css/custom.css(v4) - Update CSS variables in
src/css/custom.css - Customize Shadcn/UI components in
src/components/ui/
- Create component in
src/components/ui/orsrc/components/ - Import and use in your pages/docs
Example:
// src/components/ui/custom-button.tsx
import { Button } from '@/components/ui/button'
export function CustomButton({ children }) {
return <Button className='custom-styles'>{children}</Button>
}You can override Docusaurus components by Swizzling. Read more about Component Swizzling.
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
- π Docusaurus Documentation
- π¨ Shadcn/UI Documentation
- π TailwindCSS Documentation
- π OpenAPI Docs
This project is licensed under the MIT License - see the LICENSE file for details.
Built with β₯ by [namnguyenthanhwork]
If you find this project helpful, you can buy me a coffee π
Support this project by becoming a sponsor. Your logo will show up here. π Become a sponsor via Buy me a coffee