Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/flagForgeCTF/flagForge/llms.txt

Use this file to discover all available pages before exploring further.

FlagForge stores all of its data in MongoDB — player accounts, CTF challenges, flag submissions, badges, and more. You can connect FlagForge to a managed MongoDB Atlas cluster or to a self-hosted MongoDB instance. Mongoose handles the database connection and automatically creates collections and indexes when the application starts.

Choosing a MongoDB option

MongoDB Atlas (recommended)

A fully managed cloud database. Atlas handles backups, scaling, and high availability. The free M0 tier is sufficient for small events and development.

Self-hosted MongoDB

Run MongoDB on your own infrastructure. Gives you full control but requires you to manage upgrades, backups, and networking yourself.
MongoDB Atlas’s free M0 tier provides 512 MB of storage and shared compute — more than enough to run a small-to-medium CTF event with a few hundred participants. You can upgrade to a paid tier as your event grows.

Setting up MongoDB Atlas

1

Create an Atlas account

Go to mongodb.com/atlas and sign up for a free account.
2

Create a cluster

Click Build a Cluster and select the Free (M0) tier. Choose a cloud provider and region close to your server.
3

Create a database user

In Database Access, create a new user with a strong password. Grant the user Read and Write to any database privileges.
4

Allow network access

In Network Access, add your server’s IP address to the IP allowlist. To allow access from anywhere (useful for development), add 0.0.0.0/0.
5

Get your connection string

Click Connect on your cluster, then choose Drivers. Copy the connection string and replace <password> with your database user’s password and append the database name:
mongodb+srv://username:password@cluster.mongodb.net/flagforge
Set this as your MONGO_URL environment variable.

Connection string format

mongodb+srv://username:password@cluster.mongodb.net/flagforge
PartDescription
usernameThe database user you created in Atlas or your self-hosted MongoDB
passwordThe database user’s password (URL-encode special characters)
cluster.mongodb.netYour Atlas cluster hostname, or your server’s hostname for self-hosted
flagforgeThe database name (FlagForge creates it automatically on first run)
FlagForge’s database connection uses a connection pool with up to 10 connections and a 30-second idle timeout. The pool is reused across Next.js hot reloads in development, so you won’t exhaust your Atlas connection limit during local development.

Collections

FlagForge creates the following collections automatically when the application first connects. You do not need to create them manually.

users

Stores player accounts created when a user signs in with Google for the first time.
FieldTypeDescription
nameStringDisplay name from Google
emailStringGoogle account email (unique, lowercase)
imageStringProfile photo URL from Google
roleString"User" or "Admin"
totalScoreNumberCumulative points earned across all solved challenges
customBadgesArrayInline badge records assigned directly to this user
createdAtDateAccount creation timestamp
updatedAtDateLast modification timestamp

questions

Stores CTF challenges created by admins.
FieldTypeDescription
titleStringChallenge title
descriptionStringChallenge description (supports Markdown)
categoryStringChallenge category (e.g., Web, Crypto, Forensics)
pointsNumberPoints awarded for solving
flagStringFlag string or dynamic flag template
hintsArrayArray of hints, each with text and pointsDeduction
challengeTypeString"link" or "file"
linkStringURL to challenge resource (if type is link)
challengeFileStringPath to challenge file (if type is file)
isTimeLimitedBooleanWhether the challenge has an expiry date
expiryDateDateWhen the challenge expires (if time-limited)
uploadedByStringEmail of the admin who created the challenge
createdAtDateCreation timestamp
updatedAtDateLast modification timestamp
Indexes: compound index on (category, points) for filtered queries; index on expiryDate for expiry lookups.

userquestions

Records each solved challenge per user. A document is created here when a user successfully submits the correct flag.
FieldTypeDescription
userIdObjectIdReference to the users collection
questionIdObjectIdReference to the questions collection
createdAtDateTimestamp of when the challenge was solved

assignedbadges

Tracks badge assignments from admins to users.
FieldTypeDescription
userIdStringThe recipient user’s ID
badgeIdMixedID of the badge template or custom badge
badgeTypeString"template" or "custom"
assignedByStringAdmin who assigned the badge
reasonStringOptional reason for the assignment
isActiveBooleanWhether the badge is currently active
badgeNameStringDisplay name (denormalized for performance)
badgeDescriptionStringDisplay description (denormalized)
badgeIconStringIcon identifier (denormalized)
badgeColorStringHex color (denormalized)
assignedAtDateAssignment timestamp
Indexes: unique compound index on (userId, badgeId, isActive) with a partial filter to prevent duplicate active assignments.

badgetemplates

Stores reusable badge definitions that admins can assign to multiple users.
FieldTypeDescription
nameStringBadge name (unique)
descriptionStringBadge description
iconStringIcon identifier
colorStringHex color (default #8B5CF6)
isActiveBooleanWhether the template is available for assignment
createdByStringAdmin who created the template
createdAtDateCreation timestamp

dynamicflags

Stores per-user generated flags for dynamic flag challenges. Each document expires automatically after 24 hours.
FieldTypeDescription
userIdStringThe player’s user ID
questionIdStringThe challenge ID this flag belongs to
flagStringThe generated flag string
expiresAtDateExpiry timestamp (24 hours from generation)
Indexes: compound index on (userId, questionId) for fast lookups; TTL index on expiresAt — MongoDB automatically deletes expired documents.
Dynamic flags are deleted immediately after a successful submission, in addition to the 24-hour TTL. If a player’s flag expires before they submit it, they can generate a new one by clicking Start Challenge again.

tokenblacklists

Stores revoked JWT token IDs (JTI) to prevent reuse of signed-out session tokens.
FieldTypeDescription
jtiStringJWT ID of the revoked token (unique, indexed)
userIdStringThe user who owned the token (optional)
expiresAtDateWhen the original token would have expired
blacklistedAtDateWhen the token was revoked
Expired blacklist entries are automatically removed after a 90-day grace period via a TTL index on expiresAt.

Database indexes summary

FlagForge creates the following indexes automatically via Mongoose schema definitions:
CollectionIndexTypePurpose
questions(category, points)CompoundFiltered challenge queries
questionsexpiryDateSingle fieldTime-limited challenge lookups
dynamicflags(userId, questionId)CompoundFast per-user flag lookups
dynamicflagsexpiresAtTTLAuto-delete expired flags after 24h
assignedbadges(userId, badgeId, isActive)Unique partialPrevent duplicate active assignments
assignedbadges(userId, isActive)CompoundUser badge queries
tokenblacklistsjtiSingle fieldFast token revocation checks
tokenblacklists(jti, expiresAt)CompoundEfficient blacklist validation
tokenblacklistsexpiresAtTTLAuto-delete entries after 90 days

Build docs developers (and LLMs) love