Skip to main content
Need support for an internal framework or a tool fallow doesn’t cover yet? Create an external plugin file. No Rust code required. Plugins are declarative JSON/TOML files that teach fallow about your framework’s conventions.
Start with JSONC format for $schema support and IDE autocomplete.

Quick start

1

Create the plugin file

Create a fallow-plugin-<name>.jsonc file in your project root:
{
  "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/plugin-schema.json",
  "name": "my-framework",
  "enablers": ["my-framework"],
  "entryPoints": ["src/routes/**/*.{ts,tsx}"],
  "alwaysUsed": ["src/setup.ts"],
  "toolingDependencies": ["my-framework-cli"],
  "usedExports": [
    { "pattern": "src/routes/**/*.{ts,tsx}", "exports": ["default", "loader", "action"] }
  ]
}
Fallow auto-discovers fallow-plugin-* files in your project root.
2

Configure the fields

Customize the plugin fields for your framework. Only name is required. Add the fields relevant to your use case.

Required

FieldTypeDescription
namestringUnique plugin name (shown in fallow list --plugins)

Optional

FieldTypeDescription
enablersstring[]Package names that activate this plugin
entryPointsstring[]Glob patterns for entry point files
configPatternsstring[]Glob patterns for config files (always-used)
alwaysUsedstring[]Files always considered used
toolingDependenciesstring[]Packages used via CLI, not imports
detectionobjectRich activation logic (see below)
usedExportsobject[]Exports always considered used
3

Verify the plugin

Confirm fallow picks up your plugin:
fallow list --plugins

Supported formats

FormatExtensionComments
JSONC.jsonc// and /* */
JSON.jsonNo
TOML.toml#

Detection strategies

Plugins can use simple enablers or rich detection logic with boolean combinators.
The simplest way to activate a plugin. Package names are checked against package.json. The plugin activates if any enabler matches:
{
  "enablers": ["my-framework", "@myorg/"]  // prefix matching with trailing /
}
A trailing / enables prefix matching, so @myorg/ matches any package in the @myorg scope.
Activate a plugin when specific config files exist in the project:
{
  "detection": { "type": "fileExists", "pattern": "nuxt.config.*" }
}
Combine multiple conditions with all (AND), any (OR), or not:
{
  "detection": {
    "type": "all",
    "conditions": [
      { "type": "dependency", "package": "@my-org/core" },
      { "type": "fileExists", "pattern": "my-org.config.*" }
    ]
  }
}
This plugin only activates when both @my-org/core is installed and a my-org.config.* file exists.

Used exports

Mark specific exports as always-used for convention-based frameworks where exports are consumed by name at runtime:
{
  "usedExports": [
    { "pattern": "src/routes/**/*.{ts,tsx}", "exports": ["default", "loader", "action", "meta"] }
  ]
}

Discovery order

Fallow searches for plugin files in this order:
  1. Explicit paths from the plugins config field
  2. .fallow/plugins/ directory
  3. Project root: fallow-plugin-*.{jsonc,json,toml} files

Using the plugins config field

// .fallowrc.json
{
  "plugins": [
    "tools/fallow-plugins/",
    "vendor/my-plugin.jsonc"
  ]
}

Examples

React Router

{
  "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/plugin-schema.json",
  "name": "react-router",
  "enablers": ["react-router", "@tanstack/react-router"],
  "entryPoints": ["src/routes/**/*.{ts,tsx}", "app/routes/**/*.{ts,tsx}"],
  "configPatterns": ["react-router.config.{ts,js}"],
  "toolingDependencies": ["@react-router/dev"],
  "usedExports": [
    { "pattern": "{src,app}/routes/**/*.{ts,tsx}", "exports": ["default", "loader", "action", "meta", "handle", "shouldRevalidate"] }
  ]
}

Internal tooling

{
  "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/plugin-schema.json",
  "name": "our-build-system",
  "enablers": ["@internal/build"],
  "configPatterns": ["build.config.{ts,js}", ".buildrc"],
  "alwaysUsed": ["scripts/build/**/*.ts", "config/**/*.ts"],
  "toolingDependencies": ["@internal/build", "@internal/lint-rules"]
}
External plugins cover the vast majority of use cases. AST-based config parsing (like the built-in ESLint or Vite plugins do) requires a built-in Rust plugin.

JSON Schema

Generate the schema locally for IDE autocomplete:
fallow plugin-schema > plugin-schema.json
Reference it in your plugin file:
{
  "$schema": "./plugin-schema.json"
}

See also

Built-in plugins

Browse the 84 built-in framework plugins.

fallow list

Verify active plugins and inspect project metadata.