S
Get Started

Configuration

Every option of new Forge, what it does, its default and how invalid settings are reported

You configure StarkForge with one options object: new Forge(options). Every option is optional, so new Forge() starts a development server, and you add options as your project needs them. This page is the reference for all of them. StarkForge reads no environment variables itself; your code reads them and passes the values in, as Environment Variables shows.

A Realistic Example

This server sets the options most projects change first. It reads secrets and addresses from the environment and keeps the rest in code:

TypeScript
// src/server.ts
import { Forge } from "@starklabs/forge";

const forge = new Forge({
  ENV: process.env.NODE_ENV,
  port: Number(process.env.PORT ?? 5000),
  backendURL: process.env.BACKEND_URL,
  frontendURL: process.env.FRONTEND_URL,
  mongoDBURI: process.env.MONGODB_URI,
  databaseName: "acme",
  jwtSecret: process.env.JWT_SECRET,
  masterKey: process.env.MASTER_KEY,
  trustProxy: 1,
  bodyLimit: "1mb",
  rateLimitDuration: "10m",
  maxReqLimit: 300,
  authMaxReqLimit: 10,
  systemEmailSender: "Acme <[email protected]>",
  resendAPIKey: process.env.RESEND_API_KEY,
  defaultPageSize: 25,
  maxPageSize: 100,
});

await forge.start();

An option whose value is undefined, such as an unset environment variable, behaves as if you had not written it.

Server Options

OptionTypeDefaultWhat it does
portnumber5000The port to listen on, from 0 to 65535. 0 picks a free port, which tests use
apiVersionnumber1A positive integer. Routes are mounted under /api/v1, so 2 gives /api/v2
ENVstring"development"The environment name. "production" changes several defaults (see Production Defaults), and "test" silences logging
backendURLstringhttp://localhost:5000/api/v1, built from portThe public base URL of the API, including the version prefix. Social sign-in uses it to build callback URLs
frontendURL and frontendURLsstring and string[]noneThe browser origins that may call the API with cookies, for example http://localhost:3000. They are also the only places a redirect may point
corsConfigcors optionsbuilt from the front-end URLsReplaces the generated CORS options. Without it, the front-end origins are allowed with credentials, and with no front-end URL at all, cross-origin browser requests are refused
trustProxyboolean, number or stringfalseThe Express trust proxy setting. Set it behind a load balancer so that rate limits see the visitor's address
logRequestsbooleantrue, and false when ENV is "test"Prints the start-up banner and one log line per request
exposeErrorDetailsbooleantrue outside productionAdds hint and details to error bodies and shows real messages for unexpected errors
bodyLimitstring"100kb"The largest JSON or form body, such as "1mb". A larger body gets 413 PAYLOAD_TOO_LARGE

Database Options

OptionTypeDefaultWhat it does
isOfflinebooleantrue unless ENV is "production"Development mode for services. The database falls back to mongodb://127.0.0.1:27017, and one-time codes and magic links are printed to the console instead of being emailed. It is rejected in production
mongoDBURIstringnoneThe MongoDB connection string. Required when isOffline is false
databaseNamestring"starkForge"The database to use on that server

Security Options

OptionTypeDefaultWhat it does
jwtSecretstringnoneThe key that signs session tokens. At least 32 characters, and required when any sign-in feature is configured. Generate one with generateJWTSecret()
masterKeystringnoneThe key that encrypts fields and two-factor secrets: base64 text of exactly 32 bytes. Generate one with generateMasterKey(). Losing it makes encrypted data unreadable
adminRolesstring[]["admin"]The roles that count as administrators. The list must not be empty
protectedFieldsstring[]["role"]Fields that only administrators may write. Other users' requests have them removed

Rate Limit Options

Both limits count requests per visitor address inside one window and answer 429 when the count is exceeded.

OptionTypeDefaultWhat it does
rateLimitDurationduration"15m"The length of the window for both limits
maxReqLimitnumber100Requests allowed per window for every route. Must be positive
authMaxReqLimitnumber20A stricter shared allowance for sign-up, sign-in, one-time code and password reset routes. Must be positive
rateLimitMsgstring"Too many requests, please try again later."The message of the 429 answer
rateLimitStorestorein memoryA store from express-rate-limit. Use a shared one, such as Redis, when several instances run

Email Options

OptionTypeDefaultWhat it does
systemEmailSenderstringnoneThe sender of system emails such as codes and links. It must look like Acme <[email protected]>
resendAPIKeystringnoneThe Resend API key. Real email is sent only when this is set and isOffline is false

