---
title: "Pitlane"
description: "Pitlane gives you composable packages to help you put your Remix app on the grid."
url: "https://pitlane.tools/"
---

# Pitlane

Start with [Pitlane guides](https://pitlane.tools/guides.md).

## Packages

### @pitlane/vite-plugin-remix: Build & develop

Development, server, and browser builds, all in one Vite plugin.

```ts title="vite.config.ts"
import { remix } from "pitlane/vite-plugin-remix";
import { defineConfig } from "vite";

export default defineConfig({
    plugins: [remix()],
});
```

Guide: [Using the Vite plugin](https://pitlane.tools/guides/vite-plugin.md) · Reference: [@pitlane/vite-plugin-remix](https://pitlane.tools/package/vite-plugin-remix/index.md)

### @pitlane/content: Load & validate

Your files become typed, queryable collections.

```ts title="app/content.ts"
import { createContent } from "pitlane/content";
import * as loaders from "pitlane/content/loaders";
import * as s from "remix/data-schema";

export let content = createContent(c => ({
    posts: c.collection({
        loader: loaders.glob({
            base: "app/posts",
            pattern: "**/*.md",
        }),
        schema: s.object({ title: s.string() }),
    }),
}));
```

Guide: [Content](https://pitlane.tools/guides/content.md) · Reference: [@pitlane/content](https://pitlane.tools/package/content/index.md)

### @pitlane/theme: Style & compose

Typed design tokens. Native Remix styling.

```ts title="app/theme.ts"
import { createTheme } from "pitlane/theme";
import * as s from "pitlane/theme/schema";

export let { token: t, Theme } = createTheme({
    schema: {
        color: s.color(),
        spacing: s.scale(),
    },
    tokens: {
        color: { brand: "#eb2027" },
        spacing: "0.25rem",
    },
});
```

Guide: [Theme](https://pitlane.tools/guides/theme.md) · Reference: [@pitlane/theme](https://pitlane.tools/package/theme/index.md)

### @pitlane/crawler: Crawl & prerender

Follow your app’s links without starting an HTTP server.

```ts title="scripts/crawl.ts"
import { crawl } from "pitlane/crawler";
import router from "../app/entry.server.ts";

for await (let { pathname, response } of crawl(router)) {
    console.log(pathname, response.status);
}
```

Guide: [Crawler](https://pitlane.tools/guides/crawler.md) · Reference: [@pitlane/crawler](https://pitlane.tools/package/crawler/index.md)

### @pitlane/data-table-d1: Connect your data

Remix’s database API, backed by your Cloudflare D1 binding.

```ts title="app/database.ts"
import { createD1Database } from "pitlane/data-table-d1";
import { env } from "cloudflare:workers";

export let db = createD1Database(env.DB);
```

Guide: [Cloudflare D1](https://pitlane.tools/guides/cloudflare-d1.md) · Reference: [@pitlane/data-table-d1](https://pitlane.tools/package/data-table-d1/index.md)

## Deployment

- [Cloudflare](https://pitlane.tools/deploy/cloudflare.md): workerd
- [Netlify](https://pitlane.tools/deploy/netlify.md): Node.js
- [Vercel](https://pitlane.tools/deploy/vercel.md): Node.js
- [Railway](https://pitlane.tools/deploy/railway.md): Node.js, Bun, or Deno
- [Deno Deploy](https://pitlane.tools/deploy/deno-deploy.md): Deno
- [GitHub Pages](https://pitlane.tools/deploy/github-pages.md): Browser

## Start from a template

```sh
vpx giget github:pitlane-tools/templates/cloudflare my-app
```
