Skip to content

shanefully-done/nosite

Repository files navigation

nosite

A simple way to turn Notion pages into a fast, clean website.

nosite lets you write content in Notion and turn it into static web pages at build time using Next.js.

No live Notion calls, no complicated setup, and no slow page loads.

🔗 Demo: https://nosite.ixtj.dev


What it is

You write your content in Notion.

nosite builds your site from that content and serves it as static pages.

This makes your site:

  • Fast - Content is generated at build time, so pages load instantly
  • Cheap to host - Static files can be hosted anywhere for free or very low cost
  • Easy to reason about - No databases, no servers, no complex infrastructure
  • Stable in production - No live API calls that can break or slow down

It's designed to be approachable, even if you're still learning web development.


Why use it

  • You already like writing in Notion
  • You want a real website, not a no-code platform
  • You don't want to deal with databases or CMS servers
  • You want something you can understand, modify, and deploy yourself

What it gives you

  • Fast pages - Content is generated at build time, so pages load instantly
  • Notion as your editor - Write and edit content in Notion instead of Markdown or custom admin panels
  • SEO-friendly by default - Pages are structured for search engines out of the box
  • Modern tech, but not scary - Built with Next.js, TypeScript, and Tailwind — but you don't need to touch most of it to use the template
  • Looks good on any device - Mobile-friendly layout with light and dark mode

Pages you can have

  • Homepage (/) - Your main landing page (required)
  • Blog (/blog) - Blog post listing and individual posts
  • Gallery (/gallery) - Showcase photos, reviews, or portfolio items
  • Pricing (/pricing) - Display your services and pricing information
  • Contact (/contact) - Contact information and form

You can turn pages on or off by setting a few environment variables.


Typical workflow

  1. Write content in Notion
  2. Run a command to generate the site
  3. Deploy

When you update content, you just rebuild. No live syncing, no surprises.


Who this is for

  • Students learning web development
  • Indie hackers and solo builders
  • People who want a personal site or blog
  • Anyone who wants control without overengineering

Who this is NOT for

  • People who want full Notion feature parity
  • People who expect live syncing with Notion
  • People building interactive or app-like experiences
  • People who want maximum flexibility over clear constraints

Getting Started

Get your website up and running in just 5 minutes!

Prerequisites

  • Bun - JavaScript runtime and package manager
  • Notion account with a workspace
  • Basic familiarity with terminal commands

