W2QTI converts questions written in a Microsoft Word document into QTI 2.2 packages ready to import into assessment platforms like TAO.
Supported interaction types:
| Interaction | Description |
|---|---|
choiceInteraction |
Single-choice and multiple-choice questions (bulleted list in Word) |
matchInteraction |
Grid-matching questions (table with empty top-left corner in Word) |
extendedTextInteraction |
Open-ended questions (free-text response, no answer list) |
associateInteraction |
Pair-matching questions (2-column table in Word) |
The converter works entirely in the browser — no data is stored on the server, no cookies, no account required.
Available in English and French — two Word templates are provided (cmod_en.docx / cmod_fr.docx).
Structure your Word document using native Word formatting — no special syntax, no asterisks.
| Element | Word formatting |
|---|---|
| Question | Numbered list (List Number style) |
| Answer | Bulleted list (List Bullet style), indented under the question |
| Correct answer(s) | Bold the answer text |
Example (as seen in Word):
1. Which of the following is the capital of France?
• London
• Paris ← bold in Word
• Berlin
• Madrid
2. What is the chemical symbol for water?
• CO2
• H2O ← bold in Word
• NaCl
Structure your grid-matching question as a Word table:
- Top-left cell: empty (this distinguishes it from
associateInteraction) - First row: column headers (right-hand set of choices)
- First column: left-hand items (stems)
- Mark correct associations with a bold X (bold cell content = correct)
Write a numbered list item with no bullet sub-list — the absence of answers signals an open-ended question requiring a free-text response.
You can also nest a numbered sub-list (List Number style) under a question: each sub-item then becomes its own independent open-ended question.
Example (as seen in Word):
1. Describe the main causes of the French Revolution.
(no bullet list below → open-ended)
2. Answer each of the following:
1. What is photosynthesis?
2. Where does it take place?
(nested numbered list → two separate open-ended questions)
Structure your pair-matching question as a 2-column Word table with no empty top-left corner:
- Each row defines one correct pair (left item → right item)
- All cell values are pooled into the set of choices presented to the learner
Example (as seen in Word):
| Country | Capital |
|---|---|
| France | Paris |
| Germany | Berlin |
| Spain | Madrid |
| Feature | matchInteraction |
associateInteraction |
|---|---|---|
| Table shape | Any size (m × n) | 2 columns only |
| Top-left cell | Empty | Non-empty |
| Correct answers | Bold cell content | Each row = one pair |
Download one of the ready-to-use templates to get started:
- cmod_en.docx — English template
- cmod_fr.docx — French template
- Docker and Docker Compose
- Git
No PHP, Composer, or Node.js installation is required on the host machine.
1. Clone the repository
git clone <repository-url>
cd W2QTI_choiceInteraction2. Install PHP dependencies
Use a temporary Docker container to run Composer (no local PHP needed):
docker run --rm -u "$(id -u):$(id -g)" \
-v "$(pwd):/var/www/html" \
-w /var/www/html \
laravelsail/php83-composer:latest \
composer install --ignore-platform-reqs3. Create the environment file
cp .env.example .envOpen .env and set the database driver to SQLite (the app does not use a database, but Laravel requires a valid driver):
DB_CONNECTION=sqlite
4. Build and start the container
docker compose build
docker compose up -d5. Generate the application key (first run only)
docker exec w2qti_choiceinteraction-app-1 php artisan key:generate6. Fix storage permissions (first run only, or after a fresh clone)
docker exec -u root w2qti_choiceinteraction-app-1 \
chmod -R 777 storage bootstrap/cache7. Open the app
http://localhost:8080
Pull the latest changes and rebuild the Docker image:
git pull
docker compose down
docker compose build --no-cache
docker compose up -dIf composer.json changed, reinstall PHP dependencies before rebuilding:
docker run --rm -u "$(id -u):$(id -g)" \
-v "$(pwd):/var/www/html" \
-w /var/www/html \
laravelsail/php83-composer:latest \
composer install --ignore-platform-reqs| Action | Command |
|---|---|
| Start | docker compose up -d |
| Stop | docker compose down |
| View logs | docker logs w2qti_choiceinteraction-app-1 |
| Open a shell | docker exec -it w2qti_choiceinteraction-app-1 bash |
| Rebuild image | docker compose build --no-cache |
| Layer | Technology |
|---|---|
| Backend | PHP 8.3, Laravel 9 |
| Frontend | JavaScript (ES modules), Bootstrap 5, jQuery |
| Word parsing | Mammoth.js |
| Packaging | JSZip |
| Containerization | Docker / Apache |

