Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/howtodo1/printer-web/llms.txt

Use this file to discover all available pages before exploring further.

PenPrint is a React Router v7 SSR application built with Vite. Running it locally or deploying it to a server requires Node.js 20, a handful of npm scripts, and several static assets that must be present in the public/ directory. This page covers everything you need to know before running or building PenPrint outside of Docker.

Node.js version

PenPrint requires Node.js 20. This matches the base image used in the Dockerfile (node:20-alpine) and ensures compatibility with the React Router v7 server runtime and the WebAssembly bindings used for GCODE generation.
Using a Node.js version other than 20 may cause unexpected build or runtime failures. Pin your environment to Node.js 20 using a version manager such as nvm or fnm.

npm scripts

All scripts are defined in package.json and run through the React Router CLI or react-router-serve.
ScriptCommandWhen to use
devreact-router devLocal development with hot module replacement
buildreact-router buildCompile the SSR bundle for production
startreact-router-serve ./build/server/index.jsServe the compiled bundle in production
typecheckreact-router typegen && tscGenerate route types and run TypeScript checks

Development

npm run dev
Starts a local dev server with HMR. Vite handles asset serving, including the WebAssembly files and fonts in public/.

Production build

npm run build
Compiles the React Router SSR bundle using Vite. The output is written to build/ — specifically build/server/index.js for the server entry point.

Production server

npm run start
Starts react-router-serve on port 3000 (the default). Point this at the output of npm run build.

Type checking

npm run typecheck
Runs react-router typegen to generate up-to-date route types, then invokes tsc to check for TypeScript errors. Run this before committing or as part of CI.

Static assets in public/

Vite serves everything in public/ at the root path. PenPrint relies on the following files being present there:

WebAssembly GCODE engine

The GCODE generation engine (penprint) is compiled to WebAssembly. Two files must exist in public/:
FileURL at runtime
public/printthing.mjs/printthing.mjs
public/printthing.wasm/printthing.wasm
Both files are committed to the repository. You do not need to compile or download them separately — they are already in place when you clone the repo.
If either WebAssembly file is missing, GCODE generation and the pen-stroke preview will fail silently or throw a network error in the browser console. Confirm that both files exist in public/ before running the app.

Icons

SVG icons are served from public/icons/ and referenced at runtime as /icons/{name}.svg. The full set of icons used by the app is committed to the repository under public/icons/.

Custom font

The custom display font used by PenPrint is:
FileURL at runtime
public/machtssr-gm.ttf/machtssr-gm.ttf
This file is committed to the repository and requires no additional setup.

Environment variables

PenPrint requires no environment variables to run. The Supabase project URL and anon key used by the “Send to me!” feature are embedded directly in the application source.
This is intentional. The Supabase anon key is a publishable key designed to be exposed in client-side code. It is not a secret. Embedding it in the source avoids the need for runtime environment configuration while keeping the “Send to me!” feature fully functional in any deployment environment.

Next steps

Deploy with Docker

Build and run PenPrint in a production-ready Docker container using the included multi-stage Dockerfile.

Back to home

Return to the PenPrint documentation home page.

Build docs developers (and LLMs) love