Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c6c2795
chore: caniuse db update
Miodec Feb 27, 2026
bb4e4a8
refactor(timer-progress): extract logic into helper functions in time…
Leonabcd123 Feb 27, 2026
7722104
fix(edit-preset): error message when failing to add preset (@Leonabcd…
Leonabcd123 Feb 27, 2026
7c66fd7
feat(layout): add azerty_AFNOR layout (@JacquesHumule) (#7376)
JacquesHumule Feb 27, 2026
0f09ae3
impr(quotes): added English quote (@szpeterr) (#7378)
szpeterr Feb 27, 2026
041b15c
fix(streak-hour-offset): streak hour offset display isn't correct for…
Leonabcd123 Feb 27, 2026
26adcb3
fix(quotes): fixed some grammatical errors in spanish quotes (@GabiRP…
GabiRP Feb 27, 2026
c13d59f
feat(font): add Adwaita Mono (@poli0iq) (#7389)
poli0iq Feb 27, 2026
386101c
refactor(funbox): wikipedia getTLD cleanup (@Eric-Zhang-Developer) (#…
Eric-Zhang-Developer Feb 27, 2026
d08ea0e
chore: move tab-specific refresh to updateTabs (@byseif21) (#7414)
byseif21 Feb 27, 2026
8b29ab6
ci: less restrictive node version for dependabot (@fehmer) (#7419)
fehmer Feb 27, 2026
0c1f9f1
chore: update pnpm to 10.28.1 (@fehmer) (#7421)
fehmer Feb 27, 2026
57e6a2e
chore: update redocly-cli to 2.15.1 (@fehmer) (#7420)
fehmer Feb 27, 2026
bf6dc32
chore: update turbo to 2.7.5 (@fehmer) (#7422)
fehmer Feb 27, 2026
12d0575
impr(quotes): add english quotes (@hmonwutt) (#7427)
HmonWutt Feb 27, 2026
61a0416
chore(quotes-text): normalize the last character in quotes (@Leonabcd…
Leonabcd123 Feb 27, 2026
4d0b4cc
impr(quote-search): use rtl direction when showing rtl text in quote …
Leonabcd123 Feb 27, 2026
6eceeb4
fix(validation-indicator): punctuation when there are multiple errors…
Leonabcd123 Feb 27, 2026
5b05b28
impr(quotes): add English quotes (@lindseyp555) (#7435)
lindseyp555 Feb 27, 2026
483fc50
chore: resolve selector warnings (@byseif21) (#7437)
byseif21 Feb 27, 2026
332d119
feat(layout): add Gralmak layout (@DreymaR) (#7457)
DreymaR Feb 27, 2026
5e78c9e
feat(layout): add statica_3x5 layout, vestnik layout (@ShyPsy) (#7460)
ShyPsy Feb 27, 2026
6e59ca3
fix(blind-mode): blind mode not working in 9009 theme (@fehmer) (#7474)
Leonabcd123 Feb 27, 2026
ba4d4e9
fix(caps-warning): caps state isn't always correct (@Leonabcd123, @fe…
Leonabcd123 Feb 27, 2026
e23836f
feat: add Chinese Traditional 1k, 5k, 10k, and 50k word lists (@nota-…
nota-noob Feb 27, 2026
9b38d64
chore: remove word
Miodec Feb 27, 2026
b58b48a
feat: add practice typing mode (no stats, xp, or pb) (@Vishal27alpha)…
Vishal27alpha Feb 27, 2026
944f9c7
fix(spanish_10k): correct spelling mistake in spanish_10k.json (@eswa…
eswaldots Feb 27, 2026
cb2d899
fix: merch banner image not visible on profile page (@fehmer) (#7487)
fehmer Feb 27, 2026
8198903
chore: add SlimSelect component (@miodec, @fehmer) (#7538)
fehmer Feb 27, 2026
e69d943
chore: add custom lint rule to enforce arrow functions in components
Miodec Feb 27, 2026
0217730
chore: change custom lint from fixer to suggestion
Miodec Feb 27, 2026
e79545d
chore: add lint rules for component structure and naming conventions
Miodec Feb 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check-formatting.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Check formatting

env:
PNPM_VERSION: "9.6.0"
PNPM_VERSION: "10.28.1"
NODE_VERSION: "24.11.0"

on:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/fix-formatting.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Fix formatting

env:
PNPM_VERSION: "9.6.0"
PNPM_VERSION: "10.28.1"
NODE_VERSION: "24.11.0"

permissions:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/monkey-ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Monkey CI

env:
PNPM_VERSION: "9.6.0"
PNPM_VERSION: "10.28.1"
NODE_VERSION: "24.11.0"
RECAPTCHA_SITE_KEY: "6Lc-V8McAAAAAJ7s6LGNe7MBZnRiwbsbiWts87aj"

Expand Down
2 changes: 1 addition & 1 deletion backend/docker/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ services:
build:
dockerfile_inline: |
FROM node:24.11.0
RUN npm i -g pnpm@9.6.0
RUN npm i -g pnpm@10.28.1
RUN mkdir /pnpm-store && chown -R 1000:1000 /pnpm-store
user: "node" ##this works as long as your local user has uid=1000
restart: on-failure
Expand Down
4 changes: 2 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"devDependencies": {
"@monkeytype/oxlint-config": "workspace:*",
"@monkeytype/typescript-config": "workspace:*",
"@redocly/cli": "2.0.5",
"@redocly/cli": "2.15.1",
"@types/bcrypt": "5.0.2",
"@types/cors": "2.8.12",
"@types/cron": "1.7.3",
Expand Down Expand Up @@ -90,6 +90,6 @@
"vitest": "4.0.15"
},
"engines": {
"node": "24.11.0 || 22.21.0"
"node": ">=24.0.0 <25"
}
}
4 changes: 2 additions & 2 deletions docker/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ COPY packages packages
COPY backend backend

#gimme pnpm + build
RUN npm i -g pnpm && \
RUN npm i -g pnpm@10.28.1 && \
pnpm i --frozen-lockfile && \
npm run build

#deploy (install all non-dev dependencies in a single node_module folder)
RUN pnpm deploy --filter backend --prod /prod/backend
RUN pnpm deploy --legacy --filter backend --prod /prod/backend

#---------------------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/CONTRIBUTING_ADVANCED.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ If you use `nvm` (if you use Windows, use [nvm-windows](https://github.com/corey

Alternatively, you can navigate to the NodeJS [website](https://nodejs.org/en/) to download it from there.

For package management, we use `pnpm` instead of `npm` or `yarn`. You can install it by running `npm i -g pnpm@9.6.0`. This will install `pnpm` globally on your machine.
For package management, we use `pnpm` instead of `npm` or `yarn`. You can install it by running `npm i -g pnpm@10.28.1`. This will install `pnpm` globally on your machine.

### Docker (Recommended but Optional)

Expand Down
2 changes: 1 addition & 1 deletion frontend/docker/compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ services:
build:
dockerfile_inline: |
FROM node:24.11.0
RUN npm i -g pnpm@9.6.0
RUN npm i -g pnpm@10.28.1
RUN mkdir /pnpm-store && chown -R 1000:1000 /pnpm-store
user: "node" ##this works as long as your local user has uid=1000
# restart: on-failure
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"dependencies": {
"@date-fns/utc": "1.2.0",
"@leonabcd123/modern-caps-lock": "2.0.3",
"@monkeytype/contracts": "workspace:*",
"@monkeytype/funbox": "workspace:*",
"@monkeytype/schemas": "workspace:*",
Expand Down Expand Up @@ -127,6 +128,6 @@
"not dead"
],
"engines": {
"node": "24.11.0 || 22.21.0"
"node": ">=24.0.0 <25"
}
}
20 changes: 20 additions & 0 deletions frontend/src/html/pages/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,26 @@
<button class="addPresetButton fullWidth">add preset</button>
</div>
</div>
<div
class="section resultSaving needsAccount"
data-config-name="resultSaving"
>
<div class="groupTitle">
<i class="fas fa-save"></i>
<span>result saving</span>
<button class="text" tabindex="-1">
<i class="fas fa-fw fa-link"></i>
</button>
</div>
<div class="text">
Disable result saving, in case you want to practice without affecting
your account stats.
</div>
<div class="buttons">
<button data-config-value="false">off</button>
<button data-config-value="true">on</button>
</div>
</div>
<div class="section" data-config-name="difficulty">
<div class="groupTitle">
<i class="fas fa-star"></i>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/html/popups.html
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,7 @@
<input
id="searchBox"
class="searchBox"
dir="auto"
type="text"
maxlength="200"
autocomplete="off"
Expand All @@ -937,7 +938,7 @@
<!-- favorites -->
</button>
</div>
<div id="quoteSearchResults" class="quoteSearchResults"></div>
<div dir="auto" id="quoteSearchResults" class="quoteSearchResults"></div>
<div id="quoteSearchPageNavigator">
<button class="prevPage" disabled>
<i class="fas fa-fw fa-chevron-left"></i>
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/ts/commandline/commandline-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ export const commandlineConfigMetadata: CommandlineConfigMetadataObject = {
options: "fromSchema",
},
},
resultSaving: {
subgroup: {
options: "fromSchema",
alias: (val) => (val ? "enabled" : "disabled"),
},
alias: "results practice incognito",
},
blindMode: {
subgroup: {
options: "fromSchema",
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/ts/commandline/lists.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import MinBurstCommands from "./lists/min-burst";
import BailOutCommands from "./lists/bail-out";
import QuoteFavoriteCommands from "./lists/quote-favorites";
import ResultSavingCommands from "./lists/result-saving";
import NavigationCommands from "./lists/navigation";
import ResultScreenCommands from "./lists/result-screen";
import CustomBackgroundCommands from "./lists/custom-background";
Expand Down Expand Up @@ -98,10 +97,10 @@ export const commands: CommandsSubgroup = {
//account
...TagsCommands,
...PresetsCommands,
...ResultSavingCommands,

//behavior
...buildCommands(
"resultSaving",
"difficulty",
"quickRestart",
"repeatQuotes",
Expand Down Expand Up @@ -379,7 +378,6 @@ const lists = {
minBurst: MinBurstCommands[0]?.subgroup,
funbox: FunboxCommands[0]?.subgroup,
tags: TagsCommands[0]?.subgroup,
resultSaving: ResultSavingCommands[0]?.subgroup,
ads: adsCommands[0]?.subgroup,
};

Expand Down
39 changes: 0 additions & 39 deletions frontend/src/ts/commandline/lists/result-saving.ts

This file was deleted.

20 changes: 10 additions & 10 deletions frontend/src/ts/components/common/AnimatedModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function AnimatedModal(props: AnimatedModalProps): JSXElement {
}
});

async function showModal(isChained: boolean): Promise<void> {
const showModal = async (isChained: boolean): Promise<void> => {
if (dialogEl() === undefined || modalEl() === undefined) return;

await props.beforeShow?.();
Expand Down Expand Up @@ -153,9 +153,9 @@ export function AnimatedModal(props: AnimatedModalProps): JSXElement {
},
});
}
}
};

async function hideModal(isChained: boolean): Promise<void> {
const hideModal = async (isChained: boolean): Promise<void> => {
// Guard: only hide if visible and not already animating
if (dialogEl() === undefined || modalEl() === undefined) return;

Expand Down Expand Up @@ -209,18 +209,18 @@ export function AnimatedModal(props: AnimatedModalProps): JSXElement {
},
});
}
}
};

async function handleAfterHide(): Promise<void> {
const handleAfterHide = async (): Promise<void> => {
await props.afterHide?.();
storeHideModal(props.id);
}
};

async function handleAfterShow(): Promise<void> {
const handleAfterShow = async (): Promise<void> => {
await props.afterShow?.();
}
};

function focusFirstInput(): void {
const focusFirstInput = (): void => {
if (modalEl() === undefined || dialogEl() === undefined) return;
if (props.focusFirstInput === undefined) return;

Expand All @@ -233,7 +233,7 @@ export function AnimatedModal(props: AnimatedModalProps): JSXElement {
input.select();
}
}
}
};

const handleKeyDown = (e: KeyboardEvent): void => {
if (e.key === "Escape" && visibility()) {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/ts/components/common/AsyncContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ export default function AsyncContent<T extends QueryMapping>(
return message;
};

function allResolved(
const allResolved = (
data: ReturnType<typeof value>,
): data is { [K in keyof T]: T[K] } {
): data is { [K in keyof T]: T[K] } => {
//single query
if (data === undefined || data === null) {
return false;
}

return Object.values(data).every((v) => v !== undefined && v !== null);
}
};

const isLoading = (): boolean =>
Object.values(source() as AsyncEntry<unknown>[]).some((s) => s.isLoading());
Expand Down
1 change: 1 addition & 0 deletions frontend/src/ts/components/common/Headers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function H2(props: {
);
}

// oxlint-disable-next-line monkeytype-rules/one-component-per-file
export function H3(props: {
id?: string;
class?: string;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/ts/components/layout/overlays/FpsCounter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function FpsCounter(): JSX.Element {
let frameCount = 0;
let startTime: number;

function loop(timestamp: number): void {
const loop = (timestamp: number): void => {
if (stopLoop) return;
const elapsedTime = timestamp - startTime;
frameCount++;
Expand All @@ -31,7 +31,7 @@ export function FpsCounter(): JSX.Element {
}

window.requestAnimationFrame(loop);
}
};

createEffect(() => {
if (isVisible()) {
Expand Down
Loading
Loading