This directory holds the frontend for Codebloom, which is visible at codebloom.patinanetwork.org.
This is a React 18 + Vite project, where we mainly utilize Mantine to style our UI.
View STYLEGUIDE.md to view best practices.
Last updated: 02/15/2026
js/
├── patches # holds package patches we need
├── public # holds all our static assets
├── src
│ ├── __mock__ # mock server routes
│ ├── app # main app routes
│ ├── components # shared re-usable components
│ ├── lib
│ │ ├── api # holds our API specific code
│ │ │ ├── common
│ │ │ ├── queries # react query / fetcher logic
│ │ │ ├── schema # input validation schemas used in the frontend
│ │ │ ├── types # autogenerated types from OpenAPI schema
│ │ │ └── utils
│ │ ├── ff # feature flags
│ │ ├── helper # stateless helper functions
│ │ ├── hooks # custom re-usable react hooks
│ │ ├── queryProvider.tsx # ReactQueryProvider
│ │ ├── reporter # custom error reporter
│ │ ├── router.tsx # routes
│ │ ├── test # test utils
│ │ ├── theme.tsx # custom Mantine theme
│ ├── main.tsx # react entry point
│ ├── patches.ts # custom runtime patches we apply via side-effect import
Please go to STYLEGUIDE.md to view more detailed documentation about our Codebloom UI best practices
The Codebloom frontend has a very close relationship with the Codebloom backend.
We use openapi-typescript to introspect the backend's OpenAPI schema endpoint, which will then convert everything into TypeScript and save into a schema.ts file. This file is saved at js/src/lib/api/types/autogen/schema.ts.
We have two main use-cases for the schema file:
- We have a helper method called
ApiURL(read about here) which helps us maintain full type-safety when passing data between the frontend & backend and vice versa. - All enums sent from the backend are converted into
TypeScriptenums, which allow us to programmatically define behaviors based on the enums.
These enums are extra special because we can fully generate UI code based on these enums at compile time.
For example, our leaderboard filters are generated by the useFilters, which takes all the enum values and generates a hook object.
Every single one of these filters are automatically generated from
Tag.java
Last updated: 02/15/2026
We actually decided to try something very experimental: generating more complex types based off these enums via the Codebloom backend. This experiment is currently inside of ComplexJSTypesGenerator.java which currently generates the current file:
/**
* This file was generated by the Codebloom backend.
* DO NOT EDIT THIS FILE MANUALLY!!!
*/
import { Tag } from "@/lib/api/types/schema";
export const PARENT_TAGS_TO_CHILD_TAGS: Record<Tag, Tag[]> = {
[Tag.MHCPlusPlus]: [],
[Tag.Rpi]: [],
[Tag.Baruch]: [],
[Tag.Columbia]: [],
[Tag.Patina]: [],
[Tag.Sbu]: [],
[Tag.Bmcc]: [],
[Tag.Cornell]: [],
[Tag.Hunter]: [Tag.Gwc, Tag.MHCPlusPlus],
[Tag.Gwc]: [],
[Tag.Nyu]: [],
[Tag.Ccny]: [],
} as const;Last updated: 02/15/2026
which allows us to define a complex relationship of parent tags to child tags. This Record is now currently being used in production to generate our Club Filters.
You can view the implementation of ApiURL here.
ApiURL is a custom utility class designed to enforce type-safe requests when the frontend is sending/receiving data to/from the backend. It integrates directly with the generated schema.ts (read more about schema.ts here) file to ensure every fetch request — its method, parameters, body, and response — is validated at compile time.
ApiURL serves as the single entry point for building strongly-typed requests.
It provides the following core methods and behaviors:
-
ApiURL.create(path, options)— Static factory method to createApiURL.that validates the provided path, method, and optionally path/query parameters.path- Must be a valid endpoint path. > Note: URLs with dynamic paths are still supported.
-
.url— Accessor that returns the Web APIURLobject after substituting path and query parameters. This can be passed directly intofetch(). -
.method— Accessor returns the validated HTTP method (e.g.,"GET","POST") to use infetch.
Only allows valid methods defined in the backend OpenAPI schema. -
.req(body)— Function that serializes and validates a request body (at compile-time) according to the backend’s expected type definition.
Under the hood,.reqcallsJSON.stringifyfor you. As such, it returns astringfor use asfetch'sbody. -
.res(response)— Function that validates a JSON response against the expected type.
Adds 0 runtime overhead - it’s purely a compile-time safety check.[!NOTE] T
.reswill always target anOKresponse. This is because Codebloom uses a customApiRespondertype that will always return some fields back to the client. Read more about how it's implemented in the backend here.
const { url, method, req, res } = ApiURL.create(
"/api/admin/user/admin/toggle", // full autocomplete
{
method: "POST",
},
);
const response = await fetch(url, {
method,
headers: { "Content-Type": "application/json" },
body: req({ id: userId, toggleTo }), // full autocomplete
});
const json = res(await response.json());
return json; // `json` is fully typedconst { url, method, res } = ApiURL.create(
"/api/leetcode/submission/{submissionId}", // full autocomplete
{
method: "GET",
params: {
// params has full autocomplete
submissionId,
},
},
);
const response = await fetch(url, {
method,
});
const json = res(await response.json());
return json; // `json` is fully typed


