Configurations

Available options.

Main Config

Primary options for your app.

press.config.tsx
import { defineConfig } from "fumapress";

export default defineConfig({
  // ...
});

Site

The site information like name and linked git repository:

press.config.tsx
import { defineConfig } from "fumapress";

export default defineConfig({
  site: {
    name: "Fumapress",
    baseUrl: import.meta.env.DEV ? "http://localhost:3000" : "https://press.fumadocs.dev",
    git: {
      user: "fuma-nama",
      branch: "dev",
      repo: "fumapress",
    },
  },
});

The repository is used for the icon link in navbar, and the link to source file of pages.

Git Providers

git.provider supports github (default), gitlab, and bitbucket, the navbar icon link and source file URLs follow the given provider. For self-hosted instances, pass the instance URL with git.url:

press.config.tsx
import { defineConfig } from "fumapress";

export default defineConfig({
  site: {
    git: {
      provider: "gitlab",
      url: "https://gitlab.example.com",
      user: "fuma-nama",
      branch: "dev",
      repo: "fumapress",
    },
  },
});

Layouts

Specify or customize page UI with renderPage, renderRoot, and renderNotFound.

press.config.tsx
import { createDocsLayoutPage } from "fumapress/layouts/docs";
import { defineConfig } from "fumapress";

const DocsLayout = createDocsLayoutPage<typeof config.$context>();

const config = defineConfig({
  renderPage: (props) => <DocsLayout {...props} />,
});

export default config;

See Layouts for details.

Render Mode

By default, Fumapress build both static & dynamic routes. If you plan to deploy it to a CDN as a static site, you need to specify a render mode.

press.config.tsx
import { defineConfig } from "fumapress";

export default defineConfig({
  // ...
  mode: "static",
});

This will force Fumapress to build all routes as static.

Meta

To add meta tags, you can leverage the meta config.

press.config.tsx
import { defineConfig } from "fumapress";

export default defineConfig({
  meta: {
    root() {
      return (
        <>
          <meta property="og:type" content="website" />
          {/* you can use it for link tags as well */}
          <link rel="preconnect" href="https://fonts.googleapis.com" />
          <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
          <link
            href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap"
            rel="stylesheet"
          />
        </>
      );
    },
    page(page) {
      return <>{/* page-level meta tags */}</>;
    },
  },
});

UI

Tailwind CSS

Create a src/app.css file:

src/app.css
@import "tailwindcss";
@import "fumadocs-ui/css/neutral.css";
@import "fumadocs-ui/css/preset.css";
@import "fumapress/css/preset.css";

It will be automatically loaded, restart the dev server if there's one running.

You can change the color theme or add custom styles, like:

src/app.css
@import "tailwindcss";
@import "fumadocs-ui/css/neutral.css";
@import "fumadocs-ui/css/black.css";
@import "fumadocs-ui/css/preset.css";
@import "fumapress/css/preset.css";

@theme {
  --default-font-family: "Geist", sans-serif;
}

Using Radix UI

Fumapress uses the Base UI headless component library by default, same as Fumadocs. If you are using Radix UI, Fumapress also supports the Radix UI build of Fumadocs UI.

You can enable it by installing fumadocs-ui without the @fumadocs/base-ui alias:

npm i fumadocs-ui
npm uninstall @base-ui/react

Vite Plugin

The press() plugin connects Fumapress to Vite:

vite.config.ts
import { defineConfig } from "vite";
import press from "fumapress/vite";
import { fumadocsMdx } from "fumadocs-mdx/vite";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [press(), fumadocsMdx(), tailwindcss()],
});

It takes the options of the app itself, like the directory layout and deployment target:

Prop

Type

Deployment Adapter

Vercel, Netlify, and Cloudflare are detected from the environment, other targets fall back to waku/adapters/node. Set adapter when the detected one isn't what you deploy to:

vite.config.ts
export default defineConfig({
  plugins: [
    press({
      adapter: "waku/adapters/vercel",
    }),
  ],
});

CLI

The fumapress CLI runs Vite with the environments your app needs, use it instead of calling vite directly.

package.json
{
  "scripts": {
    "dev": "fumapress dev",
    "build": "fumapress build",
    "start": "fumapress start"
  }
}

dev and start accept --host (-h) and --port (-p), the port can also be set with the PORT environment variable. dev listens on port 3000, start picks a free port from 8080.

npm run dev -- --port 4000

Server Entry

The server entry file is optional, you can create one if needed. Useful for implementing custom router.

Custom server entries use Waku.js APIs directly. Since Fumapress manages Waku as its own dependency, install it explicitly for direct API access, matching the version pinned by Fumapress:

npm i waku@1.0.0-beta.9
src/waku.server.tsx
import _adapter from "waku/adapters/default";
// your main config file
import pressConfig from "../press.config";
import { createRouter } from "fumapress/router";
import { fsRouterFn } from "fumapress/router/fs";

const router = await createRouter(pressConfig);

const modules = import.meta.glob("./pages/**/*.{ts,tsx,js,jsx}", {
  base: "/src",
});

// file-system router
const pages = router.createPages(fsRouterFn(modules));
const middlewareFns = router.createMiddlewares();
const adapter = router.patchAdapter(_adapter);

export default adapter(pages, { middlewareFns });

You can also use Waku Config-based Routing instead of the file-system router, see the linked docs for usage.

src/waku.server.tsx
import _adapter from "waku/adapters/default";
// your main config file
import pressConfig from "../press.config";
import { createRouter } from "fumapress/router";

const router = await createRouter(pressConfig);

const pages = router.createPages(async ({ createPage }) => {
  // note: root element is already created by Fumapress
  createPage({
    render: "static",
    path: "/hello-world",
    component() {
      // ...
    },
  });
});

const middlewareFns = router.createMiddlewares();
const adapter = router.patchAdapter(_adapter);

export default adapter(pages, { middlewareFns });

Last updated on

On this page