rCTF Docs
Overview

Categories

Challenge category configuration, colors, icons, and customization.

Each challenge category in rCTF has its own color palette, icon, and display name configured in apps/web/src/lib/utils/categories.ts. The system uses dynamic CSS variable injection to apply category-specific colors to components. A category’s color key (e.g., red) maps to CSS variables like --category-foreground-l0, which components reference through Tailwind classes such as text-category-foreground-l0.

Default categories#

Each of the default categories uses a color specified in Category colors.

CategoryDisplay nameColorIcon
sanitySanitygray
pwnBinary Exploitationred
reverseReverse Engineeringorange
cryptoCryptographyyellow
forensicsForensicsgreen
blockchainBlockchainteal
webWebsky
miscMiscellaneouspurple
ppcProfessional Programming and Codingfuchsia
kothKing of the Hillpink
osintOSINTgray

A handful of category aliases (binarypwn, revreverse, cryptographycrypto) make naming a bit more flexible.

Note (How category styling works)

The getCategoryStyle(color) function generates inline CSS that binds a color’s variables to generic category tokens:

getCategoryStyle('red')
// Returns:
// "--category-foreground-l0: var(--foreground-red-l0);
// --category-foreground-l1: var(--foreground-red-l1);
// --category-background-l0: var(--background-red-l0);
// --category-background-l1: var(--background-red-l1);
// --category-background-l1-hover: var(--background-red-l1-hover);"

Components apply this style to a container, then use generic classes:

<div style={getCategoryStyle(config.color)}>
<span class="text-category-foreground-l0">{challenge.name}</span>
<span class="bg-category-background-l0 text-category-foreground-l1">
{config.name}
</span>
</div>

Each color has five variables defined in app.css for both light and dark modes. These are --background-l0, --background-l1, --background-l1-hover, --foreground-l0, and --foreground-l1.

Adding a custom category#

Define the category

Add an entry to categoryConfigs with a name, icon component, Iconify name (for exports), and color key:

lib/utils/categories.ts
import { IconCpuFilled } from '$lib/icons'
export const categoryConfigs: Record<string, CategoryConfig> = {
// ... existing
hardware: {
name: 'Hardware',
icon: IconCpuFilled,
iconName: 'tabler:cpu-filled',
color: 'teal', // Use an existing color, or add a new one
},
}
Register the icon

In lib/icons/index.ts, export the icon:

lib/icons/index.ts
export { default as IconAlertCircleFilled } from '@iconify-svelte/tabler/alert-circle-filled'
export { default as IconCameraFilled } from '@iconify-svelte/tabler/camera-filled'
export { default as IconCpuFilled } from '@iconify-svelte/tabler/cpu-filled'
export { default as IconPhotoFilled } from '@iconify-svelte/tabler/photo-filled'
export { default as IconAlertTriangleFilled } from '@iconify-svelte/tabler/alert-triangle-filled'
Set the display order (optional)

Add your category to categoryOrder to control its position in the challenge list:

lib/utils/categories.ts
export const categoryOrder = [
'sanity',
'pwn',
'reverse',
'crypto',
'forensics',
'blockchain',
'web',
'misc',
'ppc',
'koth',
'osint',
'hardware',
]

Categories not in this list show up alphabetically after the listed ones.

Add color variables (if using a new color)

If your category uses a color not already in the palette, add variables to app.css following the existing pattern. Define --background-{color}-l0, --background-{color}-l1, --background-{color}-l1-hover, --foreground-{color}-l0, and --foreground-{color}-l1 for both :root and [data-theme='dark']. Don’t forget to map the colors in @theme inline too.

Utility functions#

The following utility functions help with category configuration:

FunctionPurpose
getCategoryConfig(category)Returns { name, icon, iconName, color } for a category key
getCategoryKeyOrAlias(category)Resolves aliases to canonical keys ('rev''reverse')
getCategoryStyle(color)Generates inline CSS for category variable binding
getCategoryOrder(category)Returns sort index (-1 if unlisted)
Esc

Start typing to search the docs.