Skip to main content


CTFd themes are made up of 3 main components:

Jinja Templates

The Jinja templates are rendered by Flask which is the underlying framework that CTFd is written in. Once the template is rendered to HTML, the HTML will load the appropriate JavaScript (JS) and CSS files.

Javascript and CSS

The JS and CSS files are created through the use of a build system. CTFd has a build system designed around Vite which itself is based on Rollup.

Folders and Files

While the only two folders which are absolutely required by a CTFd theme are static and templates, in general themes should be broken down into the following structure:

|-- assets/
|-- static/
|-- templates/
|-- package.json
`-- vite.config.js

Note that we are not including other files such as configuration files, instructions, node_modules, etc. since they are only used to build our theme structure.


The assets directory generally contains the uncompiled, unminified source of any JS or CSS files.

You may commonly see a structure such as:

|-- js/
`-- scss/


The static directory will contain the compiled and minified JS and CSS files that will be served by CTFd to the user's browser. The structure for this is roughly:

|-- assets
|-- manifest.json
`-- manifest-css.json

The manifest.json and manifest-css.json files should be automatically generated by the JS/CSS build system. In the following sections it is documented how to generate these files using Vite.


The templates directory will contain the Jinja HTML templates that are rendered by CTFd and served to the user. Templates must have a very specific structure which is documented in the templates section.


package.json is a JSON file specified by most JavaScript projects. package.json is documented by npm. In most cases this should be generated for you when you create your project.


vite.config.js is the configuration file for the Vite build system used. The configuration for vite.config.js is outlined further in the Build System section.