Configuration
There are multiple way to configure Frogger. You can use the frogger key in your nuxt.config.ts file to adjust module options. You can create a separate frogger.config.ts configuration file in the root of your project, or you can use environment variables and runtime configuration to override settings in different environments.
Hierarchy
frogger.config.ts will always override nuxt.config.ts. Runtime config and env variables will always override both.
Module Options
The most common way to configure Frogger will be through it's module options. Use the frogger configuration key in your nuxt.config.ts file like so:
export default defineNuxtConfig({
frogger: {
/* Configuration options go here! */
}
})Use this to set things like the location of your log files, the configuration of the log ingestion endpoint, batching options for client or server, and more.
Module Interface
Everything is optional, meaning what you don't configure will fallback to default values. The Getting Started guide will get you familiar with the most common options:
export interface ModuleOptions {
// Subsystem preset — see "Presets" below. Default: 'minimal'.
preset?: 'minimal' | 'standard' | 'full'
clientModule?: boolean
serverModule?: {
autoEventCapture?: boolean
} | boolean
app?: AppInfoOptions,
file?: FileOptions
batch?: BatchOptions | false
// Mirrors your application logs to the console. On for both runtimes by
// default. `false` silences both; `{ client, server }` silences one side.
// See "Console output" below.
consoleOutput?: boolean | {
client?: boolean
server?: boolean
}
// Opt-in. `true` enables sensible tiers; an object tunes them.
rateLimit?: RateLimitingOptions | boolean
// Opt-in. `true` enables the dev live-stream on the default route.
websocket?: WebsocketOptions | boolean
// Opt-in. `true` enables the built-in redaction rules.
scrub?: ScrubberOptions | boolean
// Opt-in. `true` enables both sides; enable/tune each independently with
// `{ client, server }`.
errorCapture?: boolean | {
client?: ClientErrorCaptureOptions | boolean
server?: ServerErrorCaptureOptions | boolean
}
// Extra log destinations. Each forwards every batch to an HTTP ingest URL,
// from the server queue (`server`, default on) and/or the browser
// (`client`, default off). See the Transports guide. Default: [].
transports?: HttpTransportConfig[]
public?: {
endpoint?: string
baseUrl?: string
batch?: BatchOptions | false
serverModule?: boolean
}
}Click here to view the full interface
export interface ModuleOptions {
preset?: 'minimal' | 'standard' | 'full'
clientModule?: boolean
serverModule?: {
autoEventCapture?: boolean
} | boolean
app?: {
name: string;
version?: string;
} | string
file?: {
directory?: string
fileNameFormat?: string
maxSize?: number
flushInterval?: number
bufferMaxSize?: number
highWaterMark?: number
}
batch?: {
maxSize?: number
maxAge?: number
retryOnFailure?: boolean
maxRetries?: number
retryDelay?: number
sortingWindowMs?: number
} | false
consoleOutput?: boolean | {
client?: boolean;
server?: boolean;
}
rateLimit?: {
limits?: {
global?: number;
perIp: number;
perReporter?: number;
perApp?: number;
};
windows?: {
global?: number;
perIp: number;
perReporter?: number;
perApp?: number;
};
blocking?: {
enabled: boolean;
escalationResetHours: number;
finalBanHours: number;
violationsBeforeBlock: number;
timeouts: number[];
};
storage?: {
driver?: string;
options?: Record<string, any>;
};
} | boolean
websocket?: {
route: string;
defaultChannel?: string;
upgrade?: (request: Request) => boolean | Promise<boolean>;
maxConcurrentQueries?: number;
defaultQueryTimeout?: number;
maxQueryResults?: number;
cache?: {
maxMemoryMB?: number;
ttlSeconds?: number;
maxEntries?: number;
enabled?: boolean;
}
} | boolean
scrub?: {
maxDepth?: number;
deepScrub?: boolean;
preserveTypes?: boolean;
rules?: ScrubRule[];
} | boolean
errorCapture?: boolean | {
client?: {
includeComponent?: boolean;
includeComponentProps?: boolean;
includeComponentOuterHTML?: boolean;
includeInfo?: boolean;
includeStack?: boolean;
} | boolean;
server?: {
includeRequestContext?: boolean;
includeHeaders?: boolean;
includeRejectionHandled?: boolean;
includeWarnings?: boolean;
includeStack?: boolean;
} | boolean;
}
transports?: Array<{
// Full ingest URL — shorthand for `baseUrl` (origin) + `endpoint` (path).
url?: string
baseUrl?: string
endpoint?: string
// Sent as the `x-api-key` header on every batch to this destination.
apiKey?: string
headers?: Record<string, string>
client?: boolean // fan out from the browser (default false)
server?: boolean // fan out from the server queue (default true)
name?: string
vendor?: string
timeout?: number
retryOnFailure?: boolean
maxRetries?: number
retryDelay?: number
}>
public?: {
endpoint?: string
baseUrl?: string
batch?: {
maxSize?: number
maxAge?: number
retryOnFailure?: boolean
maxRetries?: number
retryDelay?: number
sortingWindowMs?: number
} | false
}
}Client transport keys are public
A client: true transport's apiKey and headers are compiled into the browser bundle. Only ever use a write-only, per-service, rate-limited ingest key there. See Transports → Security.
Presets
Frogger is quiet by default. A bare install logs to a file and the console, and nothing else — the heavier subsystems are opt-in. A preset is a shorthand for a group of those toggles:
| Preset | scrub | rateLimit | errorCapture | websocket (dev live-stream) |
|---|---|---|---|---|
minimal (default) | ✗ | ✗ | ✗ | ✗ |
standard | ✓ | ✓ | ✓ | ✗ |
full | ✓ | ✓ | ✓ | ✓ |
file + console output and client/server batching are always on (unless you disable them explicitly; console output is turned off with consoleOutput). Only the four columns above are preset-controlled.
export default defineNuxtConfig({
// A production-sensible safety net: redaction, ingest rate-limiting and
// global error capture, without the dev-only websocket live-stream.
frogger: { preset: 'standard' }
})Individual options always win over the preset, so you can start from a preset and flip one thing:
export default defineNuxtConfig({
frogger: {
preset: 'standard',
scrub: false, // turn one subsystem back off
websocket: true, // ...or add one the preset left off
}
})Each opt-in option accepts true (enable with sensible defaults), an object (enable and customise), or false/omitted (off). errorCapture additionally accepts { client, server } so you can enable each side independently.
Config applied when a subsystem is enabled
These are the defaults each subsystem uses once switched on (via a preset, true, or an object). Pass an object to override any field — it deep-merges onto these.
// scrub: true → engine on, but ZERO rules (nothing is scrubbed until you
// declare rules — see the Scrubbing guide). Only the knobs below are defaulted;
// maxDepth is unset = unlimited recursion:
{ deepScrub: true, preserveTypes: true }
// rateLimit: true →
{
limits: { global: 10000, perIp: 100, perReporter: 50, perApp: 30 },
windows: { global: 60, perIp: 60, perReporter: 60, perApp: 60 },
blocking: {
enabled: true,
escalationResetHours: 24,
timeouts: [60, 300, 1800],
violationsBeforeBlock: 3,
finalBanHours: 12,
},
}
// websocket: true →
{
route: '/api/_frogger/dev-ws',
defaultChannel: 'main',
maxConcurrentQueries: 10,
maxQueryResults: 1000,
defaultQueryTimeout: 30000,
}
// errorCapture: true →
{
client: {
includeComponent: true,
includeComponentProps: true,
includeComponentOuterHTML: true,
includeInfo: true,
includeStack: true,
},
server: {
includeRequestContext: true,
includeHeaders: true,
includeRejectionHandled: false,
includeWarnings: false,
includeStack: true,
},
}Always-on core defaults (consoleOutput, file, batch)
// consoleOutput →
{ client: true, server: true }
// file →
{
directory: 'logs',
fileNameFormat: 'YYYY-MM-DD.log',
maxSize: 10 * 1024 * 1024,
flushInterval: 1000,
bufferMaxSize: 1 * 1024 * 1024,
highWaterMark: 64 * 1024,
}
// batch (server) →
{ maxSize: 200, maxAge: 15000, retryOnFailure: true, maxRetries: 5, retryDelay: 10000, sortingWindowMs: 3000 }
// public.batch (client) →
{ maxSize: 100, maxAge: 3000, retryOnFailure: true, maxRetries: 3, retryDelay: 3000, sortingWindowMs: 1000 }Upgrading from a version before presets
Earlier versions enabled scrubbing, rate-limiting, the dev websocket and global error capture by default. They are now off unless you opt in. To keep the old behaviour, set preset: 'full' (or preset: 'standard' to skip the dev-only websocket). The vestigial public.globalErrorCapture option has been removed — use errorCapture instead.
Note that scrubbing changed further: enabling it no longer applies any built-in rules. Even with preset: 'full', nothing is scrubbed until you declare rules. To restore the old default coverage, opt into the RECOMMENDED_RULES bundle — see the Scrubbing guide.
Console output
By default Frogger mirrors every application log to the console: the browser devtools console on the client, stdout on the server. consoleOutput turns that off.
export default defineNuxtConfig({
frogger: {
consoleOutput: false, // silence both runtimes
}
})Pass an object to control each runtime independently. The most common case is a silent browser with the server console left intact:
export default defineNuxtConfig({
frogger: {
consoleOutput: {
client: process.env.NODE_ENV !== 'production',
// `server` is unspecified, so it stays on
},
}
})client covers loggers created by useFrogger() and the ambient frogger.* facade, including the logs they emit during server-side rendering. server covers getFrogger().
Silencing the console never drops a log
Console output and transport delivery are independent paths. A logger with consoleOutput: false still batches every log and ships it to your configured transports and ingest endpoint. This is what makes it safe to run a production browser build that prints nothing to devtools while still collecting everything.
Per-logger overrides
consoleOutput is also a per-instance option. A value passed to a specific logger always wins over the module option, in either direction:
// with nuxt.config.ts set to frogger: { consoleOutput: false }
frogger.info('silent') // module default: no console
useFrogger().info('silent') // module default: no console
useFrogger({ consoleOutput: true }).info('loud') // opts back inResolution order, most specific first:
| Source | Example |
|---|---|
| Per-logger option | useFrogger({ consoleOutput: true }) |
| Module option | frogger: { consoleOutput: { client: false } } |
| Built-in default | true |
Child loggers and spans inherit their parent's resolved value, so logger.child({}), logger.startSpan('checkout') and logger.span('checkout', fn) all stay consistent with the logger they came from.
Not the same as verbose / logLevel
consoleOutput governs your application logs. Frogger's own internal diagnostics (transport state, caught errors in its machinery, build banners) are a separate channel, controlled by the verbose and logLevel module options. Those are already silent in production builds.
One console message is deliberately exempt from both: if a log fails to reach the queue and a direct send also fails, Frogger prints an error rather than dropping your log silently.
Frogger Config
If you prefer to keep your Frogger configuration separate from your Nuxt configuration, you can create a frogger.config.ts file in the root of your project. It will be automatically scanned by Frogger.
import { defineFroggerOptions } from '#frogger/config';
export default defineFroggerOptions({
/* Configuration options go here! */
});Env Variables
All of Frogger's module options are stored in Nuxt's runtime configuration. Everything is overridable, meaning zero changes required if you need different settings in different environments.
For example, if you set a NUXT_PUBLIC_FROGGER_ENDPOINT env variable in your production environment:
NUXT_PUBLIC_FROGGER_ENDPOINT=https://my-custom-endpoint.comIt will behave the same as overriding the public.endpoint option in the module configuration:
export default defineNuxtConfig({
frogger: {
public: {
endpoint: '/api/_frogger/logs',
endpoint: 'https://my-custom-endpoint.com'
}
}
})Nested keys follow the same pattern, so console output can be silenced per runtime without touching your config:
NUXT_PUBLIC_FROGGER_CONSOLE_OUTPUT_CLIENT=falseWARNING
Changing Frogger's options during the runtime of your applications is not recommended. It won't work. Frogger internals capture configuration options at build time, and wont react to changes. Configuration options should only be set at the starting of your application or at build time.
TIP
If you need something more dynamic, logger instances are designed to be pluggable, extendable, and configurable at runtime.