mdx-blog-ui
v0.1.0
Published
Copy-paste blog UI templates for Next.js + mdx-blog-core, installed via CLI.
Readme
mdx-blog-ui
Copy-paste blog UI for Next.js (App Router) apps that use mdx-blog-core for data and types.
This package ships a small CLI that copies TypeScript/React source files into your repository (similar to the outcome of shadcn/ui, but without a hosted shadcn registry). After running add, you own the code and can change styles, props, and behaviour freely.
What you get
- Post list, card, URL-based search (
?q=), keyboard prev/next, share menu, inline TOC (collapsible). - Imports
mdx-blog-coreforPost,useFilteredPosts,TOCItemType, etc. - Imports your UI primitives at paths aligned with
components.json(shadcn-style aliases).
This package does not load MDX or read the filesystem. Use mdx-blog-core (createBlogSource, etc.) for that.
Requirements
- Node.js 20+
- Next.js 14+ (App Router), React 18+
- Tailwind CSS (templates use utility classes)
mdx-blog-coreinstalled in the same appcomponents.json(recommended) so the CLI can rewrite@/lib/utils,@/components/ui/..., and@/hooks/...to match your aliases
Install
npm install mdx-blog-ui mdx-blog-core
# or
pnpm add mdx-blog-ui mdx-blog-core
# or
yarn add mdx-blog-ui mdx-blog-corePeer dependencies (mdx-blog-ui)
These are declared on the package; your app should satisfy them:
| Package | Range | Notes |
| ----------------- | ------- | ------------------------------------------ |
| mdx-blog-core | ≥0.1.0 | Types, useFilteredPosts, TOC types |
| next | ≥14 | Image, Link, useRouter where used |
| react | ≥18 | |
| react-dom | ≥18 | |
Additional dependencies (per feature)
The CLI prints hints after each add. Typical installs:
| You use | Also install (examples) |
| ------------------------------- | ------------------------------------------------------------ |
| post-item | date-fns |
| use-search-query, search list | nuqs |
| post-search-input | nuqs, lucide-react, react-hotkeys-hook |
| post-keyboard-shortcuts | react-hotkeys-hook |
| post-share-menu | lucide-react, sonner |
| inline-toc | lucide-react |
Add the shadcn/ui (or compatible) primitives the templates import:
- Button, Input —
post-search-input - Button, DropdownMenu —
post-share-menu - Collapsible —
inline-toc
nuqs in the App Router
Search components use useQueryState from nuqs. Wrap your app (or the blog layout) with the Next.js adapter, for example:
import { NuqsAdapter } from "nuqs/adapters/next/app"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<NuqsAdapter>{children}</NuqsAdapter>
</body>
</html>
)
}See the nuqs Next.js docs for details.
CLI
Run from your Next.js project root (where components.json and package.json live).
npx mdx-blog-ui list
npx mdx-blog-ui add <component> [--dir <path>] [--cwd <path>]| Command | Description |
| ------- | ----------- |
| list | Print all component ids you can add. |
| add | Copy the component and its dependencies into your tree. |
| Option | Description |
| ------- | ----------- |
| --dir | Output directory relative to cwd (default: components/mdx-blog). |
| --cwd | Project root (default: current working directory). |
Examples
npx mdx-blog-ui add post-list-with-search
npx mdx-blog-ui add post-search-input --dir src/components/mdx-blog
npx mdx-blog-ui add inline-toc --dir src/components/blog --cwd .Import path rewriting
If components.json exists and defines aliases (e.g. utils, ui, hooks), the CLI rewrites:
@/lib/utils→ youraliases.utils@/components/ui/...→ under youraliases.ui@/hooks/...→ under youraliases.hooks
If the file is missing, defaults match a typical shadcn layout (@/components, @/lib/utils, @/components/ui, @/hooks).
Available components
| Id | Purpose |
| -- | ------- |
| post-item | Post card: image, title, date, optional “new” dot. Props include basePath (default "/blog") for post links. |
| post-list | Two-column grid + empty state; passes basePath to each item. |
| use-search-query | Hook: nuqs state for the q search param. |
| post-list-with-search | Client list filtered with useFilteredPosts from mdx-blog-core/react. |
| post-search-input | Search field + clear; optional onQueryChange (debounced) for analytics. |
| post-keyboard-shortcuts | Left/Right arrow prev/next using next/navigation. |
| post-share-menu | Copy link, X / LinkedIn intents, Web Share API when available; sonner toasts. |
| inline-toc | Collapsible on-page TOC from TOCItemType[] (from mdx-blog-core / getTableOfContents). |
Transitive files are included automatically (e.g. add post-list-with-search also copies post-list, post-item, and hooks/use-search-query.ts).
Integration sketch
- Install
mdx-blog-core,mdx-blog-ui, and peers (see above). - Add shadcn button, input, dropdown-menu, collapsible if you do not have them.
- Ensure
NuqsAdapterwraps routes that use search. - Run
npx mdx-blog-ui add …into e.g.src/components/mdx-blog. - In a Server Component, load posts with
createBlogSourcefrommdx-blog-core/nodeand pass them into client components as needed. - Style and tweak the copied files to match your site.
Monorepo (this workspace)
{
"devDependencies": {
"mdx-blog-ui": "workspace:*"
}
}Template sources live in packages/mdx-blog-ui/templates/. To refresh a consumer app after editing templates, run add again with the same --dir or merge manually.
Publishing to npm (maintainers)
Ensure
package.json"files"includes everything needed on the registry:bin/,templates/,manifest.json
Version with semver, then publish:
npm publish --access publicPublishing requires npm 2FA or a token allowed to publish (see npm’s docs if you see
403onPUT).
License
MIT
