A type-safe knowledge archive platform that converts Notion content to MDX and deploys as a static Next.js 15 blog
π Live Demo: https://mdx-norkive.vercel.app/
π¦ Repository: https://github.com/ryoonwithinwisdomlights/MdxNorkive
Norkive is a modern knowledge management platform that bridges the gap between Notion's intuitive editing experience and a high-performance static blog. It automatically converts Notion databases into type-safe MDX content, optimizes images through Cloudinary CDN, and deploys as a blazing-fast Next.js application with advanced rendering optimizations.
- π Automated Pipeline: Notion β MDX conversion with full metadata preservation
- πΌοΈ Image Optimization: Cloudinary integration with 70% size reduction
- π¨ MDX Components: Rich interactive components with Shiki syntax highlighting
- π¬ Rich Media Support: YouTube, PDF, Google Drive, Embeds, Bookmarks with custom wrappers
- π Advanced Search: Command palette (
βK) with fuzzy search (Orama) - β‘ Performance: Lighthouse 96/100, < 1s initial load, 89% rendering reduction
- π― Type Safety: Zod schemas + Content Collections for runtime validation
- π React Optimization: Comprehensive memoization with React.memo, useMemo, useCallback
- π± Responsive: Mobile-first design with dark mode support (Zustand)
- π State Management: TanStack Query for server state, Zustand for client state
- π‘οΈ Safe MDX Processing: Advanced link transformation, code block protection, XSS prevention
- Framework: Next.js 15 (App Router), React 19
- Language: TypeScript 5.6 (87.3% of codebase)
- Styling: Tailwind CSS 4.1
- Content: MDX + Content Collections + Fumadocs
- State: TanStack Query (server), Zustand (client)
- Search: Orama (full-text search engine)
- Infrastructure: Vercel, Cloudinary, Upstash Redis
- Quality: ESLint, Prettier, Zod validation
- Node.js >= 20.17.0
- npm/pnpm/yarn
# Clone the repository
git clone https://github.com/ryoonwithinwisdomlights/MdxNorkive.git
cd MdxNorkive
# Install dependencies
npm install
# or
pnpm install
# Set up environment variables
cp .env.example .env.local
# Run development server
npm run devVisit http://localhost:3000
# Notion API (optional - for MDX conversion)
NOTION_API_KEY=your_notion_integration_token
NOTION_DATABASE_ID=your_database_id
# Cloudinary (for image optimization)
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# Upstash Redis (for caching)
UPSTASH_REDIS_REST_URL=your_redis_url
UPSTASH_REDIS_REST_TOKEN=your_redis_token
# Site configuration
NEXT_PUBLIC_SITE_URL=https://your-domain.com
NEXT_PUBLIC_LANG=kr-KRNorkive provides comprehensive support for Notion blocks through custom MDX components and safe content processing.
| Block Type | Component | Status | Description |
|---|---|---|---|
| YouTube | YoutubeWrapper |
β Supported | Lite YouTube embed with lazy loading |
| Video | Native iframe | β Supported | Generic video embeds |
| Audio | Native audio | β Supported | HTML5 audio player |
| Image | Next Image | β Supported | Optimized with Cloudinary |
| File wrapper | β Supported | PDF preview and download | |
| Figma | EmbededWrapper | β Supported | Figma design embeds |
| Google Maps | EmbededWrapper | β Supported | iframe embed |
| Block Type | Component | Status | Extensions |
|---|---|---|---|
| PDF Files | FileWrapper |
β Supported | .pdf |
| Documents | FileWrapper |
β Supported | .doc, .docx, .rtf, .txt, .md, .odt |
| Spreadsheets | FileWrapper |
β Supported | .xls, .xlsx, .key, .numbers |
| Presentations | FileWrapper |
β Supported | .ppt, .pptx |
| Google Drive | GoogleDriveWrapper |
β Supported | Docs, Sheets, Slides |
| Block Type | Component | Status | Features |
|---|---|---|---|
| Bookmark | BookMarkWrapper |
β Supported | Rich link preview with metadata |
| Embed | EmbededWrapper |
β Supported | Generic iframe embeds |
| External Link | Custom component | β Supported | SEO-friendly external links |
| Page Link | Native link | β Supported | Internal page navigation |
| Block Type | Status | Features |
|---|---|---|
| Heading | β Supported | H1-H6 with TOC support |
| Paragraph | β Supported | Rich text formatting |
| Quote / Callout | β Supported | Fumadocs callout components |
| Code Block | β Supported | Shiki syntax highlighting |
| Inline Code | β Supported | Monospace formatting |
| Lists | β Supported | Ordered, unordered, task lists |
| Tables | β Supported | Responsive tables |
| Divider | β Supported | Horizontal rules |
Norkive implements sophisticated MDX transformation pipeline for safe and robust content processing:
# YouTube
[video](https://www.youtube.com/watch?v=xxx) β <YoutubeWrapper />
# Files
[document.pdf](url) β <FileWrapper />
# Google Drive
[My Doc](drive.google.com/...) β <GoogleDriveWrapper />
# Embeds
[embed](url) β <EmbededWrapper />
# Bookmarks
[bookmark](url) β <BookMarkWrapper />- XSS Prevention: Strict HTML tag whitelist
- Code Block Protection: Prevents transformation of code content
- Blockquote Protection: Preserves nested quotes
- Nested Link Fixing: Handles complex link structures
- Invalid HTML Cleaning: Removes unsafe attributes
- Link Detection: Regex pattern matching
- Component Transformation: Markdown β JSX components
- Code Protection: Preserve code blocks and quotes
- Safety Validation: XSS prevention
- Error Handling: Graceful degradation
All media components follow a consistent wrapper pattern:
// YoutubeWrapper.tsx
export default function YoutubeWrapper({ urls, names }: WrapperProps) {
const youtubeId = getYoutubeId(urls);
return <LiteYouTubeEmbed id={youtubeId} />;
}
// FileWrapper.tsx
export default function FileWrapper({ urls, names }: WrapperProps) {
return (
<a href={urls} download>
<FileTextIcon /> {names}
</a>
);
}Key Benefits:
- β¨ Consistent API across all wrappers
- π Type-safe with TypeScript
- π¨ Styled with Tailwind CSS
- βΏ Accessible with ARIA labels
- π± Responsive design
- π Dark mode support
Notion MDX β Link Detection β Component Transform β
Code Protection β Safety Validation β Final MDX
Processing Types:
- Functional Pipeline: Pure functions, pipe composition
- Plugin Architecture: Modular transformation steps
- Class-based: Object-oriented transformer pattern
See content-functional.ts for implementation details.
Option A: Using Notion (Recommended)
- Create content in your Notion database
- Run the conversion script:
npm run generate:mdx
- MDX files are automatically generated in
content/directory
Option B: Direct MDX
Create a file in content/records/my-post.mdx:
---
notionId: "unique-id"
title: "My Post Title"
date: 2025-01-15
category: "Engineering"
tags: ["Next.js", "TypeScript"]
---
# Your content here
This is a paragraph with **bold** and *italic* text.
\`\`\`typescript
const example = "code block";
\`\`\`npm run dev # Start development server
npm run build # Production build
npm start # Start production server
npm run lint # Run ESLint
npm run validate:mdx # Validate MDX files
npm run prettier:write # Format code
npm run analyze # Analyze bundle size
npm run check:validity # Run validity checks and tests- π Architecture - System design, data flow, and technical decisions
- π Migration Guide - react-notion-x β MDX migration story
- β‘ Performance - Optimization strategies and benchmarks
- π οΈ Development - Local setup and development guide
- π€ Contributing - How to contribute to this project
- π Memoization Guide - React rendering optimization
norkive/
βββ app/ # Next.js App Router
β βββ (home)/ # Home page
β βββ api/ # API routes
β βββ book/ # Book category
β βββ engineering/ # Engineering posts
β βββ project/ # Project showcase
β βββ records/ # Personal records
βββ content/ # MDX content files
β βββ books/
β βββ engineerings/
β βββ projects/
β βββ records/
βββ lib/ # Utilities & libraries
β βββ cache/ # Caching system
β βββ context/ # React contexts
β βββ hooks/ # Custom hooks
β βββ stores/ # Zustand stores
β βββ utils/ # Helper functions
βββ modules/ # UI components
β βββ common/ # Shared components
β βββ layout/ # Layout components
β βββ mdx/ # MDX components
β βββ page/ # Page components (memoized)
βββ scripts/ # Build & conversion scripts
βββ types/ # TypeScript definitions
Performance: 96/100 β‘
Accessibility: 98/100 βΏ
Best Practices: 100/100 β
SEO: 100/100 π
| Metric | Score | Target | Status |
|---|---|---|---|
| LCP | 1.2s | < 2.5s | β |
| FID | 12ms | < 100ms | β |
| CLS | 0.02 | < 0.1 | β |
- React.memo: Applied to 6+ list item components
- useMemo: Complex calculations and filtering cached
- useCallback: Event handlers stabilized
- Result: 89% reduction in unnecessary re-renders
See PERFORMANCE.md for detailed optimization strategies.
- Performance: Static generation vs. runtime API calls (60% faster)
- SEO: Complete HTML for crawlers (100% indexing)
- Customization: Full control over React components
- Reliability: No dependency on Notion API availability
- TanStack Query: Automatic caching, revalidation, and server state management
- Zustand: Simple, performant client state (replaces complex Context)
- Separation of Concerns: Server state vs client state
- Large Lists: 100+ items in records list
- Complex Filtering: Multi-criteria filtering and sorting
- Performance Goal: <100ms interaction response time
- Result: 89% rendering reduction achieved
See ARCHITECTURE.md for detailed analysis.
| Metric | Before (react-notion-x) | After (MDX) | Improvement |
|---|---|---|---|
| Initial Load | 2.5s | 1.0s | β 60% |
| Bundle Size | 2.3MB | 890KB | β 61% |
| Build Time | 3m+ | 45s | β 75% |
| Lighthouse | 60 | 96 | β 60% |
| Component Renders | 112 | 12 | β 89% |
| Component | Before | After | Improvement |
|---|---|---|---|
| DateSortedRecords | 100 renders | 10 renders | β 90% |
| LatestRecords | 3 renders | 1 render | β 67% |
| FeaturedRecords | Optimized | Optimized | β |
| EntireRecords | Optimized | Optimized | β |
- Service Worker & PWA support
- React memoization optimization
- RSS/Atom feeds
- Comment system (Giscus)
- Full i18n support (Korean/English)
- Web-based MDX editor
- Analytics dashboard
- Advanced search filters
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Run tests:
npm run check:validity - Commit:
git commit -m 'feat: add new feature' - Push:
git push origin feature/my-feature - Open a Pull Request
This project is licensed under the MIT License.
Ryoon with Wisdom Lights
- Email: [email protected]
- GitHub: @ryoonwithinwisdomlights
This project includes reusable packages published to npm:
MDX UI components for rendering content in browsers. Includes YouTube embeds, file links, bookmarks, Google Drive links, and embedded content.
npm install @norkive/mdx-uiimport { getYoutubeId, LiteYouTubeEmbed, YoutubeWrapper } from '@norkive/mdx-ui';
import '@norkive/mdx-ui/styles.css';
const id = getYoutubeId('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
// 'dQw4w9WgXcQ'Features:
- β YouTube embeds with lazy loading
- β File, Google Drive, Bookmark wrappers
- β YouTube URL utilities
- β TypeScript Support
- β Zero dependencies (peer dependencies only)
π Full Documentation
Note:
@norkive/youtube-utilsand@norkive/lite-youtube-embedhave been merged into@norkive/mdx-ui. See migration guide.
@norkive/mdx-safe-processor- Safe MDX content processor@norkive/mdx-validator- MDX file validator@norkive/image-optimizer- Image optimization utilities
See packages-guide for more information.
Built with these amazing open-source projects:
- Next.js - React framework
- Fumadocs - Documentation system
- Radix UI - Headless UI components
- Tailwind CSS - CSS framework
- TanStack Query - Server state management
- Zustand - Client state management
- Vercel - Hosting platform
β If you find this project helpful, please consider giving it a star!
Made with β€οΈ by Ryoon with Wisdom Lights

