GioJSdocs
On this page

Installation

Scaffold a new GioJS app in seconds, or add it to an existing project.

System requirements

  • Node.js 20 or newer (22.16 or newer for the database starter feature)
  • Linux x64 (glibc or musl/Alpine), macOS (Intel or Apple Silicon), or Windows x64. Linux arm64 has no prebuilt server binary yet - see Known Limitations.
  • No Rust toolchain: the server binary for your platform is installed from npm

Create a new app

The scaffolder asks a few questions:

npm create giojs@latest
  • Project name - also the folder (default my-giojs-app)
  • Language - TypeScript or JavaScript
  • Server app or Static site - a server app has everything (SSR, caching, route handlers, actions, WebSockets); a static site builds to plain HTML with gio export (see Static Export)
  • Add features - optional starter features: Tailwind CSS, an API route, authentication, a SQLite database, Docker and GitHub Actions CI (a static site is offered the two that work without a server: Tailwind and CI). Add more later with gio add <feature>
  • Install dependencies - with the package manager you ran it with, which is also the one the printed next steps use

It then creates a git repository with a first commit (when git is available and the folder is not already inside a repository). Start the dev server:

cd my-giojs-app
npm run dev        # http://localhost:3000

Edits restart the server's render worker and reload the browser. The dev server also serves the error overlay and the dashboard at /_gio/devtools.

Options

Pass the directory as the first argument and flags after it to skip the questions - anything you pass is not asked. With npm, put the flags after --; pnpm, Yarn and Bun pass them straight through.

npm create giojs@latest my-app -- --ts --server
npm create giojs@latest my-app -- --js --static --no-git
npm create giojs@latest . -- --yes          # current (empty) folder, all defaults
npm create giojs@latest my-app -- --tailwind --features auth,db,docker

npm create giojs@latest -- --help           # every option
FlagEffect
[directory]Where the app goes (. = the current directory); the npm package name comes from its name
--ts / --jsLanguage (default: TypeScript)
--server / --staticServer app (default) or static site (npm run build exports to out/)
--pm <npm|pnpm|yarn|bun>Package manager for the install and the printed next steps (default: the one that ran the command)
--install / --no-installInstall dependencies (default: install)
--git / --no-gitgit init and a first commit (default: on)
-f, --forceScaffold into a directory that is not empty (refused by default)
-y, --yesAccept the defaults for every question not answered by a flag
--tailwind --api --auth --db --docker --ciAdd these starter features instead of asking (a static site takes only --tailwind and --ci)
--features a,b,cThe same, as a list
-h, --help / -v, --versionUsage / the scaffolder's version
  • Directory. A directory name that is not a valid npm package name (My App) gets a sanitized default (my-app) - offered at the prompt, or used directly with a note.
  • Existing files. A directory that is not empty is refused, with a list of what is in it, unless you pass --force (template files then overwrite files of the same name). A fresh clone's .git, README.md and LICENSE, and editor folders, don't count.
  • Git. When git is installed and the directory is not already inside a repository (a monorepo, for example), the scaffold runs git init and commits the files. After --force, the commit holds only what the scaffold created: files that were already in the directory (a .env, say) stay untracked and are listed for you to review. A failed commit - no user.name configured, say - leaves the repository and prints a note; it never fails the scaffold.
  • Scripts and CI. Without a terminal (piped stdin, CI) nothing is asked: every option you did not pass takes its default (no starter features), so a scripted run never hangs. Unknown flags are an error with a did-you-mean hint.
  • Ctrl+C at any question exits without writing anything.

What you get

A small app that uses the framework's own features: file-based routes with a dynamic posts/[id] route (getServerSideProps plus getStaticPaths), the metadata API for titles and descriptions, global CSS imported from app/layout through the CSS pipeline, fonts self-hosted from public/fonts/ with [[fonts]], a .gitignore, an .env.example, and an AGENTS.md for coding agents. See Project Structure.

A static site is the same app with npm run build wired to gio export and its fonts declared with @font-face in app/globals.css, since an export has no server to apply [[fonts]].

Starter recipes

Guides for common additions, explaining what each adds and how to take it further:

Add GioJS to an existing project

Install the packages:

npm install @gio.js/server @gio.js/core @gio.js/react react react-dom cross-env
npm install -D typescript @types/react @types/react-dom @types/node

Add the scripts and an app/ directory with a root layout and a page:

json
{
  "type": "module",
  "scripts": {
    "dev": "cross-env NODE_ENV=development giojs-server",
    "build": "tsc --noEmit",
    "start": "cross-env NODE_ENV=production giojs-server"
  }
}
tsx
// app/layout.tsx
import type { LayoutProps, Metadata } from '@gio.js/core';

export const metadata: Metadata = { title: 'My App' };

export default function RootLayout({ children }: LayoutProps) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
      </head>
      <body>{children}</body>
    </html>
  );
}

// app/page.tsx
export default function Home() {
  return <h1>Hello from GioJS</h1>;
}

A gio.toml is optional - every setting has a production-ready default. For typed routes, add ".gio/routes.d.ts" to the include list of your tsconfig.json (the server writes it at startup), and add .gio/ to .gitignore. Coming from Next.js? npm create giojs@latest -- migrate converts the project - see Migrating from Next.js. Upgrading an app from an earlier GioJS beta? Follow Upgrading.