diff --git a/deadlock-plugins/deadlock-extension/.vscode/launch.json b/deadlock-plugins/deadlock-extension/.vscode/launch.json
index 44ec2a1b7c4c09cb5626d28802fa3272b7862365..71f1eaee1da467cf15e99ba14b73062132c45f8f 100644
--- a/deadlock-plugins/deadlock-extension/.vscode/launch.json
+++ b/deadlock-plugins/deadlock-extension/.vscode/launch.json
@@ -20,7 +20,9 @@
       "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
       "outFiles": ["${workspaceFolder}/dist/**/*.js"],
       "env": {
-        "DL_MOUNT_EXTENSION": "true"
+        "DL_MOUNT_EXTENSION": "true",
+        // TODO: SETTING: replace with your own extension path
+        "EXTENSION_PATH": "${workspaceFolder}/deadlock-coding-0.1.10.vsix"
       },
       "preLaunchTask": "${defaultBuildTask}"
     },
@@ -33,7 +35,7 @@
       "env": {
         "DL_MOUNT_EXTENSION": "true",
         // TODO: SETTING: replace with your own extension path
-        "EXTENSION_PATH": "/home/takima/Desktop/d-projects/deadlock-desktop/deadlock-plugins/deadlock-extension/deadlock-coding-0.1.10.vsix"
+        "EXTENSION_PATH": "${workspaceFolder}/deadlock-coding-0.1.10.vsix"
       },
       "preLaunchTask": "tasks: build and watch"
     },
diff --git a/deadlock-plugins/deadlock-extension/.vscodeignore b/deadlock-plugins/deadlock-extension/.vscodeignore
index 62bf20897c27705b453c85d440e97fb4f0d9bc2a..358029d704b76e53507a98a2ae97de7d33de94bd 100644
--- a/deadlock-plugins/deadlock-extension/.vscodeignore
+++ b/deadlock-plugins/deadlock-extension/.vscodeignore
@@ -4,4 +4,3 @@ out/
 src/
 dev/
 tsconfig.json
-node_modules
\ No newline at end of file
diff --git a/deadlock-plugins/deadlock-extension/package.json b/deadlock-plugins/deadlock-extension/package.json
index badb37739425fa8925e11efa2fb924dbebd86dd6..bd2be05fb0d82950b6d6d0e3d739ee55c61844f9 100644
--- a/deadlock-plugins/deadlock-extension/package.json
+++ b/deadlock-plugins/deadlock-extension/package.json
@@ -59,16 +59,22 @@
           "when": "deadlock.inContainer"
         },
         {
-          "id": "help",
-          "name": "Help",
-          "visibility": "visible"
+          "id": "startedMissions",
+          "type": "webview",
+          "name": "Started Missions",
+          "contextualTitle": "Deadlock",
+          "when": "!deadlock.inContainer"
         },
         {
           "id": "commandTree",
           "name": "Commands",
-          "icon": "media/dep.svg",
           "contextualTitle": "Deadlock",
           "when": "deadlock.inContainer"
+        },
+        {
+          "id": "help",
+          "name": "Help",
+          "visibility": "visible"
         }
       ]
     },
diff --git a/deadlock-plugins/deadlock-extension/resources/js/startedMissionsView.js b/deadlock-plugins/deadlock-extension/resources/js/startedMissionsView.js
new file mode 100644
index 0000000000000000000000000000000000000000..413890dc390885265b4f4df95454bb4bde693a43
--- /dev/null
+++ b/deadlock-plugins/deadlock-extension/resources/js/startedMissionsView.js
@@ -0,0 +1,8 @@
+const vscode = acquireVsCodeApi();
+
+function openMission(mission) {
+  vscode.postMessage({
+    command: 'openMission',
+    mission: mission,
+  });
+}
diff --git a/deadlock-plugins/deadlock-extension/resources/styles/startedMissionsView.css b/deadlock-plugins/deadlock-extension/resources/styles/startedMissionsView.css
new file mode 100644
index 0000000000000000000000000000000000000000..2ad5394eda129f3a5291d7289bd9703d9cbd7f55
--- /dev/null
+++ b/deadlock-plugins/deadlock-extension/resources/styles/startedMissionsView.css
@@ -0,0 +1,6 @@
+.item {
+    width: 100%;
+    margin: 1em 0em 0em 0em;
+    word-wrap: normal;
+    justify-content: center;
+}
\ No newline at end of file
diff --git a/deadlock-plugins/deadlock-extension/src/core/api.service.ts b/deadlock-plugins/deadlock-extension/src/core/api.service.ts
index 7087949b9710fbdbfc01947357852b9f71fd19c4..90a1716d0df33c1d0d8641150bd502b3a519ff56 100644
--- a/deadlock-plugins/deadlock-extension/src/core/api.service.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/api.service.ts
@@ -2,11 +2,11 @@ import axios, { AxiosError, AxiosInstance } from 'axios';
 import { API_QUERY_REFERER, API_URL } from '../config';
 import { GiteaPublicProperties } from '../model/giteaPublicProperties.model';
 import { SshKeyPair } from '../model/sshKeyPair.model';
