Skip to main content
While building your own custom functionality into FrogBot, like Plugins, Hooks, Access Control functions, custom views, GraphQL queries or mutations, or anything else, you may benefit from generating your own TypeScript types dynamically from your FrogBot Config itself.

Types generation script

Run the following command in a FrogBot project to generate types based on your FrogBot Config:
You can run this command whenever you need to regenerate your types. The single generated frogbot-types.ts file augments FrogBot with generated collection and agent types.

Type generation options

Configure type generation with the root typescript option.

The declare block

The generated file ends with a declare module 'frogbot' block that registers your collection, agent, model, and role types with FrogBot. FrogBot always writes this block. If you copy frogbot-types.ts into a project that doesn’t install frogbot, the block reports an error there. Install frogbot as a dev dependency of that project, as described in Using your types.

Custom output file path

You can specify where you want your types to be generated by adding a property to your FrogBot Config:
The above example places your types next to your FrogBot Config itself as the file generated-types.ts.

Custom generated types

FrogBot generates your types based on a JSON schema. You can extend that JSON schema, and thus the generated types, by passing a function to typescript.schema:
This function takes the existing JSON schema as an argument and returns the modified JSON schema. It can be useful for plugins that wish to generate their own types.

External schema references

You can use $ref to reference external JSON schema files in your custom schemas:
External references are resolved relative to your project’s working directory (process.cwd()).

Example Usage

For example, let’s look at the following simple FrogBot Config:
By generating types, we’ll end up with a file containing the following two TypeScript interfaces:

Custom Field Interfaces

array, group and named tab fields generate a top-level interface only when you set interfaceName on them. block fields always generate a top-level interface — interfaceName on a block is an override of the auto-derived name (which is a PascalCase form of the slug: 'content-block' → ContentBlock). The following group field config:
will generate:
Naming CollisionsSince these types are hoisted to the top level, you need to be aware that naming collisions can occur. For example, if you have a collection with the name of Meta and you also create a interface with the name Meta they will collide. It is recommended to scope your interfaces by appending the field type to the end, i.e. MetaGroup or similar.

Block interface name collisions

Every block generates a top-level interface named after its slug ('hero' → Hero). If two different blocks resolve to the same name but have different fields — for example a hero block reused across collections but overridden in one of them — a single shared Hero interface couldn’t represent both shapes. The first block keeps the clean name; any later block with a different shape gets a short content-hash suffix, so neither is silently mistyped:
The suffix is derived from the block’s fields, so the same schema always produces the same name across regenerations — it only changes when the block’s fields change. If you import a hashed interface and later change that block, you’ll get a type error that points you at the change instead of silently receiving the wrong shape. To choose the name yourself and avoid the hash, set an explicit interfaceName on the block. Explicit names are always used verbatim. This is the recommended fix when two blocks intentionally share a slug, or when you want a stable, human-readable name to import.

Using your types

Now that your types have been generated, FrogBot’s Local API will now be typed. It is common for users to want to use this in their frontend code, we recommend generating them with FrogBot and then copying the file over to your frontend codebase. This is the simplest way to get your types into your frontend codebase. The generated file refers to types from frogbot, so install frogbot as a dev dependency of the frontend (pnpm add -D frogbot) and set skipLibCheck: true in its tsconfig.json. frogbot is only used for types and isn’t bundled. With the file in place, the FrogBot REST API SDK is typed from it automatically.

Typing the current user

Once your types are generated, req.user is typed as your generated user, or null when no one is signed in. This applies in access control, hooks, endpoints, tools, and every other place that receives req, with no cast. For example, if your users collection has a role field:
With more than one auth collection, req.user is a union of their generated types. Check collection to narrow it:
Use TypedUser to type your own helpers:
Outside a FrogBot request, such as in server components, route handlers, and server actions, frogbot.auth() returns the same type:
frogbot.createRequest({ user }) expects a full user. Passing an object with only some fields, such as { id: 1 }, is a type error. Pass the user returned by frogbot.auth() or read from the Local API instead. Before you generate types, req.user is an object with an id and unknown fields. Keep skipLibCheck: true in your tsconfig.json, as FrogBot’s templates do. Prebuilt pieces ship declaration files built without your generated types, so skipLibCheck: false reports errors inside those files that don’t affect your code.

Adding an npm script

ImportantFrogBot needs to be able to find your config to generate your types.
FrogBot will automatically try and locate your config, but might not always be able to find it. For example, if you are working in a /src directory or similar, you need to tell FrogBot where to find your config manually by using an environment variable. If this applies to you, you can create an npm script to make generating your types easier. To add an npm script to generate your types and show FrogBot where to find your config, open your package.json and update the scripts property to the following:
Now you can run pnpm generate:types to easily generate your types.