CardTrio
A Python terminal client for three courses, backed by your Google Sheet and a Google Apps Script admin dashboard. Learners submit code or text for manual review. An administrator's approval unlocks the next step.
| Course | Subject | Lesson cards | Challenges |
|---|---|---|---|
| python96 | Python | 48 | 12 |
| BattleAI | HTML | 48 | 12 |
| microduck | JavaScript | 48 | 12 |
Every card includes a lesson, an example, and a practice problem. Every fourth card is followed by a challenge. There are 144 cards and 36 challenges in total. This is an original standalone implementation with no ICOA dependency.
1. Set up Google Apps Script
- Open your course Google Sheet. Choose Extensions → Apps Script.
- Replace the entire previous
Code.gswithapps-script/Code.gsfrom this project. Remove any earlier versions ofdoGet,doPost, or public admin helpers in other files so they cannot conflict with these handlers. - Add a script file named Curriculum and paste
apps-script/Curriculum.gs. - Add an HTML file named Admin and paste
apps-script/Admin.html. - Optionally enable “Show appsscript.json manifest file” in project settings
and replace it with the supplied
apps-script/appsscript.json. - Select setup_ in the editor and run it. Authorize access to the Sheet. The trailing underscore is intentional: it keeps this setup helper private from web-page RPC calls.
- Select Deploy → New deployment → Web app. Execute as Me, and allow Anyone to access the endpoint. Learners are authenticated by their course tokens, and admin actions require a server-validated admin session. If your Workspace account does not permit anonymous web-app access, a plain terminal client cannot use that deployment without an additional Google sign-in flow.
- Copy the production URL ending in
/exec, not/dev.
setup_ seeds the full curriculum automatically; a CSV import is not required.
It creates these tabs and validates their headers:
- Catalog: lessons, practice, challenges, and reference answers.
- Tokens: token, student, courses, active state, optional expiry.
- Reviews: submitted work, status, feedback, review time, revision.
The initial admin password is admin. It is hashed with a random salt and
stored in Script Properties, not in HTML or the Python client. Re-running setup
preserves an existing password and existing data. An existing compatible Catalog
is kept as-is rather than overwritten. Keep the Sheet private to its administrators.
For an unbound Apps Script project, set SPREADSHEET_ID in Script Properties to
your Sheet ID before running setup_. Do not copy another spreadsheet's ID.
2. Open the admin dashboard
Append ?page=admin to your deployed URL:
https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec?page=admin
Sign in with admin. The dashboard provides:
- A queue filtered by course and review status, with pagination.
- Submitted code rendered as text, the problem, lesson context, and a reference answer. Other correct solutions can be approved; exact matching is not required.
- Approve & unlock next step, with optional feedback.
- Request changes, requiring actionable feedback. The learner can revise and submit a new attempt. Earlier attempts remain in the ledger.
- Token issuance for any one course or all three, optional expiration, and enable/disable controls.
- A Settings page for changing the admin password. This revokes existing admin sessions. Sessions otherwise expire after one hour and can expire earlier if Apps Script evicts its cache. Sign in again when prompted.
The dashboard does not run submitted code. HTML is displayed as text, not rendered as a page. The only network requests made by the learner client target Google Apps Script and its Google-hosted response redirects.
3. Install and run the learner client
Requires Python 3.10 or later. There are no runtime third-party dependencies.
From the extracted project directory:
python -m pip install .
cardtrio configure
cardtrio
For an already-built wheel:
python -m pip install dist/cardtrio_terminal-0.2.0-py3-none-any.whl
cardtrio configure
cardtrio
On Windows, py may be used instead of python. If scripts are not on PATH,
use python -m cardtrio and python -m cardtrio configure.
Configure the base /exec URL without ?page=admin. An admin issues access
tokens in the dashboard's Access tokens tab, then provides each learner their
token. Tokens are reusable access codes, not a consumable credit balance.
Shortcuts:
python96
battleai
microduck
cardtrio --course BattleAI
Tokens are entered with a hidden password prompt and are not saved to disk.
CARDTRIO_TOKEN and CARDTRIO_URL can optionally supply login configuration.
The endpoint is stored in ~/.cardtrio/config.json. CARDTRIO_HOME overrides
the local settings directory.
During a lesson
- Enter a short answer and press Enter to submit it for review.
- Use
:multifor multiline code. A line containing only.ends input. - Use
:file PATHto submit a UTF-8 source file after preview and confirmation. - Use
:hintto revisit the lesson rule. - Use
:refreshto check for an admin decision. - Use
:menuto change courses, or:quitto close the program.
Submissions are limited to 8,000 characters. No arbitrary code is executed by
the terminal application or backend. A local outbox preserves unconfirmed
submissions without storing the token. Network retries reuse the request ID,
so a lost response cannot submit the same work twice. If a local retry becomes
obsolete, the retry prompt's d option discards only that local retry; it does
not cancel work already received by the administrator.
Approval is required before the next step becomes available. Completion is derived from the contiguous sequence of approvals in Reviews, keeping progress and the review decision in one authoritative record. Do not manually reorder or change review statuses unless intentionally repairing data.
Updating an earlier draft
Version 0.2 replaces automatic exact-answer grading with manual review. Earlier
Progress and Submissions tabs are not deleted or imported; they remain an
archive. Manual-review progress starts in the new Reviews tab. Existing
compatible Tokens and Catalog tabs are reused. A mismatched header causes setup
to stop rather than replace the sheet's data.
Curriculum maintenance
The authoring source is tools/build_curriculum.py. Regenerate bundled data and
the Apps Script seed after editing it:
python tools/build_curriculum.py
python -m cardtrio check
python -m cardtrio export --output Catalog.csv
The CSV export is optional and useful for editing an existing Catalog. Back up
the Sheet before replacing content. Do not renumber active course steps because
reviews refer to those step numbers. Apps Script source changes require a new
deployment version; simply saving the editor does not update a production /exec
deployment.
Tests
From a source checkout, install the package first or set PYTHONPATH=src:
python -m unittest discover -s tests -p "test_*.py" -v
node tests/test_backend.cjs
The backend tests execute the actual Apps Script source with in-memory Google service doubles. They cover authentication, token permissions, expiration, manual review, feedback, idempotency, revisions, progression, and header safety. They do not replace a live Google deployment test.
The optional browser test requires Node.js, Playwright, and Chromium:
node tests/test_admin_browser.cjs
It uses the real HTML and backend with service doubles, checks the review and
token flows, and saves desktop/mobile screenshots in artifacts/. Set
CHROMIUM_PATH if Chromium is not at /usr/bin/chromium.
PyPI release
The working distribution name is cardtrio-terminal. Availability and ownership
have not been verified. Choose a name you control in pyproject.toml before
publishing. The installed command names can remain unchanged.
python -m pip install build twine
python -m build
python -m twine check dist/*
python -m twine upload --repository testpypi dist/*
After checking TestPyPI and finalizing your package metadata, publish to your
PyPI account with python -m twine upload dist/*. Upload credentials belong in
your publishing environment, not in this package. No PyPI upload or Google
Apps Script deployment is performed merely by installing or running CardTrio.
The MIT license covers this original code and curriculum. There is no ICOA code, content, branding, or service dependency.
References: Python packaging and Apps Script web apps.
Metadata
Release files for cardtrio-terminal 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cardtrio_terminal-0.2.0.tar.gz | 95.9 kB | Without provenance | Details for cardtrio_terminal-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cardtrio_terminal-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for cardtrio_terminal-0.2.0-py3-none-any.whl |
Total release size: 128.1 kB
Release files / cardtrio_terminal-0.2.0.tar.gz
| Download URL | cardtrio_terminal-0.2.0.tar.gz |
|---|---|
| Size | 95.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
12cd430e0123a73b52a5f9711e499dddefa28c2e661f229dbb465b047ede38b7
|
|
BLAKE2b-256 checksum How to use checksums |
8106827d02ee0a7da11e406b3e0306db70d2eae90297e4eeab055742527298e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / cardtrio_terminal-0.2.0-py3-none-any.whl
| Download URL | cardtrio_terminal-0.2.0-py3-none-any.whl |
|---|---|
| Size | 32.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f34589f432d34841f83928b0cff9d497a6e79d78ea615ffc42a4d3056b48a6a5
|
|
BLAKE2b-256 checksum How to use checksums |
76e7fee6b7ea6c6ce15e9b3a929a6080e03595f795a49b0bb594009a61fc2fe3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Security for cardtrio-terminal 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.