Yash's Site

Get Started

Introduction

yash101

Published 1/30/2025

Updated 1/30/2025

#

🍝 What is Béchamel?

Built on a roux, a Béchamel is a basic unflavored French sauce which can be used as the base for a different dish.

This project is an under-development static-site-generator which uses React via Next.js to help you think less about coding and focus on writing instead. Articles are written in Jupyter notebooks, which serves as an IDE for your articles, providing a WYSIWYG editing experience.

And the best part is that since Jupyter notebooks were meant to meld together writing and code together, this static site generator makes for the perfect platform to write technical articles!

#

✨ Key Features of Béchamel

  • Cost-Effective: Deploy to S3 or any static hosting for pennies
  • Interactive Development: Full Jupyter/JupyterLab interface support
  • Lightning Fast: Most content is static-site generated (SSG), so serve it off a CDN and achieve blazing fast performance!
  • Simple Workflow: Just write notebooks, commit, and deploy
  • Embeds: Strong embeds so you can add a ton of interactability into your pages
  • React-based: Create custom components, embeds and so much more without adding a ton of complexity or performance impact

Oh, and did I say performance? Most content, especially all your markdown content and code blocks are statically rendered using server components only!

JupyNext
a static site generator based around Jupyter notebooks.

When creating a website or a blog, it is often beneficial to have a CMS (content management system) to host the content and keep it separate from the design. However, content management systems pose a huge tradeoff which needs to be made:

pros:

  • Absolutely no backend
  • Statically export and deploy to CDN
  • Create your own embeds and components using React
  • WYSIWYG editor when you use Jupyter notebooks (JupyterLab or Jupyter Notebook (legacy))

cons:

  • Lack of features, primarily due to the lack of maturity in this project
  • JupyNext’s markdown renderer is different from Jupyter’s renderer leading to some inconsistencies

JupyNext is a website and blog platform which uses Jupyter notebooks as the writing medium.

#

Some Goals

#

Ease-of-use

My goal when building this SSG platform was spend less time coding and more time writing content.

#

Prerendering

Basic content (markdown, images, even code snippets, code cells and their outputs) are fully statically rendered. Your users will have a quick and snappy experience using your website, even if they have JavaScript disabled!

#

Quickstart

#

Install

git clone [email protected]:yash101/jupyter-next-site-platform.git
cd jupyter-next-site-platform
npm install --force # Some dependency issues since some deps don't fully support React 19

npm run prebuild # builds your notebooks and contents into static files which are rendered by the Next.js app
npm run dev # Runs Next.js in dev mode
#

Your first notebook

  • First cell in each notebook - metadata:

    Note: the format can be either TOML or JSON.

    root = 'some-base-url'
    name = 'some-article'
    title = 'Some Article'
    subtitle = 'Page one of Some Article'
    page = 1
    isPublished = true
    authors = 'yash101'
    
    lastModifiedOn = '2025-02-07T20:56:17.277Z'
    publishedOn = '2025-02-07T00:00:00.277Z'
    
  • Second cell:

    If the notebook is for the first page of an article, the second cell will be used as the hero content for the article, displayed in a blog view if that is enabled for the root.

  • Content: the rest of the cells of your notebook are for your content!

#

_site-structure.json - How the Sidebar / Menu Behaves

{
  "roots": {
    "pages": {
      "menuTitle": "Pages",
      "rootType": "Pages",
      "displayArticlesInMenu": true,
      "pageTitle": "Pages",
      "linkInMenu": false
    },
    "deep-dive": {
      "linkInMenu": true,
      "menuTitle": "Deep Dives",
      "rootType": "Blog",
      "displayArticlesInMenu": true,
      "pageTitle": "Deep Dives by Yash"
    }
  }
}
  • Each root is a base in the URL of the website.

    • Example, articles in the root pages would be /pages/{article_name}/{page_number}
    • Example, articles in the root deep-dives would be /deep-dives/{article_name}/{page_number}
  • linkInMenu: whether to link the root to /{root}

  • menuTitle: Title to display in the Menu

  • rootType: Blog OR Pages

    • Blog: display a blog view at /{root} showing the articles, their hero section, and a list of the pages
    • Pages: currently implemented as a 404 error
  • displayArticlesInMenu: whether to list articles under the root in the sidebar or menu

**The _site-structure.json should be placed in the root of the /notebooks directory.

Behavior in the future may have more site configuration in here.

#

Update Site Configuration

Update /src/site-config.ts with your site title and any other settings.

#

Deploying

#

Static export

  1. Install Node v22.13.0 or later
  2. Run ./ci.sh or npm run ci-build to build and export the website
  3. Deploy /out to your host of choice
  4. Redirect URLs without an extension (such as .html) to .html. This should be the default setting with most hosts.
#

Vercel/Netlify: Connect your repository for automatic deployments

Note: I haven’t tested this. If you do, please PR an update to this documentation with the steps you took!

#

Cloudflare Pages

  • Use the following configuration:
    • Build command: npm run ci-build
    • Build output: out
    • Environment variables:
      • NODE_VERSION is v22.13.0
      • SKIP_DEPENDENCY_INSTALL is 1 since some of the dependencies used “don’t support” React 19.