A minimal LexTALE application scaffold built with Deno, Hono, and server-side JSX.
- Deno
2.9.0 - Docker with the Compose plugin
- hk for git hooks
- Zed with Dev Containers support when developing inside a container
cp .env.example .env
docker compose -f compose.dev.yaml up -d postgres
deno task --env-file=.env devApplication: http://localhost:8000
Healthcheck: http://localhost:8000/health
Adminer can be started alongside Postgres for browser-based database access:
docker compose -f compose.dev.yaml up -d postgres adminerAdminer: http://localhost:8080
Use these connection settings on the login screen:
- System:
PostgreSQL - Server:
postgres - Username:
elx - Password:
elx - Database:
elx
Fully containerized local startup:
docker compose -f compose.dev.yaml up --buildThis also starts Adminer, so the database UI is available at http://localhost:8080.
Open the repository as a Dev Container. The configuration installs Deno and the
Docker CLI, mounts the host's /var/run/docker.sock, and forwards ports 8000,
5432, and 8080.
From the Dev Container, start Postgres through the host Docker daemon and run the application directly:
docker compose -f compose.dev.yaml up -d postgres
deno task devDo not start the app service from compose.dev.yaml inside the Dev Container:
the /workspaces/elx bind mount is not a valid Docker host filesystem path on
macOS.
deno task ci # fmt, lint, type-check, tests, coverage
deno task --env-file=.env db:generate # create a Drizzle migration
deno task --env-file=.env db:migrate # apply migrations
deno task e2e # Playwright E2ETo import words from external CSV or JSON files, use the import:words task.
Example config to import a CEFR vocabulary list with columns
headword,pos,CEFR,CoreInventory 1,CoreInventory 2,Threshold (where Threshold
is mapped to the definition):
{
"format": "csv",
"delimiter": ",",
"hasHeader": true,
"fields": {
"value": { "from": "headword" },
"isReal": { "from": "pos", "default": true },
"difficulty": {
"from": "CEFR",
"map": {
"A1": 1,
"A2": 2,
"B1": 3,
"B2": 4,
"C1": 5,
"C2": 5
},
"default": 1
},
"definition": { "from": "Threshold" }
},
"onConflict": "update"
}For more details on mapping options and formats, see Word Import Mapping Configuration.
Install hk to enable pre-commit and pre-push hooks:
brew install hk # macOS
hk installPre-commit runs deno fmt --check and deno lint on staged files. Pre-push
runs deno task check (type-check) and deno task test.
See CONTRIBUTING.md for guidelines.
compose.yaml expects a production .env next to the Compose file. At minimum,
it requires:
APP_IMAGE=ghcr.io/owner/elx
APP_TAG=sha-full-git-sha
DOMAIN=example.com
POSTGRES_DB=elx
POSTGRES_USER=elx
POSTGRES_PASSWORD=replace-meThe provisioning template is in deploy/cloud-init.yaml. Replace the SSH key
and configure the DigitalOcean Firewall before using it.
GitHub Actions publishes the image to GHCR and deploys over SSH. The
production environment requires these secrets:
DEPLOY_HOSTDEPLOY_USERDEPLOY_SSH_KEYDEPLOY_PATHGHCR_USERNAMEGHCR_TOKEN
DEPLOY_PATH must contain a repository checkout and a protected production
.env.
.github/workflows/wiki-sync.yaml mirrors docs/ into the GitHub wiki
repository Mkots/elx.wiki.git on each push to main or master that changes
documentation.
Configure the repository secret WIKI_SYNC_TOKEN before enabling the workflow.
Use a GitHub token that can push to Mkots/elx.wiki.git. The workflow treats
docs/ as the source of truth and deletes wiki pages removed from docs/. The
publish step builds a reader-facing wiki view instead of copying the source tree
verbatim:
- YAML frontmatter is stripped from published pages and rendered as a compact metadata section.
- Internal links are rewritten to GitHub Wiki page routes without
.md. - Nested source paths are flattened into stable wiki page names such as
Requirements,Technical-Details, andREQ-WORD-SELECTION. _Sidebar.mdand_Footer.mdare generated automatically.
Create and maintain docs/Home.md as the source landing page for the generated
wiki home.