-import { User } from '../model/user.model';
 import { extensionError as error } from '../recorder/utils/log';
 import Controller from './controller';
 import ExtensionStore from './extensionStore';
 import KeycloakOAuth2DeviceFlowConnection from './keycloakOAuth2DeviceFlowConnection';
+import { User } from './mission/models/userChallenge';
 
 export default class ApiService {
   private axiosInstance: AxiosInstance;
@@ -128,7 +128,7 @@ export default class ApiService {
     return res.data;
   }
 
-  async getUser(userId: string | null): Promise<User> {
+  async getUser(userId?: string): Promise<User> {
     if (!userId) return this.getCurrentUser();
     const res = await this.axiosInstance.get<User>(`users/${userId}`);
     return res.data;
diff --git a/deadlock-plugins/deadlock-extension/src/core/controller.ts b/deadlock-plugins/deadlock-extension/src/core/controller.ts
index bd342ee76dc9332fda2d60c7df1e049aa5315247..b93c6060deb7a59f8701dc8292636c907064819f 100644
--- a/deadlock-plugins/deadlock-extension/src/core/controller.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/controller.ts
@@ -6,15 +6,16 @@ import ExtensionStore from './extensionStore';
 import KeycloakOAuth2DeviceFlowConnection from './keycloakOAuth2DeviceFlowConnection';
 import ApiService from './api.service';
 import { GiteaPublicProperties } from '../model/giteaPublicProperties.model';
-import { User } from '../model/user.model';
-import { Mission } from './mission/mission';
+import { Mission } from './mission/models/mission';
 import { MissionDevContainer } from './mission/missionDevContainer';
 import { extensionLog as log } from '../recorder/utils/log';
 import { commands, ExtensionContext, Uri, window } from 'vscode';
 import { createSshKeyFiles, isSshKeyPairExist } from './sshKeyManager';
 import { hasStatusNumber } from './utils/typeguards';
+import { User } from './mission/models/userChallenge';
 
 export default class Controller {
+  private static instance: Controller;
   public connection: KeycloakOAuth2DeviceFlowConnection;
   private commandHandler: CommandHandler;
   private briefingView: BriefingView;
@@ -22,7 +23,7 @@ export default class Controller {
   private extensionStore: ExtensionStore;
   private apiService: ApiService;
 
-  constructor(private context: ExtensionContext) {
+  private constructor(context: ExtensionContext) {
     this.extensionStore = ExtensionStore.getInstance(context);
     this.briefingView = new BriefingView();
     this.quickSetupView = new QuickSetupView(context.extensionUri);
@@ -38,6 +39,13 @@ export default class Controller {
     this.init();
   }
 
+  public static getInstance(context: ExtensionContext): Controller {
+    if (!Controller.instance) {
+      Controller.instance = new Controller(context);
+    }
+    return Controller.instance;
+  }
+
   private async init() {
     const that = this;
     window.registerUriHandler({
@@ -47,7 +55,7 @@ export default class Controller {
         // TODO: Should we follow eslint no-case-declarations ?
         const missionId = queryParams.get('missionId');
         const missionVersion = queryParams.get('missionVersion');
-        const userId = queryParams.get('userId');
+        const userId = queryParams.get('userId') ?? undefined;
         log('Opening link', uri);
 
         switch (action) {
@@ -113,7 +121,7 @@ export default class Controller {
     commands.executeCommand(openUrlInBrowserCommand.cmd, Uri.parse(url));
   }
 
-  public async launchMission(missionId: string, missionVersion: string, userId: string | null) {
+  public async launchMission(missionId: string, missionVersion: string, userId?: string) {
     window.showInformationMessage(`vous lancez la mission ${missionId}`);
     const hadMissionWorkdir = this.extensionStore.getMissionWorkdir() !== undefined;
     if (!hadMissionWorkdir) {
diff --git a/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts b/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts
index 8350f2abb651049db4faeaa6b70f4f84a098742d..cccd611ddb70fa4bbab305d7662fd5ab4454427e 100644
--- a/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts
@@ -1,14 +1,14 @@
 import { userSshKeyFolderPath } from '../config';
-import { Base, DockerfileSpecific, LifecycleScripts, VSCodespecific } from './devContainer';
+import { Base, DockerfileSpecific, LifecycleScripts, VSCodespecific } from './models/devContainer';
 import { mkdir, writeFile } from 'fs/promises';
-import { Mission } from './mission';
-import { User, UserChallengeJson } from '../../model/user.model';
+import { Mission } from './models/mission';
 import { GiteaPublicProperties } from '../../model/giteaPublicProperties.model';
 import { commands, Uri } from 'vscode';
 import { existsSync, copyFileSync } from 'fs';
 import { join } from 'path';
 
 import assert = require('assert');
+import UserChallenge, { User } from './models/userChallenge';
 
 const remoteUserHomeDir = '/home/deadlock';
 const remoteMissionDir = `${remoteUserHomeDir}/mission/`;
@@ -30,7 +30,7 @@ export class MissionDevContainer {
   ) {
     let prefix = `${this.missionsWorkdir}`;
     if (this.isReviewingStudent()) {
-      prefix += `/students/${this.user.details.lastName}_${this.user.details.firstName}-${this.user.id}`;
+      prefix += `/students/${this.user.details.lastName}_${this.user.details.firstName}_${this.user.id}`;
     }
     this.dirs = {
       missionWorkdir: `${prefix}/${this.mission.id}`,
@@ -66,14 +66,15 @@ export class MissionDevContainer {
     return writeFile(
       `${this.dirs.config}/user-challenge.json`,
       (() => {
-        const userChallengeJson: UserChallengeJson = {
+        const userChallengeJson: UserChallenge = {
           giteaHost: this.giteaProperties.sshHost,
           giteaSshPort: this.giteaProperties.sshPort,
           username: this.user.id.split('-').join(''),
           email: `${this.user.id.split('-').join('')}@deadlock.io`,
           missionId: this.mission.id,
+          missionVersion: this.mission.version,
           remoteGitUsername: this.user.id.split('-').join(''),
-          currentUserDetails: this.currentUser ? this.currentUser.details : this.user.details,
+          currentUserDetails: this.currentUser.details,
           remoteUserDetails: this.user.details,
         };
         return JSON.stringify(userChallengeJson, null, 2);
@@ -99,15 +100,14 @@ export class MissionDevContainer {
   private createDevContainerFile(options?: Partial<DockerfileSpecific & Base & VSCodespecific & LifecycleScripts>) {
     const hostMissionDevcontainerFileDir = `${this.dirs.devcontainer}/devcontainer.json`;
     const image = `${this.dockerImageUrl}/${this.mission.id}:${this.mission.version}`;
-    let extTarget;
+    let extTarget: string;
     this.mounts.push(
       `source=${userSshKeyFolderPath},target=/tmp/.ssh,type=bind,consistency=cached,readonly`,
       `source=${this.dirs.config},target=/home/config/,type=bind,consistency=cached,readonly`,
       'source=/etc/hosts,target=/etc/hosts,type=bind,consistency=cached,readonly',
     );
     if (process.env.DL_MOUNT_EXTENSION === 'true') {
-      const extPath =
-        '/home/takima/Desktop/d-projects/deadlock-desktop/deadlock-plugins/deadlock-extension/deadlock-coding-0.1.10.vsix';
+      const extPath = process.env.EXTENSION_PATH;
       extTarget = '/injected-extension/extension.vsix';
       this.mounts.push(`source=${extPath},target=${extTarget},type=bind`);
     } else {
diff --git a/deadlock-plugins/deadlock-extension/src/core/mission/devContainer.ts b/deadlock-plugins/deadlock-extension/src/core/mission/models/devContainer.ts
similarity index 100%
rename from deadlock-plugins/deadlock-extension/src/core/mission/devContainer.ts
rename to deadlock-plugins/deadlock-extension/src/core/mission/models/devContainer.ts
diff --git a/deadlock-plugins/deadlock-extension/src/core/mission/mission.ts b/deadlock-plugins/deadlock-extension/src/core/mission/models/mission.ts
similarity index 100%
rename from deadlock-plugins/deadlock-extension/src/core/mission/mission.ts
rename to deadlock-plugins/deadlock-extension/src/core/mission/models/mission.ts
diff --git a/deadlock-plugins/deadlock-extension/src/model/user.model.ts b/deadlock-plugins/deadlock-extension/src/core/mission/models/userChallenge.ts
similarity index 52%
rename from deadlock-plugins/deadlock-extension/src/model/user.model.ts
rename to deadlock-plugins/deadlock-extension/src/core/mission/models/userChallenge.ts
index 7744bdc8f081d3c950926eb76932c3dc6078225b..46f75dd7403b2e67556fd5458ab656ab5b0069bf 100644
--- a/deadlock-plugins/deadlock-extension/src/model/user.model.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/mission/models/userChallenge.ts
@@ -1,37 +1,30 @@
-import { GiteaPublicProperties } from './giteaPublicProperties.model';
-
-export interface User {
-  id: string;
-  details: UserDetails;
-}
-
-export interface UserDetails {
-  firstName: string;
-  lastName: string;
-  organization: string;
-  email: string;
-  login: string;
-  roles: string[];
-  avatarUrl: string;
-}
-
-export interface UserChallengeJson {
+interface UserChallenge {
   giteaHost: string;
   giteaSshPort: number;
   username: string;
   email: string;
   missionId: string;
+  missionVersion: string;
   remoteGitUsername: string;
   currentUserDetails: UserDetails;
   remoteUserDetails: UserDetails;
 }
 
-export interface UserChallengeJson2 {
-  gitea: Pick<GiteaPublicProperties, 'sshPort' | 'sshHost'>;
-  username: string;
+export default UserChallenge;
+
+export interface UserDetails {
+  firstName: string;
+  lastName: string;
+  organization: string;
   email: string;
-  missionId: string;
-  remoteGitUsername: string;
-  currentUserDetails: UserDetails;
-  remoteUserDetails: UserDetails;
+  login: string;
+  roles: Set<
+    'ADMIN' | 'MANAGER' | 'OFFLINE_ACCESS' | 'PROFESSOR' | 'UMA_AUTHORIZATION' | 'CANDIDATE' | 'DEFAULT-ROLES-DEADLOCK'
+  >;
+  avatarUrl: string;
+}
+
+export interface User {
+  id: string;
+  details: UserDetails;
 }
diff --git a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts b/deadlock-plugins/deadlock-extension/src/core/userConfig.ts
index 0f68f1fd05c455d27197d9aba1faba4cde7f699f..2d6928893d12283da2731d41db7a7a20d1a919aa 100644
--- a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/userConfig.ts
@@ -14,8 +14,8 @@
  * "missionId":"code_persist_cdb_crud"
  * }
  */
-import { UserDetails } from '../model/user.model';
 import { recorderError as error } from '../recorder/utils/log';
+import { UserDetails } from './mission/models/userChallenge';
 
 export default abstract class UserConfig {
   private userConfigJson: any | undefined;
diff --git a/deadlock-plugins/deadlock-extension/src/extension.ts b/deadlock-plugins/deadlock-extension/src/extension.ts
index 3f52e208f5b7ffa487996eb8b25f324c79339991..6e86ff1ba0c025ba32b57bf4630f349669d1e43a 100644
--- a/deadlock-plugins/deadlock-extension/src/extension.ts
+++ b/deadlock-plugins/deadlock-extension/src/extension.ts
@@ -5,18 +5,21 @@ import { extensionError as error } from './recorder/utils/log';
 import { DepNodeProvider } from './theia/deadlockPanel';
 import UserConfigTheia from './theia/userConfigTheia';
 import { CommandTreeProvider } from './view/CommandTree';
+import StartedMissionsView from './view/startedMissionsView';
 
 export const userConfig = new UserConfigTheia();
 
 export async function activate(context: ExtensionContext) {
   window.showInformationMessage('Bienvenue sur Deadlock!');
 
-  new Controller(context);
+  Controller.getInstance(context);
 
   const workspaceFolders = workspace.workspaceFolders?.toString() ?? '';
   if (!workspaceFolders) window.showInformationMessage('Pas de répertoires ouverts');
   const deadlockPanelProvider = new DepNodeProvider();
   window.registerTreeDataProvider('deadlockPanel', deadlockPanelProvider);
+  window.registerWebviewViewProvider('startedMissions', new StartedMissionsView(context));
+
   if (isDocker()) {
     commands.executeCommand('setContext', 'deadlock.inContainer', true);
     window.registerTreeDataProvider('commandTree', new CommandTreeProvider(context));
@@ -26,6 +29,7 @@ export async function activate(context: ExtensionContext) {
   try {
     await userConfig.init();
   } catch (e) {
+    error(JSON.stringify(e));
     error('Cannot init userConfig');
   }
 }
diff --git a/deadlock-plugins/deadlock-extension/src/recorder/utils/log.ts b/deadlock-plugins/deadlock-extension/src/recorder/utils/log.ts
index aef8d4715ae945ee92bdf91c5edd381262372100..e231a4d4999f462ac688208ef92393196b95fc9f 100644
--- a/deadlock-plugins/deadlock-extension/src/recorder/utils/log.ts
+++ b/deadlock-plugins/deadlock-extension/src/recorder/utils/log.ts
@@ -6,6 +6,14 @@ export const log = (prefix: string, message: any, ...args: any[]) => {
   }
 };
 
+export const warn = (prefix: string, message: any, ...args: any[]) => {
+  if (args) {
+    console.warn(`[${prefix}] ${message}`, ...args);
+  } else {
+    console.warn(`[${prefix}] ${message}`);
+  }
+};
+
 export const error = (prefix: string, message: any, ...args: any[]) => {
   if (args) {
     console.error(`[${prefix}] ${message}`, ...args);
@@ -29,3 +37,7 @@ export function extensionError(message: any, ...args: any[]) {
 export function extensionLog(message: any, ...args: any[]) {
   log('DEADLOCK-EXTENSION', message, ...args);
 }
+
+export function extensionWarn(message: any, ...args: any[]) {
+  warn('DEADLOCK-EXTENSION', message, ...args);
+}
diff --git a/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts b/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts
index a7e7c5b2a66382c5f0394ac6693310814ab4ad20..6503a2cdc5d601f64b14ac72939fa3912eca216d 100644
--- a/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts
@@ -3,7 +3,6 @@ import ChallengeYaml, { MissionCommand as MissionCommandYaml } from '../model/ch
 import { parse } from 'yaml';
 import { readFileSync } from 'fs';
 import { commands, ExtensionContext, ThemeColor, ThemeIcon, TreeDataProvider, TreeItem, window } from 'vscode';
-import { extensionLog } from '../recorder/utils/log';
 
 export class CommandTreeProvider implements TreeDataProvider<MissionCommand> {
   challenge: ChallengeYaml;
@@ -40,7 +39,6 @@ class MissionCommand extends TreeItem {
     this.iconPath = new ThemeIcon('notebook-execute', new ThemeColor('debugIcon.startForeground'));
     commands.registerCommand(missionCommandYaml.name, () => {
       const terminalName = `Deadlock`;
-      extensionLog(JSON.stringify(window.terminals));
       const terminal =
         window.terminals.filter((terminal) => terminal.name === terminalName)[0] ??
         window.createTerminal({
diff --git a/deadlock-plugins/deadlock-extension/src/view/startedMissionsView.ts b/deadlock-plugins/deadlock-extension/src/view/startedMissionsView.ts
new file mode 100644
index 0000000000000000000000000000000000000000..463d15dfd12c2670a7164eff9bf4f127bf112451
--- /dev/null
+++ b/deadlock-plugins/deadlock-extension/src/view/startedMissionsView.ts
@@ -0,0 +1,92 @@
+import { randomBytes } from 'crypto';
+import { existsSync, readdirSync, readFileSync } from 'fs';
+import { join } from 'path';
+import { ExtensionContext, Webview, WebviewView, WebviewViewProvider, window } from 'vscode';
+import Controller from '../core/controller';
+import ExtensionStore from '../core/extensionStore';
+import UserChallenge from '../core/mission/models/userChallenge';
+import { extensionWarn } from '../recorder/utils/log';
+import { getUri } from './webviewBase';
+
+export default class StartedMissionsView implements WebviewViewProvider {
+  private readonly controller: Controller;
+  private readonly missionsWorkdir: string;
+  constructor(private context: ExtensionContext) {
+    this.missionsWorkdir = ExtensionStore.getInstance(this.context).getMissionWorkdir() ?? '';
+    this.controller = Controller.getInstance(context);
+  }
+
+  resolveWebviewView(webviewView: WebviewView): void | Thenable<void> {
+    webviewView.webview.options = {
+      enableScripts: true,
+
+      localResourceRoots: [this.context.extensionUri],
+    };
+    webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);
+    webviewView.webview.onDidReceiveMessage(this.onMessageReceive.bind(this));
+  }
+
+  onMessageReceive(message: any): void {
+    switch (message.command) {
+      case 'openMission': {
+        window.showInformationMessage('click received: ' + message.mission);
+        const path = join(this.missionsWorkdir, message.mission, '.config', 'user-challenge.json');
+        const userChallenge: UserChallenge = JSON.parse(readFileSync(path, 'utf8'));
+        this.controller.launchMission(userChallenge.missionId, userChallenge.missionVersion);
+        return;
+      }
+    }
+  }
+
+  private _getHtmlForWebview(webview: Webview) {
+    const toolkitUri = getUri(webview, this.context.extensionUri, [
+      'node_modules',
+      '@vscode',
+      'webview-ui-toolkit',
+      'dist',
+      'toolkit.js',
+    ]);
+
+    const css = getUri(webview, this.context.extensionUri, ['resources', 'styles', 'startedMissionsView.css']);
+
+    const js = getUri(webview, this.context.extensionUri, ['resources', 'js', 'startedMissionsView.js']);
+
+    // find all folders in mission directory
+    const path = this.missionsWorkdir;
+    let missionsHtml = '';
+    existsSync(path) &&
+      readdirSync(path).forEach((mission) => {
+        if (existsSync(join(path, mission, '.config', 'user-challenge.json'))) {
+          try {
+            const userChallenge: UserChallenge = JSON.parse(
+              readFileSync(join(path, mission, '.config', 'user-challenge.json'), 'utf8'),
+            );
+            missionsHtml += `<vscode-button onclick="openMission('${userChallenge.missionId}')" class="item" appearance="primary">${userChallenge.missionId}</vscode-button>`;
+          } catch (e) {
+            extensionWarn(`Failed to read user-challenge.json for mission ${mission}`);
+          }
+        } else {
+          extensionWarn(`Folder '${mission}' has no user-challenge.json file so it is ignored.`);
+        }
+      });
+
+    if (!missionsHtml) {
+      missionsHtml = '<div class="item">Aucune mission n\'a été démarrée</div>';
+    }
+
+    return `<!DOCTYPE html>
+    <html lang="en">
+    <head>
+        <meta charset="UTF-8">
+        <script type="module" src="${toolkitUri}"></script>
+        <script nonce="${randomBytes(16).toString('base64')}" src="${js}"></script>
+        <link rel="stylesheet" type="text/css" href="${css}">
+        </head>
+    <body>
+      <div>
+        ${missionsHtml}
+      </div>
+    </body>
+    </html>`;
+  }
+}