Nooxy
Zero dependency Notion proxy (reverse) for custom domains with seamless in-domain navigation for inner Notion pages, complete HTML/CSS/JS and MetaData customization, CLI tools, local development, multi-instance support, and edge performance. Transform Notion pages into professional websites
Install / Use
/learn @draphy/NooxyREADME
Nooxy
<div align="center"> <img src="assets/logo.png" alt="Nooxy Logo" width="140" />Turn Notion into a website. Free. Forever.
The only Notion reverse proxy with full SEO, zero dependencies, and complete customization.
Quick Start · Why Nooxy · Features · Configuration · Examples
</div>The Problem
You built something great in Notion. Now you want to share it with the world on your own domain.
Your options today:
| Solution | Cost | SEO | Customization | Interactivity | |----------|------|-----|---------------|---------------| | Notion Sites | $10-22/mo | Limited, noindex issues | Minimal | Full | | Super.so | $12-28/mo | Good, but subdomain-only hurts rankings | Good | Lost (static) | | Fruition | Free | Poor, outdated | Limited | Full | | Nooxy | Free | Full SEO suite | Complete | Full |
Notion Sites charges $10/month per domain with limited SEO and customization. Super.so costs $12-28/month and converts your pages to static HTML—you lose Notion's live databases, filtering, and real-time updates. Fruition is no longer maintained and lacks modern SEO features.
Nooxy gives you everything. For free.
See It Live
These sites run on Nooxy right now:
- os.draphy.org — Life documented as a file system
- draphy.org — Personal site
View source, check the SEO tags, test the interactivity. It works.
Why Nooxy?
<table> <tr> <td width="50%">What you get
- $0/month — No subscriptions, no limits
- Full SEO — Canonical URLs, structured data, proper indexing
- Complete control — Inject any CSS, JavaScript, HTML
- Live Notion — Real-time databases, filtering, collaboration
- Your domain — Professional URLs like
yourdomain.com/about
What you avoid
- ~~$120-336/year~~ on hosting fees
- ~~Subdomain SEO penalties~~ from free tiers
- ~~Static pages~~ that lose Notion's power
- ~~Vendor lock-in~~ from closed platforms
- ~~Outdated tools~~ that break with Notion updates
Features
SEO That Actually Works
Nooxy rewrites Notion's HTML to give search engines exactly what they need:
- Removes
noindextags — Your pages get indexed by Google - Canonical URLs —
https://yourdomain.com/aboutnot/About-abc123def - Structured data — JSON-LD schema for rich search results
- Open Graph & Twitter Cards — Beautiful social media previews
- Custom meta tags — Title, description, keywords, author per page
- AI attribution — Proper source credits for ChatGPT, Claude, Perplexity
- XML sitemap — Auto-generated at
/sitemap.xml - Robots.txt — Proper crawler directives at
/robots.txt
Complete Customization
- Custom CSS — Override any Notion style, add your brand
- JavaScript injection — Analytics, interactions, custom functionality
- HTML headers — Navigation bars, announcements, CTAs
- Google Fonts — Apply any font family site-wide
- Google Analytics — Built-in GA4 support
Production Ready
- Zero dependencies — Nothing to break, nothing to update
- Edge computing — Runs on Cloudflare Workers' global network
- Node.js support — Works with any modern Node.js runtime (18.17+)
- Multi-tenant — Host multiple sites from one deployment
- Local development — Test locally before deploying
Developer Experience
- TypeScript — Full type safety and IntelliSense
- CLI tools —
npx nooxy initandnpx nooxy generate - Auto-minification — CSS, JS, HTML optimized automatically
- Clean URLs —
/aboutinstead of/About-Page-abc123def456
Quick Start
For detailed deployment guides, see examples.
1. Install
npm install nooxy
2. Initialize
npx nooxy init
This creates a nooxy/ folder with all configuration files.
3. Configure
Edit nooxy/config.js:
export const SITE_CONFIG = {
// Your custom domain
domain: 'yourdomain.com',
// Your Notion workspace (e.g., yourname.notion.site)
notionDomain: 'yourname.notion.site',
// Site name for SEO
siteName: 'Your Site Name',
// Map URLs to Notion page IDs
slugToPage: {
'/': 'YOUR_HOME_PAGE_ID', // yourdomain.com/
'/about': 'YOUR_ABOUT_PAGE_ID', // yourdomain.com/about
'/blog': 'YOUR_BLOG_PAGE_ID', // yourdomain.com/blog
},
// SEO configuration (optional but recommended)
seo: {
indexing: true, // Enable search engine indexing
keywords: 'your, keywords, here',
defaultAuthor: 'Your Name',
},
// Required: Generated files (don't modify)
customHeadCSS: HEAD_CSS_STRING,
customHeadJS: HEAD_JS_STRING,
customBodyJS: BODY_JS_STRING,
customHeader: HEADER_HTML_STRING,
};
4. Generate
npx nooxy generate
5. Deploy
Nooxy works with Cloudflare Workers (recommended) and Node.js.
For complete step-by-step deployment guides, see:
| Platform | Guide | |----------|-------| | Cloudflare Workers | Full Deployment Guide | | Node.js | Coming soon |
Quick reference for Cloudflare Workers:
import { initializeNooxy } from 'nooxy';
import { SITE_CONFIG } from '../nooxy/config';
const proxy = initializeNooxy(SITE_CONFIG);
export default {
async fetch(request: Request): Promise<Response> {
return proxy(request);
},
};
Quick reference for Node.js:
import { initializeNooxy } from 'nooxy';
import { SITE_CONFIG } from './nooxy/config';
import http from 'node:http';
const proxy = initializeNooxy(SITE_CONFIG);
http.createServer(async (req, res) => {
const request = new Request(`http://${req.headers.host}${req.url}`);
const response = await proxy(request);
res.statusCode = response.status;
response.headers.forEach((v, k) => res.setHeader(k, v));
res.end(Buffer.from(await response.arrayBuffer()));
}).listen(8787);
Configuration Reference
Required
| Field | Description |
|-------|-------------|
| domain | Your custom domain (e.g., example.com) |
| notionDomain | Your Notion workspace domain (e.g., yourname.notion.site) |
| siteName | Site name for SEO and social sharing |
| slugToPage | URL path to Notion page ID mapping |
| customHeadCSS | Generated CSS string |
| customHeadJS | Generated head JavaScript string |
| customBodyJS | Generated body JavaScript string |
| customHeader | Generated header HTML string |
SEO Configuration
seo: {
// Enable search engine indexing (default: true)
indexing: true,
// Canonical domain (if different from domain)
// Useful when nooxy runs on subdomain but SEO points to main domain
canonicalDomain: 'example.com',
// Path mapping for canonical URLs
// Maps nooxy paths to canonical domain paths
canonicalPathMap: {
'/': '/home', // os.example.com/ → example.com/home
'/docs': '/documentation',
},
// Meta keywords for SEO
keywords: 'notion, website, custom domain',
// Default author for pages
defaultAuthor: 'Your Name',
// Replace "Notion" branding with custom text
brandReplacement: 'Your Brand',
// AI crawler attribution (ChatGPT, Claude, etc.)
aiAttribution: 'Your Name - yourdomain.com',
}
Page-Specific Metadata
pageMetadata: {
'NOTION_PAGE_ID': {
title: 'Custom Page Title',
description: 'Custom meta description for this page',
image: 'https://yourdomain.com/og-image.jpg',
author: 'Page Author Name',
},
}
Nooxy Configuration
nooxy: {
// Show "Made with Nooxy" badge in header
// Default: true
// Set to false to hide it... 💔 it'll break my heart, but hey,
// if it helps your site look cleaner, I'll survive... probably 😢
showBadge: true,
}
Optional Features
| Field | Description |
|-------|-------------|
| twitterHandle | Twitter/X handle for social cards (e.g., @yourusername) |
| siteIcon | Custom favicon URL |
| googleFont | Google Font family name (e.g., Inter) |
| googleTagID | Google Analytics measurement ID |
| fof | Custom 404 page configuration |
| subDomains | Subdomain redirect rules |
CLI Commands
Initialize Project
npx nooxy init
Creates the nooxy/ directory with all configuration templates.
Generate Files
# Standard generation (with minification)
npx nooxy generate
# Custom path
npx nooxy generate --path=./my-project
# Without minification (for debugging)
npx nooxy generate --no-minify
Converts your custom files to optimized, importable strings.
Customization
Custom CSS (nooxy/head.css)
/* Hide Notion's default elements */
.notion-topbar { display: none !important; }
/* Custom styling */
.notion-page-content {
max-width: 900px;
margin: 0 auto;
font-family: 'Inter', sans-serif;
}
/* Dark mode support */
.dark .notion-page-content {
background: #1a1a1a;
}
Custom JavaScript (nooxy/body.js)
// Analytics, interactions, custom func