Upload Options

OptionTypeDefaultWhat it does
cloudinaryAPIKey, cloudinaryAPISecret and cloudinaryCloudNamestringnoneYour Cloudinary credentials. All three are required as soon as one route accepts files
cloudinaryFolderNamestring"starkForge"The Cloudinary folder that receives the files
uploadMaxFileSizenumber5242880The largest single file in bytes, which is 5 MiB
uploadMaxFilesnumber10The most files in one request

Pagination Options

OptionTypeDefaultWhat it does
defaultPageSizenumber50The page size of a list when the request has no limit. It must not be larger than maxPageSize
maxPageSizenumber100The largest page size of a list. A larger limit in a request is lowered to this value

Collections and Built-in Features

OptionTypeDefaultWhat it does
collectionscollection[][]Your resources. See Collections
builtinConfigobjectnoneSettings for features that StarkForge generates for you: auth, account and email. The Authentication page covers the first two. The email key holds the placeholder values of system emails: companyName, companyUrl, companyAddress, supportEmail and unsubscribeUrl

Production Defaults

Setting ENV to "production" turns on stricter defaults. Each row below is a default that you can still override, except the offline rule, which is enforced.

SettingDevelopmentProduction
isOfflinetruefalse, and true is rejected
mongoDBURIOptionalRequired
exposeErrorDetailstruefalse, so errors carry no hint or details and unexpected errors answer Something went wrong.
Log detailDebugInfo
Auth cookie sameSite"lax""none", for a front end on another site
Auth cookie securefalsetrue, so cookies travel only over HTTPS
One-time codes and magic linksPrinted to the consoleEmailed, which needs resendAPIKey and systemEmailSender

The Deployment page lists everything else to check before you go live.

Duration Values

Options such as rateLimitDuration take a duration: a number followed by a unit, with no space. The number may have decimals, as in "1.5h".

UnitMeaningExample
msMilliseconds"500ms"
sSeconds"30s"
mMinutes"15m"
hHours"2h"
dDays"7d"
wWeeks"2w"
moMonths of 30 days"1mo"
yYears of 365 days"1y"

Invalid Settings

new Forge checks every option immediately and throws one ConfigurationError that lists every problem it found, so you can fix them in one pass. Its code is CONFIGURATION_ERROR. This is what a missing secret and a missing user model look like:

Text
ConfigurationError (CONFIGURATION_ERROR): Invalid Forge configuration:
 - auth.mongooseConfig is required when auth.mode is 'builtin'.
 - jwtSecret is required for authentication. Generate one with generateJWTSecret().
hint: Fix the listed options in new Forge({...}).

A duration written in words is rejected the same way:

Text
ConfigurationError (CONFIGURATION_ERROR): Invalid Forge configuration:
 - rateLimitDuration "15 minutes" is not a valid duration (examples: "30s", "15m", "1d").
hint: Fix the listed options in new Forge({...}).

Mistakes inside a collection, such as an unknown handler name, are reported when the app is built, which start() does for you. Their message lists each problem with the method and the path of the route, and the Routes page shows it.

Misspelled Options

StarkForge does not reject an option name it does not know. In TypeScript the compiler flags a misspelled name for you. In plain JavaScript nothing does, so check the spelling against the tables above.

Warnings

Some problems are not fatal. StarkForge logs a warning when it starts, and forge.config.warnings holds the same list.

The warning saysWhat it means
have routes that require sign-in, but no authentication is configuredThose routes answer 401 to every request. Configure builtinConfig.auth or mark the routes auth: "public"
builtinConfig.email was not providedReal email can go out, and its templates may show empty placeholders. Add builtinConfig.email
corsConfig: origin '*' together with credentials is unsafeList your front-end origins instead of *
auth.cookie.secure is false in productionSession cookies would travel over plain HTTP
domain is deprecatedYou used the 1.x top-level domain option. Set builtinConfig.auth.cookie.domain instead

Reading the Resolved Config

forge.config holds the validated settings with every default filled in. It is read-only, so you can pass it around safely. For example, forge.config.port is the port that was resolved, forge.config.apiPrefix is /api/v1 and forge.config.isProduction tells you which mode you are in.

Where to Go Next

Authentication

Configure sign-up, sign-in and sessions with builtinConfig.

Deployment

Check everything that changes in production.

:::