Installation

  1. Clone the repository

    git clone https://github.com/shanefully-done/nosite.git
    cd nosite
  2. Install dependencies

    bun install
  3. Duplicate the Notion template

    Before setting up environment variables, duplicate the Notion template to your workspace:

    • Visit the nosite template page
    • Click "Duplicate" in the top-right corner to copy it to your Notion workspace
    • This template includes example databases and pages for all supported features
    • You can customize the content after duplicating
  4. Set up environment variables

    cp .env.example .env.local

    Edit .env.local and add:

    NOTION_TOKEN=your_notion_token_here
    HOMEPAGE_NOTION_ID=your_homepage_page_id_here
    NEXT_PUBLIC_SITE_URL=http://localhost:3000
    NEXT_PUBLIC_SITE_NAME=My Website
    NEXT_PUBLIC_SITE_DESCRIPTION=A professional website powered by Notion
  5. Get Notion page IDs

    • After duplicating the template, open the page in your Notion workspace
    • Copy the page ID from the URL (it's the part after /workspace/)
  6. Generate cache

    bun run cache
  7. Start development server

    bun run dev
  8. Open your browser Navigate to http://localhost:3000

That's it! You now have a working website powered by Notion! 🎉


Detailed Setup Guide

Everything you need to know to set up and customize your site.

1. Setting Up Notion Integration

Create a Notion Integration

  1. Go to Notion My Integrations
  2. Click "New integration"
  3. Give it a name (e.g., "My Website")
  4. Select your workspace
  5. Copy the "Internal Integration Token" - this is your NOTION_TOKEN

Share Your Notion Pages with the Integration

Important: Your integration won't be able to access your pages until you explicitly share them.

  1. Open each Notion page you want to use
  2. Click the ••• menu in the top-right
  3. Select "Add connections"
  4. Find and select your integration

2. Understanding Page IDs

Notion page IDs are found in the URL when viewing a page:

https://notion.so/workspace/PAGE_ID?v=...
                        ^^^^^^^^
                        This is your page ID

Copy the 32-character ID (including hyphens) and paste it into your .env.local file.

3. Setting Up Different Pages

Homepage (Required)

The homepage is always required and cannot be disabled.

  1. Create a Notion page with your homepage content
  2. Copy the page ID
  3. Set HOMEPAGE_NOTION_ID in .env.local

Blog Posts

To enable the blog:

  1. Create a Notion database (not a page)
  2. Add these required properties:
    • Title (Title type)
    • Slug (Text type) - URL-friendly identifier for each post
    • Published Date (Date type)
    • Description (Text type)
    • Cover (Files type) - Optional cover image
    • Published (Checkbox type) - Must be checked to appear
  3. Copy the database ID (found in the URL when viewing the database)
  4. Set BLOG_NOTION_ID in .env.local

Gallery

To enable the gallery page:

  1. Create a Notion database for your gallery items
  2. Add properties like:
    • Title (Title type)
    • Image (Files type)
    • Description (Text type)
    • Category (Select type)
  3. Copy the database ID
  4. Set GALLERY_NOTION_ID in .env.local

Pricing and Contact Pages

To enable pricing or contact pages:

  1. Create a Notion page (not a database)
  2. Add your content
  3. Copy the page ID
  4. Set PRICING_NOTION_ID or CONTACT_NOTION_ID in .env.local

4. Configuring Your Site

The main configuration file is src/config/site.config.ts.

You can customize:

  • Site name and description
  • Which pages are enabled
  • Navigation menu labels
  • SEO metadata
  • Social media links

5. Cache Revalidation API (Optional)

The cache revalidation API allows you to automatically trigger cache updates by visiting a special URL. This is particularly useful when combined with GitHub's deployment hooks on platforms like Vercel.

How it works:

  1. When you visit the special API URL with your secret key, it updates a text file in your GitHub repository
  2. This change triggers a new deployment (if you've set up deployment hooks)
  3. The deployment runs the cache update script automatically
  4. Your site rebuilds with fresh content from Notion

Setup Instructions:

  1. Create a GitHub Personal Access Token:

    • Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
    • Generate a new token with repo scope
    • Copy the token - you'll need it for GITHUB_TOKEN
  2. Generate a secure UPDATE_KEY:

    • Create a random, secret string that will be your API key
    • You can generate one using: openssl rand -hex 32 or a password manager
    • Treat this like a password - never share it publicly!
  3. Add environment variables to your deployment:

    # Cache revalidation configuration
    GITHUB_TOKEN=your_github_personal_access_token
    UPDATE_KEY=your_random_secret_key
    GITHUB_OWNER=your_github_username
    GITHUB_REPO=your_repository_name
    GITHUB_UPDATE_FILE_PATH=update.txt
    GITHUB_BRANCH=master
  4. Set up your API URL:

    • Your API endpoint will be: https://yourdomain.com/api/[UPDATE_KEY]
    • Example: https://mysite.com/api/abc123def456...
  5. Using the API:

    Option A: Manual URL visit

    • Simply visit the API URL in your browser
    • The cache will update and trigger a rebuild

    Option B: Add to Notion (Private Pages Only!)

    • Create a button or link in your private Notion workspace
    • ⚠️ CRITICAL: Only add this to PRIVATE Notion pages
    • Never add this link to public pages or share it publicly
    • Example button text: "🔄 Refresh Website Cache"

    Option C: Automate with Webhooks

    • Use tools like Zapier or n8n to trigger the URL on schedules
    • Set up cron jobs to automatically refresh content
    • Integrate with other systems

Security Best Practices:

  • 🔒 Keep UPDATE_KEY secret - Treat it like a password
  • 🔒 Never expose it publicly - Don't commit it to public repos
  • 🔒 Use long, random strings - At least 32 characters recommended
  • 🔒 Only add to private Notion pages - Never to public content
  • 🔒 Rotate keys periodically - Change your UPDATE_KEY regularly
  • 🔒 Monitor deployment logs - Check for unauthorized cache updates

Troubleshooting:

  • If the API returns "Not found", check that UPDATE_KEY matches exactly
  • If you see "Server configuration error", verify all GitHub environment variables are set
  • Check GitHub token has proper repo permissions
  • Ensure the repository branch name matches your setup

6. Updating Content

You can update your content in two ways:

Option A: Manual Cache Update

  1. Update your content in Notion
  2. Run the cache update script:
    bun run cache
  3. Rebuild your site if in production:
    bun run build

Option B: Using the Cache Revalidation API

  1. Update your content in Notion
  2. Visit your API endpoint URL: https://yourdomain.com/api/[UPDATE_KEY]
  3. Wait for the deployment to complete
  4. Your site will automatically rebuild with fresh content

Build and Deployment

Building for Production

# Update cache (including downloading images) and build
bun run build

# Start production server
bun run start

Image Management

Automatic Image Downloading:

When you run bun run build, the build process automatically:

  1. Downloads all images from Notion URLs to public/images/
  2. Generates hash-based filenames (e.g., a3f2c9d1.jpg)
  3. Replaces remote URLs in cached content with local paths
  4. Creates a mapping file in cache/image-mapping.json

This ensures your images are served locally and won't expire.

Manual Image Download:

If you want to download images without rebuilding:

bun run download-images

This will:

  • Scan all cache files for image URLs
  • Download images to public/images/
  • Create/update cache/image-mapping.json

How It Works:

  • Images are downloaded from: *.notion.so, images.unsplash.com, *.amazonaws.com
  • If download fails, the remote URL is used as fallback
  • Hash-based filenames prevent naming conflicts
  • Local images take precedence over remote URLs
  • Build continues even if some images fail to download (with warnings)

Updating Images:

When you change images in Notion:

  1. Run bun run cache (updates content cache)
  2. Images are automatically downloaded and replaced
  3. Rebuild and deploy as usual

Troubleshooting Image Issues:

  • If images don't load: Check cache/image-mapping.json exists and is valid
  • If you see warnings: Some images failed to download (using remote URLs as fallback)
  • To redownload all images: Delete public/images/ directory and run bun run cache again

Deploying to Vercel

  1. Fork this repository
  2. Import your repository
  3. Add environment variables (from your .env.local)
  4. Click "Deploy"

Deploying to Other Platforms

This template works on any platform that supports Next.js:

  • Netlify: Build command bun run build, Publish directory .next
  • AWS Amplify: Next.js preset, Build command bun run build
  • Railway: Build command bun run build, Start command bun run start

Configuration

Image Host Configuration

Important: Next.js only allows images from specified hosts to be displayed on your site. If your images fail to load, you may need to add your image host to the allowed list.

The current allowed image hosts are configured in next.config.ts:

  • *.notion.so - All Notion-hosted images
  • images.unsplash.com - Unsplash stock photos
  • *.amazonaws.com - AWS S3 and CloudFront images

To add a new image host:

  1. Open next.config.ts
  2. Add a new entry to the remotePatterns array:
images: {
	remotePatterns: [
		// ... existing patterns ...
		{
			protocol: "https",
			hostname: "your-image-host.com",  // Add your host here
			port: "",
			pathname: "/**",
		},
	],
},
  1. Restart your development server after making changes

Common image hosts you might need:

  • Cloudinary: *.cloudinary.com
  • Cloudflare Images: *.cloudflareimages.com
  • Imgur: i.imgur.com
  • Custom CDN: Your specific domain

Enable/Disable Pages

Pages are automatically enabled based on whether their Notion ID is set:

  • Homepage: Always enabled (required)
  • Blog: Enabled if BLOG_NOTION_ID is set
  • Gallery: Enabled if GALLERY_NOTION_ID is set
  • Pricing: Enabled if PRICING_NOTION_ID is set
  • Contact: Enabled if CONTACT_NOTION_ID is set

To disable a page, remove or comment out its environment variable.

Environment Variables

Required variables:

  • NOTION_TOKEN - Your Notion API token
  • HOMEPAGE_NOTION_ID - Your homepage page ID
  • NEXT_PUBLIC_SITE_URL - Your website URL

Optional variables (for enabling pages):

  • BLOG_NOTION_ID - Blog posts database ID
  • GALLERY_NOTION_ID - Gallery database ID
  • PRICING_NOTION_ID - Pricing page ID
  • CONTACT_NOTION_ID - Contact page ID

Optional variables (for customization):

  • NEXT_PUBLIC_SITE_LANGUAGE - Language preference for navigation and UI labels
    • "ko-en" (default) - Korean with English fallback
    • "ko" - Korean only
    • "en" - English only

See .env.example for all available options.


Customization

Styling

The template uses Tailwind CSS for styling. You can customize:

  • Global styles: Edit src/app/globals.css
  • Component styles: Each component has its own Tailwind classes

Components

UI components are in src/components/ui/ and are built with Radix UI. You can:

  • Modify existing components
  • Add new components
  • Change component variants

Layout

The main layout is in src/components/layout.tsx. You can customize:

  • Navigation menu
  • Footer content
  • Logo/branding

Troubleshooting

"Content not found" errors

Problem: You see "Content not found" messages on your pages.

Solution:

  1. Make sure you've shared your Notion pages with your integration
  2. Check that your Notion IDs are correct
  3. Run bun run cache to update the cache
  4. Verify the integration token is valid

Cache issues

Problem: Content changes in Notion don't appear on your site.

Solution:

  1. Run bun run cache to rebuild the cache
  2. If in development, restart the dev server
  3. If in production, rebuild and redeploy

Build errors

Problem: The build fails with errors.

Solution:

  1. Check that all required environment variables are set
  2. Verify Notion IDs are correct
  3. Make sure cache files exist (run bun run cache)
  4. Check the error message for specific issues

Navigation not showing pages

Problem: A page is enabled but doesn't appear in navigation.

Solution:

  1. Check the page is enabled in src/config/site.config.ts
  2. Verify the environment variable is set
  3. Check the page file exists in src/app/

License

MIT. Free to use, modify, and ship.

About

A simple way to turn Notion pages into a fast, clean website.

Resources

License

Stars

Watchers

Forks

Contributors