The Kai Project is an open-source platform for sharing Japanese graduate school entrance exam questions, solutions, and preparation experience. In addition to the content library itself, the site now includes study tools that help users track progress, take notes, and sync practice records across devices.
"Answer to the Ultimate Question of Life, the Universe, and Everything"
Project website: Japanese graduate school entrance exam answers
- Open past-exam and solution database across multiple universities and departments
- Exam-experience blog posts and preparation write-ups
- Per-question progress tracking with review reminders and a progress dashboard
- Built-in notes on each question page with Markdown and LaTeX support
- Optional login, cloud sync, and weekly leaderboard powered by Supabase
- Local search, PWA/offline support, and share-as-image for answer pages
- Node.js
>=20 - Yarn
>=1.22.0
Install dependencies and start the development server:
yarn install
yarn devThen open http://localhost:3000.
To build and preview the production bundle locally:
yarn build
yarn serveUseful repository scripts:
yarn generate:universities
yarn generate:site-stats
yarn tags:generate
yarn content:validate
yarn tags:audit
yarn review:format
yarn api:validateyarn generate:universities: regeneratesrc/data/universities.jsafter changing thedocs/directory structure or_category_.jsonlabels.yarn generate:site-stats: regeneratesrc/data/siteStats.jsonfrom the same scan used by the public JSON API.yarn tags:generate: regeneratedocs/tags.ymlfromsrc/data/tagTaxonomy.json.yarn content:validate: validate contributor-editable JSON data undersrc/data/, including links, admissions, university metadata, and the tag taxonomy.yarn tags:audit: summarize site-wide school, subject, subsubject, topic, pending, and deprecated tag usage.yarn review:format: review answer-document formatting underdocs/before opening a PR.yarn api:validate: validate the structured data used by the public JSON API.
Contributor-editable content data lives in JSON files under src/data/: links.json, admissions.json, universityMetadata.json, and tagTaxonomy.json. The generated universities.js, siteStats.json, and docs/tags.yml files should be refreshed with the scripts above.
The site works without any cloud credentials: documentation pages, blog posts, local progress tracking, and local notes still work. If the environment variables below are not set, login, cloud sync, and the leaderboard are unavailable.
export SUPABASE_URL="https://your-project.supabase.co"
export SUPABASE_ANON_KEY="your-anon-key"
export HCAPTCHA_SITE_KEY="your-hcaptcha-site-key"SUPABASE_URLandSUPABASE_ANON_KEYenable authentication and cloud sync.HCAPTCHA_SITE_KEYis optional but recommended for abuse protection on the login/register page.
If you want to enable cloud sync end-to-end:
- Create a Supabase project.
- Run src/services/schema.sql in the Supabase SQL editor.
- Configure the auth security items noted in that SQL file, including rate limits, password policy, and hCaptcha.
Registered users can request JSON API access in the developer center. After a project maintainer approves the request, the user can create an API key and read exam and answer data. API keys are shown only once when created; the database stores only SHA-256 hashes.
- Log in on the website and open
/developers, then enter the JSON API feature. You can also open/developers/apidirectly. - Submit an API access request. Intended use is optional; mark the commercial-use checkbox when applicable.
- Wait for project maintainer review. Once approved, the page will allow API key creation.
- Create an API key and save the
kai_live_...value immediately. - Call the content API with
Authorization: Bearer kai_live_.... The content API does not accept anonymous requests or login JWTs.
Available endpoints:
GET /v1/catalog: returns universities, departments, programs, years, and document counts.GET /v1/exams?university=tokyo-university&department=IST&program=cs&year=2024&include=content: queries exam documents;include=contentreturns markdown content.GET /v1/exams?subject=Computer-Science&subsubject=Computer-Science.Computer-Architecture&topic=Computer-Science.Computer-Architecture.Cache: filters by the derived learning taxonomy.GET /v1/exams/{doc_id}: returns one document by ID.
Exam rows include the original frontmatter tags plus derived taxonomy fields: schoolTags, learningTags, subjectIds, subsubjectIds, and topicIds. Topic IDs are namespaced as Subject.Subsubject.Topic; learningTags identifies whether each learning tag is a subsubject, concrete topic, or pending tag, and topic entries include short_id.
Examples:
curl -H "Authorization: Bearer kai_live_..." \
"https://your-project.supabase.co/functions/v1/kai-api/v1/catalog"
curl -H "Authorization: Bearer kai_live_..." \
"https://your-project.supabase.co/functions/v1/kai-api/v1/exams?university=tokyo-university&department=IST&program=cs&year=2024&include=content"
curl -H "Authorization: Bearer kai_live_..." \
"https://your-project.supabase.co/functions/v1/kai-api/v1/exams?subject=Computer-Science&subsubject=Computer-Science.Computer-Architecture&topic=Computer-Science.Computer-Architecture.Cache"Responses always include apiVersion, sourceUrl, license, and contentNotice. Content is provided for personal study and research use only; commercial use requires separate permission.
The project exposes exam data through Supabase Edge Functions while reusing the existing login system as the developer identity layer.
- Run the latest src/services/schema.sql in Supabase.
- Deploy the functions in supabase/functions:
npx supabase functions deploy developer-api-keys --project-ref "$SUPABASE_PROJECT_REF"
npx supabase functions deploy kai-api --project-ref "$SUPABASE_PROJECT_REF"You can also deploy from the Supabase Dashboard Edge Functions editor: create developer-api-keys and kai-api, then add each function's own index.ts, http.ts, and crypto.ts. Each function directory is self-contained and does not import files outside its own directory.
- Sync structured exam documents:
SUPABASE_URL="https://your-project.supabase.co" \
SUPABASE_SERVICE_ROLE_KEY="your-service-role-key" \
yarn api:syncThis command mirrors the current docs/ tree: it upserts current documents and hard-deletes stale exam_documents rows whose doc_id no longer exists locally.
- Confirm the Supabase Function secrets include
API_LOG_SALT, and disable JWT verification for both functions. - Review requests in the
api_access_requeststable from the Supabase Dashboard: setstatustoapprovedto allow key creation, or userejected/revokedto deny or pause access.
The first version gives all approved users the same free limits: 60 requests/minute and up to 3 active keys. api_access_requests and api_keys already reserve fields such as plan and commercial_allowed for future commercial plans and tiered quotas.
The project encourages community contributions through multiple channels:
- Git Pull Requests: For contributors familiar with Git
- Email Submissions: For users who prefer to send content via email
- Community Discussion: Discuss the answers to the questions and your experience with the exam via the QQ group, or let us know if the answers are wrong via GitHub issues!
All answer-document contributions under docs/ should follow a consistent structure.
Each answer markdown document should look like this:
---
sidebar_label: 'Title displayed in sidebar'
tags:
- Tokyo-University
- Subsubject-Tag
- Topic-Tag
---
# Full page title
## **Author**
[Your Name](https://example.com)
## **Description**
Problem statement, transcription, or a short summary of the question.
## **Kai**
Your solution, derivation, explanation, or notes.Rules enforced by the repository formatter:
sidebar_labelis required.tagsis required.- The first non-empty line after frontmatter must be an H1 title.
## **Author**is required.## **Description**and## **Kai**are optional individually, but at least one of them must exist.- If both are present, keep the order
Author→Description→Kai.
Tag rules:
- Prefer existing canonical subsubject IDs and namespaced topic IDs from src/data/tagTaxonomy.json. Top-level subject tags and legacy short topic tags are not valid frontmatter tags.
- Subject associations in the taxonomy should be strong associations found in actual problem content, not broad theoretical overlap.
- School tags remain compatible, but the site primarily derives school metadata from the
docs/school/department/...path. - Correct new subsubject or topic tags are allowed;
yarn review:formatreports them as warnings instead of blocking the PR. - Deprecated or typo tags are reported as errors with the canonical replacement.
- If a document only has a school tag and no learning tag, the formatter reports a warning. If it has only a subsubject tag, the formatter suggests adding a more concrete topic when the problem statement has enough signal.
Before opening a PR, please run:
yarn review:format
yarn tags:auditBlog posts should use author IDs defined in blog/authors.yml, not inline author objects.
- Add a new author entry to blog/authors.yml, or reuse an existing one.
- Reference that author ID in the post frontmatter.
Example:
---
title: Post title
authors: yourAuthorId
tags: [Tag1, Tag2]
---For reference, existing posts such as blog/2025-04-02-furry.md and blog/2025-07-10-unagoya.md already use author IDs.
Files must be placed in the correct directory structure and follow naming conventions:
- Base directory:
docs/ - Hierarchy:
school/department/major/academic year/ - Filename: should indicate the specific content details (school abbreviation, exam year/month, subject, question number)
docs/
├── <university>/
│ ├── <department>/
│ │ ├── <specialization>/
│ │ │ ├── <academic year>/
│ │ │ │ └── <exam_file>.md
blog/
├── <blog_post>.md
Example:
docs/tokyo-university/engineering/ap/2020/ap_201908_phys_3.md
This corresponds to:
- School: Tokyo University
- Department: Engineering
- Major: Applied Physics (
ap) - Year and month of the exam:
201908 - Subject: Physics
- Question number:
3
For contributors who are not familiar with Git, the project accepts contributions via email.
Steps for email submission:
- Prepare your content following the formatting guidelines above.
- Please read our Contributor License Agreement (CLA).
- Send your content to the project email address: 376672994@qq.com.
- Include the following statement in your email body: "I have read and agree to The Kai Project CLA."
- Project maintainers will review your submission and add it to the repository if approved.
Before we can merge your contributions, you must sign our Contributor License Agreement (CLA).
For GitHub users (Pull Requests): CLA signing is now checked automatically by the workflow in this repository: .github/workflows/cla-check.yml.
After opening a PR, please add a signature statement in any one of these places (by the PR author):
- PR description
- PR conversation comment
- PR review comment
Accepted statements:
I have read the CLA Document and I sign the CLA
I have read and agree to The Kai Project CLA.
If no statement is detected, the CLA 检查 workflow will fail and leave a reminder comment. Once a valid statement is added, the check will pass automatically.
For non-GitHub users (Email submissions): As mentioned above, include the statement "I have read and agree to The Kai Project CLA." in the email body.
The Kai Project maintains a QQ group for community discussion about exam solutions and your experience with the exam, or let us know if the answers are wrong via GitHub issues!
Feedback received through community discussions may be incorporated into the repository by maintainers or used to guide future contributions.
All code contributions to The Kai Project are subject to the GNU Affero General Public License v3.0.
In addition, exam question copyright belongs to the respective schools/institutions.
The Kai Project acknowledges all contributors in maintaining and expanding this knowledge base.
If you believe any content infringes on your rights, please contact the project maintainers immediately.
