Cojak is a Flask-based web application that provides comprehensive reference access to Asian language character databases, primarily Unihan, CEDICT, and RADK (Radical Array Kanji Dictionary). It's designed as both a learning tool for students and a reference database for developers, accessible through an intuitive web interface.
Originally created in 2005 as a PHP application, Cojak has been rewritten in Python/Flask to provide modern, performant access to interconnected Unicode and East Asian linguistic data.
| Radical index | Character detail |
|---|---|
![]() |
![]() |
-
Radical Charts: Browse characters organized by radical and stroke count
- Kangxi radicals
- CJK radicals
- RADK (Radical Array Kanji Dictionary)
- Each radical links to all characters that contain it
-
Syllable Index: Interactive Mandarin pinyin matrix
- Organized by initials (consonants) and finals (vowel components)
- Includes all valid Mandarin syllables with tone marks
- Click any syllable to see all characters pronounced that way
-
Name Indices: Chinese naming character databases
- Surname index with usage frequency
- Given name indices (general, male-only, female-only, ambigender)
- Shows character count and percentage of usage
-
School Grade Characters: Hong Kong primary school curriculum
- Grades 1-6 with traditional/simplified variants
- Organized by stroke count
-
USENET Frequency: Common characters by usage frequency
- Three frequency tiers
- Traditional and simplified variants
-
Character Detail Viewer: Comprehensive information on any character
- Unicode codepoint and hanzi form
- Radical and stroke analysis
- Mandarin, Cantonese, Japanese (on/kun), Korean, and Vietnamese readings
- English definitions
- Character variants (traditional/simplified)
-
Today's Character: Date-based character selection
-
Random Character: Browse random characters from the database
- Global Visitor Map: Displays all unique visitors as points on an interactive map
- Tracks IP address, latitude, and longitude
- Visualizes geographic distribution of Cojak users worldwide
- Accessible at
/map
Cojak interweaves multiple authoritative Asian language databases:
- Unihan: The Unicode Han Unification database
- CEDICT: Chinese-English Dictionary
- RADK: Radical Array Kanji Dictionary
Characters are cross-linked across all databases, allowing you to discover connections between stroke patterns, pronunciation, definitions, and usage.
- Python 3.12+
- Flask 3.0+
- SQLAlchemy 2.0+
- SQLite 3
See requirements.txt for complete dependency list.
- Clone the repository:
git clone https://github.com/dharbigt/cojak.git
cd cojak- Create a virtual environment:
python3 -m venv geo
source geo/bin/activate- Install dependencies:
pip install -r requirements.txt- Configure environment variables:
cp .env.example .env
# Edit .env — at minimum set SECRET_KEY to a long random value:
python3 -c "import secrets; print(secrets.token_hex(32))"- Obtain the database (see Database section below)
# Development server
python run.py
# Or via Flask directly
export FLASK_APP=run.py
export FLASK_ENV=development
flask runThe application will be available at http://localhost:5000
# Production (gunicorn)
gunicorn -w 4 -b 0.0.0.0:8000 run:appCojak uses a pre-populated SQLite database (instance/cojak.db) containing:
Character & Linguistic Data:
- unihan: Main Unihan character data with phonetic readings, definitions, and stroke information
- unihan_radicals: Kangxi radical definitions and Unicode values
- unihan_folded_radicals: CJK and other radical classification systems
- radk_index: Radical Array Kanji Dictionary cross-reference
- cedict_entries: CEDICT Chinese-English dictionary entries
- cedict_index: CEDICT character index for lookup
- names_index: Chinese name character usage statistics
Analytics:
- visitors: User tracking table with fields:
ip(unique IP address),latitude,longitude
The compiled database (instance/cojak.db, ~113 MB) is not included in this repository. It is distributed as compressed SQL table dumps in a companion repository:
cojak-db — SQL dumps, one file per table, compressed with gzip
# After cloning cojak-db alongside this repo:
mkdir -p instance
for f in cojak-db/*.sql.gz; do gunzip -c "$f" | sqlite3 instance/cojak.db; doneAlternatively, download a pre-built cojak.db release from the cojak-db releases page and place it at instance/cojak.db.
The original import scripts (import/edict/, etc.) predate current distribution formats for Unihan and CEDICT. The database distributed via cojak-db represents a curated snapshot. Pull requests to update or replace the import scripts for current upstream formats are welcome.
Once instance/cojak.db is in place the application starts without further setup. To reset, delete the file and re-import from cojak-db.
cojak/
├── app/ # Main Flask application
│ ├── __init__.py # App factory and main routes
│ ├── config.py # Configuration
│ ├── models.py # Database models (User, Place)
│ ├── static/ # CSS, JS, images
│ │ ├── css/ # Stylesheets
│ │ ├── js/ # Client-side JavaScript
│ │ └── json/ # Static data files
│ ├── templates/ # HTML templates (Jinja2)
│ └── user/ # User authentication (legacy)
├── edict/ # Original data import scripts
├── geo/ # Python virtual environment
├── migrations/ # Alembic database migrations
├── instance/ # Instance-specific files
│ └── cojak.db # SQLite database
├── index.wsgi # WSGI entry point
└── requirements.txt # Python dependencies
- Framework: Flask 3.0.3
- Database: SQLite with SQLAlchemy 2.0
- ORM: Flask-SQLAlchemy
- Frontend: Jinja2 templates, vanilla JavaScript
- Security: Flask-WTF (CSRF protection), Flask-Bcrypt
- Server: WSGI-compatible (tested with gunicorn)
All routes serve primarily HTML templates except the /unihan/* and /cedict/* endpoints which return JSON.
Character Browsers:
/or/index- Radical index (Kangxi)/kangxi_index- Kangxi radical chart/cjk_index- CJK radical chart/radk_index- RADK (Hanzi structure components)/radk/<unicode>- Characters using a specific RADK component/syllable_index- Mandarin syllable matrix/syllable/<syllable>- Characters with given syllable pronunciation/surname_index,/gn_index,/bgn_index,/ggn_index,/agn_index- Various name indices/school_index/<grade>- School characters by grade (1-6)/usenet_index/<frequency>- Characters by frequency tier (1-3)/zi/- Interactive character viewer/zi/<codepoint>- Character detail page/zi/today- Today's character/zi/random- Random character
API Endpoints (JSON):
/unihan/detail/<row_id>- Full character details/unihan/batch- Paginated character batch/unihan/radicals- All radicals with metadata/cedict/entries/<codepoint>- Dictionary entries for a character/cedict/search/<term>- Search dictionary by definition
Information:
/about- About page (data sources, project info)/donate- Donation page/convert- Text to HTML entity converter
The Unicode Han Unification database. Primary source for character definitions, pronunciations, and structural information.
Note: The original data source information is maintained on the /about page. As of this writing, that page may be outdated as Unihan and other databases have changed their distribution formats.
Chinese-English Dictionary - comprehensive bilingual dictionary with example usage.
Radical Array Kanji Dictionary - organizes kanji by radical and structural components.
All secrets and deployment-specific values are set via environment variables loaded from a .env file (see .env.example).
| Variable | Required | Default | Description |
|---|---|---|---|
SECRET_KEY |
yes | — | Flask session signing key. Generate with secrets.token_hex(32) |
FLASK_ENV |
no | production |
Set to development to enable debug mode |
MAIL_SERVER |
no | smtp.gmail.com |
SMTP server for registration emails |
MAIL_PORT |
no | 587 |
SMTP port |
MAIL_USE_TLS |
no | true |
Enable STARTTLS |
MAIL_USERNAME |
no | — | SMTP login username |
MAIL_PASSWORD |
no | — | SMTP login password or app password |
The database is always loaded from instance/cojak.db relative to the project root.
Cojak has been hosted continuously since 2005. For deployment:
- Use a WSGI application server (e.g., gunicorn, uWSGi)
- Configure a reverse proxy (e.g., Nginx, Apache)
- Ensure the
instance/cojak.dbfile persists between deployments - Set
SESSION_COOKIE_SECURE = Trueif using HTTPS
gunicorn -w 4 -b 0.0.0.0:8000 --access-logfile - index:appSee .env.example and the Configuration table above. In production, set these in your process manager or web server environment rather than in a .env file.
# To be configuredAlembic is configured for database schema migrations:
flask db upgrade # Apply migrations
flask db migrate # Generate new migrationThis project was ported from PHP (2005-present). Some scaffolding from the Flask template may remain:
- User authentication system - Likely to be removed
- Place model and related code - May be removed in future cleanup
The /deck and /exchange endpoints are placeholders for future gameplay features and are currently stubbed out.
Cojak is free software released under the GNU General Public License v3.0.
The compiled database distributed via cojak-db is derived from:
- Unihan — © Unicode, Inc. (Unicode Terms of Use)
- CC-CEDICT — Creative Commons Attribution-Share Alike 3.0
- KANJIDIC / RADK — © The Electronic Dictionary Research and Development Group (CC BY-SA 4.0)
Each dataset's own license terms apply to its data.
Bug reports and pull requests are welcome. For significant changes, please open an issue first to discuss what you'd like to change.
Areas where contributions are especially useful:
- Updated import scripts for current Unihan / CEDICT / RADK distribution formats
- Test coverage
- Accessibility improvements
For questions about the Cojak database or this implementation, see the /about page or open a GitHub issue.
Cojak — Making Asian linguistic databases accessible and intertwined since 2005.

