public/
Static files the Rust server serves as they are, at the site root and under /public/, before any page renders.
public/
favicon.ico /favicon.ico and /public/favicon.ico
robots.txt /robots.txt and /public/robots.txt
images/hero.webp /images/hero.webp and /public/images/hero.webp
.well-known/security.txt /.well-known/security.txt and /public/.well-known/security.txtReference
Location
The public/ folder next to app/. GIO_PUBLIC_DIR points the server at another directory.
URLs
| URL | What is served | Caching |
|---|---|---|
The site root: public/a/b.png at /a/b.png | Regular files, GET and HEAD only, except dotfiles (other than the top-level .well-known/), symlinks and a top-level public/_gio/ | Cache-Control: public, max-age=0, must-revalidate and Last-Modified |
/public/ + the path: /public/a/b.png | Every file in the folder, dotfiles and symlinks included; a folder URL (/public/docs/) serves that folder's index.html | Last-Modified, no Cache-Control |
Both answer conditional and range requests, with a Content-Type from the file extension, and X-Gio-Cache: static. Neither ever reaches the Node worker or the page cache.
Precedence
- A file at the site root wins over a page or
route.tswith the same path: the server answers before routing. - It also wins over app/sitemap.ts, app/robots.ts and app/manifest.ts, which then never run; startup warns about each.
- Guards, header rules and
[[rate_limits]]written for a file's/public/...URL also apply at its root URL, so protecting/public/members/*restprotects/members/...too.
The root index
Which files answer at the root is decided by an index the server builds at startup, so a request never costs a filesystem lookup. In development, changes under public/ refresh it and reload open browser tabs (the worker does not restart). In production a file added after startup answers under /public/ right away and at the root after the next restart. The index holds up to 100,000 files; any beyond that are served under /public/ only.
Examples
A favicon and a touch icon
import React from 'react';
import type { LayoutProps, Metadata } from '@gio.js/core';
export const metadata: Metadata = {
icons: {
icon: '/favicon.ico',
apple: '/apple-touch-icon.png',
},
};
export default function RootLayout({ children }: LayoutProps) {
return (
<html lang="en">
<head />
<body>{children}</body>
</html>
);
}With public/favicon.ico and public/apple-touch-icon.png in place, browsers that request /favicon.ico without reading the page find it too.
Optimized images from public/
import { GioImage } from '@gio.js/react';
<GioImage src="/images/hero.webp" alt="" width={1200} height={600} priority /><GioImage> resizes files from public/ through /_gio/image; src may be the root URL or the /public/ one.
Good to know
- Everything in
public/is public. Dotfiles are kept off the root, but stay reachable under/public/: never put.envfiles, keys or backups there. - File names carry no content hash, so browsers revalidate root files on every use. For assets that should be cached for a year, reference them from CSS (
url(./bg.png)next to an imported stylesheet is copied with a hashed name) or put a version in the file name. - Directory listings are never served.
public/index.htmldoes not answer/(only/public/and/index.html), so it never competes withapp/page.tsx. gio exportcopies the folder toout/andout/public/, so static hosts serve the same URLs; a file whose output path a rendered page needs is skipped, and the export says so.gio build standaloneships the folder in the deploy directory.- Local
[[fonts]]are read frompublic/(url = "/public/fonts/inter.woff2") and served from/_gio/fonts/under a content-hashed name. - A path with an encoded slash (
%2F) or backslash under/public/is refused with400, and never matches a root file: the rules for/members/*restcould not see it.
Related
- Project Structure: public/
- Middleware: public/ files at the site root
- Deployment: static files
- Images, Fonts
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Files are also served at the site root, ahead of pages, with max-age=0, must-revalidate; dotfiles (except .well-known/), symlinks and public/_gio/ stay off the root. The folder defaults to the one next to app/. Rules for /public/... URLs cover the root URLs. |
v0.1.0-beta.1 | Introduced: files served under /public/. |