Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- run: pnpm install --frozen-lockfile

- run: pnpm typecheck

- run: pnpm test

- run: pnpm validate-content

- run: pnpm check-i18n

- run: pnpm build
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
dist
dist-ssr
*.local
.DS_Store
coverage
.turbo
*.log
.env
.env.*
!.env.example
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100
}
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,55 @@
# coderkeys
An open-source, local-first typing tutor tailored for programmers and technical writers to master code syntax and specific vocabularies.
# CoderKeys

Open-source, local-first typing tutor tailored for **programmers** and **technical writers** to master code syntax and real-world vocabularies.

## Features

- **Skill-based tracks** — Programmers (code syntax, symbols) and Technical Writers (requirements, documentation)
- **Bilingual** — Interface and lessons in `en-US` and `pt-BR`
- **100% local** — No backend, no cloud costs; progress saved in IndexedDB
- **Contributor-friendly** — Add lessons by creating JSON files in `content/`

## Quick Start

```bash
git clone https://github.com/iagommendes/coderkeys.git
cd coderkeys
pnpm install
pnpm dev
```

Open [http://localhost:5173](http://localhost:5173) in your browser.

### Other commands

```bash
pnpm build # Production build
pnpm preview # Preview production build locally
pnpm test # Run all tests
pnpm validate-content # Validate lesson JSON files
pnpm check-i18n # Verify translation key parity
```

## Project Structure

```
coderkeys/
├── apps/web/ # React SPA (Vite + Tailwind)
├── packages/engine/ # Typing engine (WPM, accuracy) — framework-agnostic
├── packages/schemas/ # Zod schemas for lessons and progress
├── content/ # Lesson content (contributors edit here)
└── docs/ # Architecture and planning docs
```

## Contributing Lessons

1. Create a JSON file in `content/tracks/{track}/{locale}/{module}/`
2. Follow the schema in `packages/schemas/src/lesson.schema.ts`
3. Run `pnpm validate-content`
4. Open a Pull Request

See [docs/PLANEJAMENTO-ARQUITETURA.md](docs/PLANEJAMENTO-ARQUITETURA.md) for the full architecture plan.

## License

MIT
24 changes: 24 additions & 0 deletions apps/web/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
8 changes: 8 additions & 0 deletions apps/web/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["react", "typescript", "oxc"],
"rules": {
"react/rules-of-hooks": "error",
"react/only-export-components": ["warn", { "allowConstantExport": true }]
}
}
32 changes: 32 additions & 0 deletions apps/web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)

## React Compiler

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).

## Expanding the Oxlint configuration

If you are developing a production application, we recommend enabling type-aware lint rules by installing `oxlint-tsgolint` and editing `.oxlintrc.json`:

```json
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["react", "typescript", "oxc"],
"options": {
"typeAware": true
},
"rules": {
"react/rules-of-hooks": "error",
"react/only-export-components": ["warn", { "allowConstantExport": true }]
}
}
```

See the [Oxlint rules documentation](https://oxc.rs/docs/guide/usage/linter/rules) for the full list of rules and categories.
16 changes: 16 additions & 0 deletions apps/web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⌨</text></svg>" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CoderKeys — Typing Tutor</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
39 changes: 39 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "@coderkeys/web",
"private": true,
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"typecheck": "tsc -b --noEmit",
"test": "vitest run --passWithNoTests",
"lint": "eslint src"
},
"dependencies": {
"@coderkeys/engine": "workspace:*",
"@coderkeys/schemas": "workspace:*",
"clsx": "^2.1.1",
"dexie": "^4.0.11",
"i18next": "^24.2.3",
"i18next-browser-languagedetector": "^8.0.4",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-i18next": "^15.4.1",
"react-router-dom": "^7.4.0",
"tailwind-merge": "^3.0.2",
"zustand": "^5.0.3"
},
"devDependencies": {
"@tailwindcss/vite": "^4.0.14",
"@types/node": "^22.14.0",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.2",
"tailwindcss": "^4.0.14",
"typescript": "^5.8.2",
"vite": "^8.1.0",
"vitest": "^3.0.9"
}
}
1 change: 1 addition & 0 deletions apps/web/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading