# Installation

Many solutions are availble :

1. Node application in dev mode (not compiled)
2. Node application id Production mode (compiled)
3. Docker container

# Instructions

**WASPL - Digital Assessment Platform (Alpha)**  
Status: Alpha  
License: AGPL v3  
Technology Stack: Node.js, Vue 3, MongoDB, Docker

---

### 🧭 Table of Contents

- Overview
- Features
- Architecture
- Getting Started
    
    
    - Local Development (no Docker)
    - Docker Usage
        
        
        - Development Mode (hot-reload)
        - Production Mode (with NGINX)
        - Available `make` Commands
- Environment Variables
    
    
    - Quick Setup (Development)
    - Configuration File Structure
    - Production Configuration
    - Security
- Interaction Types
- Default User
- Project Structure
- Contributing
- License

---

### 📘 Overview

WASPL is an open-source digital assessment platform designed to create, manage, and deliver interactive online tests. Built with modern technologies (Node.js, Vue 3, MongoDB, Docker), it provides educators with powerful tools to design rich and flexible testing experiences.

**⚠️ Pre-Alpha Version**: This software is in active development and not yet ready for production use.

---

### ✨ Features

- **Waspleditor**: Create tests using 12 interactive question types.
- **WasplTestRunner**: Deliver assessments in EXAM or LEARNING mode.
- Rich interactions: drag-and-drop, clickable images, gap-fills, and more.
- **AI Integration**: Automatic scoring and test generation.
- **Internationalization**: Supports 6 languages (EN, FR, ES, DE, IT, PT).
- **MongoDB**: Stores responses and metadata.
- **Strict ESM**: Modern modular imports everywhere.

---

### 🧱 Architecture

WASPL consists of two main applications:

- `waspleditor`: Admin/editor interface to build tests.
- `waspltestrunner`: Interface for test takers.

Both apps use a shared backend and a MongoDB database. Services are orchestrated with Docker.

Full documentation is available at: [https://waspl-wiki.wiquid.fr/](https://waspl-wiki.wiquid.fr/)

---

### 🚀 Getting Started

#### 🔧 Local Development (no Docker)

1. Clone the repository:
    
    <div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none rounded-t-2xl">bash</div><div class="sticky top-9"></div><div class="overflow-y-auto p-4" dir="ltr">`git <span class="hljs-built_in">clone</span> https://github.com/janfix/waspl.git<span class="hljs-built_in">cd</span> waspl`</div></div>
2. Install dependencies:
    
    <div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none rounded-t-2xl">bash</div><div class="sticky top-9"></div><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-built_in">cd</span> waspleditor && npm install<span class="hljs-built_in">cd</span> ../waspltestrunner && npm install`</div></div>
3. Start MongoDB manually (if needed), then:
    
    <div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none rounded-t-2xl">bash</div><div class="sticky top-9"></div><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-built_in">cd</span> ../waspleditor && npm run dev<span class="hljs-built_in">cd</span> ../waspltestrunner && npm run dev`</div></div>

Pre-configured `.env` files are included with safe default values.

#### 🐳 Docker Usage

##### 🧪 Development Mode (hot-reload)

Command:

<div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk-go-copiermodifier-ma"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-built_in">make</span> dev`</div></div>- Waspleditor: [http://localhost:5173](http://localhost:5173)
- WasplTestRunner: [http://localhost:5174](http://localhost:5174)

Services wait for MongoDB before launching.

##### 🚀 Production Mode (with NGINX)

Command:

<div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk-go-copiermodifier-ma-1"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-built_in">make</span> prod`</div></div>- Single entry point: [http://localhost/](http://localhost/)
    
    
    - `/editor/` for the editor
    - `/runner/` for test-taking

NGINX handles redirection, security headers, and gzip compression.

##### ⚙️ Available `make` Commands

<div class="_tableContainer_16hzy_1" id="bkmrk-command-description-"><div class="_tableWrapper_16hzy_14 group flex w-fit flex-col-reverse" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)" data-end="3292" data-start="2941"><thead data-end="2974" data-start="2941"><tr data-end="2974" data-start="2941"><th data-col-size="sm" data-end="2959" data-start="2941">Command</th><th data-col-size="md" data-end="2974" data-start="2959">Description</th></tr></thead><tbody data-end="3292" data-start="3010"><tr data-end="3063" data-start="3010"><td data-col-size="sm" data-end="3029" data-start="3010">`make dev`</td><td data-col-size="md" data-end="3063" data-start="3029">Start all services in dev mode</td></tr><tr data-end="3124" data-start="3064"><td data-col-size="sm" data-end="3083" data-start="3064">`make prod`</td><td data-col-size="md" data-end="3124" data-start="3083">Start all services in production mode</td></tr><tr data-end="3174" data-start="3125"><td data-col-size="sm" data-end="3144" data-start="3125">`make down`</td><td data-col-size="md" data-end="3174" data-start="3144">Stop and remove containers</td></tr><tr data-end="3223" data-start="3175"><td data-col-size="sm" data-end="3194" data-start="3175">`make reset-db`</td><td data-col-size="md" data-end="3223" data-start="3194">Remove MongoDB local data</td></tr><tr data-end="3292" data-start="3224"><td data-col-size="sm" data-end="3243" data-start="3224">`make reset-all`</td><td data-col-size="md" data-end="3292" data-start="3243">Remove all containers, data and Docker images</td></tr></tbody></table>

<div class="sticky end-(--thread-content-margin) h-0 self-end select-none"><div class="absolute end-0 flex items-end"><span class="" data-state="closed"><button class="bg-token-bg-primary hover:bg-token-bg-tertiary text-token-text-secondary my-1 rounded-sm p-1 transition-opacity group-[:not(:hover):not(:focus-within)]:pointer-events-none group-[:not(:hover):not(:focus-within)]:opacity-0"><svg class="icon-md-heavy" fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor" fill-rule="evenodd"></path></svg></button></span></div></div></div></div>---

### ⚙️ Environment Variables

#### 🚀 Quick Setup (Development)

Everything works out of the box after cloning:

<div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk-arduino-copiermodifi"><div class="overflow-y-auto p-4" dir="ltr">`npm run dev`</div></div>#### 📁 Configuration File Structure

<div class="_tableContainer_16hzy_1" id="bkmrk-file-included-descri"><div class="_tableWrapper_16hzy_14 group flex w-fit flex-col-reverse" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)" data-end="3968" data-start="3470"><thead data-end="3541" data-start="3470"><tr data-end="3541" data-start="3470"><th data-col-size="sm" data-end="3490" data-start="3470">File</th><th data-col-size="sm" data-end="3501" data-start="3490">Included</th><th data-col-size="sm" data-end="3541" data-start="3501">Description</th></tr></thead><tbody data-end="3968" data-start="3614"><tr data-end="3684" data-start="3614"><td data-col-size="sm" data-end="3634" data-start="3614">`.env`</td><td data-col-size="sm" data-end="3644" data-start="3634">✅ Yes</td><td data-col-size="sm" data-end="3684" data-start="3644">Base development configuration</td></tr><tr data-end="3755" data-start="3685"><td data-col-size="sm" data-end="3705" data-start="3685">`.env.docker`</td><td data-col-size="sm" data-end="3715" data-start="3705">✅ Yes</td><td data-col-size="sm" data-end="3755" data-start="3715">Docker-specific configuration</td></tr><tr data-end="3826" data-start="3756"><td data-col-size="sm" data-end="3776" data-start="3756">`.env.template`</td><td data-col-size="sm" data-end="3786" data-start="3776">✅ Yes</td><td data-col-size="sm" data-end="3826" data-start="3786">Example with placeholders</td></tr><tr data-end="3897" data-start="3827"><td data-col-size="sm" data-end="3847" data-start="3827">`.env.local`</td><td data-col-size="sm" data-end="3857" data-start="3847">❌ No</td><td data-col-size="sm" data-end="3897" data-start="3857">Local custom variables (ignored)</td></tr><tr data-end="3968" data-start="3898"><td data-col-size="sm" data-end="3918" data-start="3898">`.env.production`</td><td data-col-size="sm" data-end="3928" data-start="3918">❌ No</td><td data-col-size="sm" data-end="3968" data-start="3928">Sensitive production configuration</td></tr></tbody></table>

<div class="sticky end-(--thread-content-margin) h-0 self-end select-none"><div class="absolute end-0 flex items-end"><span class="" data-state="closed"><button class="bg-token-bg-primary hover:bg-token-bg-tertiary text-token-text-secondary my-1 rounded-sm p-1 transition-opacity group-[:not(:hover):not(:focus-within)]:pointer-events-none group-[:not(:hover):not(:focus-within)]:opacity-0"><svg class="icon-md-heavy" fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor" fill-rule="evenodd"></path></svg></button></span></div></div></div></div>#### 🔧 Production Configuration

Create a `.env.local` file with real values:

<div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk-ini-copiermodifier-v"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-attr">VITE_CHATGPT_API</span>=sk-your-openai-key<span class="hljs-attr">VITE_SYSTEM_TOKEN_FOR_TESTRUNNER</span>=your-jwt-token<span class="hljs-attr">JWT_SECRET</span>=your-strong-secret<span class="hljs-attr">MONGO_URI</span>=mongodb://your-server:<span class="hljs-number">27017</span>/waspldata`</div></div>Or use system environment variables:

<div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk-arduino-copiermodifi-1"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-keyword">export</span> VITE_CHATGPT_API=<span class="hljs-string">"sk-your-key"</span><span class="hljs-keyword">export</span> JWT_SECRET=<span class="hljs-string">"your-secret"</span>`</div></div>#### 🛡️ Security

- ✅ Development files use safe defaults and are included
- ❌ Real secrets are excluded from Git
- 🔄 Templates are available to simplify setup

---

### 🎯 Interaction Types

WASPL supports 12 interaction types:

- **Choice**: Classic single or multiple choice
- **Choice Block**: Choice with rich media support
- **Text Puzzle**: Drag-and-drop gap-filling puzzle
- **Text Gaps**: Traditional fill-in-the-blank text
- **Short Answer**: Free-form answer with AI scoring
- **Hot Spot**: Clickable image-based interactions
- **Order**: Sequencing with drag-and-drop
- **Match**: Match pairs between two columns
- **Making Pairs**: Build and assign item pairs
- **Message**: Instructional text without input
- **No Editor**: Raw content mode
- **Default**: Custom base interaction

---

### 🔑 Default User

Default credentials:

- Username: `admin`
- Password: `password`

---

### 📂 Project Structure

<div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk-vbnet-copiermodifier"><div class="overflow-y-auto p-4" dir="ltr">`waspleditor/         → Vue3 + Vite app <span class="hljs-keyword">for</span> test creation  ├─ Dockerfile  └─ Dockerfile.devwaspltestrunner/     → Vue3 + Vite app <span class="hljs-keyword">for</span> test execution<span class="hljs-keyword">shared</span>/              → <span class="hljs-keyword">Shared</span> models <span class="hljs-built_in">and</span> utilsmedia/               → <span class="hljs-keyword">Static</span> files (images, audio)scripts/             → Utility scriptscertbot/             → SSL certificate automationdocker-compose.yml   → Docker orchestration confignginx.conf*          → NGINX config filesMakefile             → CLI helper commands`</div></div>---

### 🤝 Contributing

We welcome contributions!  
Open an issue or submit a pull request.  
Please follow the existing code style and use meaningful commit messages.

#### 🔧 Setup for Contributors

1. Clone the repo:
    
    <div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="overflow-y-auto p-4" dir="ltr">`git <span class="hljs-built_in">clone</span> https://github.com/janfix/waspl.git<span class="hljs-built_in">cd</span> wasplnpm run dev`</div></div>
2. (Optional) Enable AI features:
    
    <div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-built_in">cp</span> waspleditor/.env.template waspleditor/.env.local<span class="hljs-comment"># Then add your OpenAI key</span>`</div></div>
3. Recommended: use Docker
    
    <div class="contain-inline-size rounded-2xl border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-built_in">make</span> dev`</div></div>

---

### 📝 License

This project is licensed under the **AGPL v3**.  
See the LICENSE file for details.