diff --git a/.gitignore b/.gitignore
index fd8204af44c4303b75c0b1526f39c238aad5cb2b..d37af39152d28c7126cfd2606471870e65e60b58 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+out/
+
 
 # Created by https://www.toptal.com/developers/gitignore/api/node,java
 # Edit at https://www.toptal.com/developers/gitignore?templates=node,java
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a1b24966fe4739f14778dad3ef3cdad8be9a5343
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,11 @@
+stages:
+  - build
+
+build:
+  stage: build
+  image: docker:18.09.6
+  script:
+    - ./build-plugins.sh
+    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.e-biz.fr
+    - docker build . -t $CI_REGISTRY_IMAGE
+    - docker push $CI_REGISTRY_IMAGE
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..6686f39f04b9c76e28af1814d0320c863bbaf397
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,7 @@
+FROM theiaide/theia-java:1.3.0
+
+COPY plugins /home/plugins
+
+ENTRYPOINT [ "yarn", "theia", "start", "/home/project", "--hostname=0.0.0.0", "--plugins=local-dir:/home/plugins"]
+
+
diff --git a/build-plugins.sh b/build-plugins.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9d0527752b1e8d890dad0d9f061a7092229a983b
--- /dev/null
+++ b/build-plugins.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+for dir in plugins/*/; do
+    echo "Building $dir"
+    cd $dir
+    npm run compile
+    cd -
+done
diff --git a/deadlock-extension/README.md b/deadlock-extension/README.md
deleted file mode 100644
index dfe5e4614ad676accc028cbfff661dddec225f91..0000000000000000000000000000000000000000
--- a/deadlock-extension/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Cat Coding — A Webview API Sample
-
-Demonstrates VS Code's [webview API](https://code.visualstudio.com/api/extension-guides/webview). This includes:
-
-- Creating and showing a basic webview.
-- Dynamically updating a webview's content.
-- Loading local content in a webview.
-- Running scripts in a webview.
-- Sending message from an extension to a webview.
-- Sending messages from a webview to an extension.
-- Using a basic content security policy.
-- Webview lifecycle and handling dispose.
-- Saving and restoring state when the panel goes into the background.
-- Serialization and persistence across VS Code reboots.
-
-## Demo
-
-![demo](demo.gif)
-
-## VS Code API
-
-### `vscode` module
-
-- [`window.createWebviewPanel`](https://code.visualstudio.com/api/references/vscode-api#window.createWebviewPanel)
-- [`window.registerWebviewPanelSerializer`](https://code.visualstudio.com/api/references/vscode-api#window.registerWebviewPanelSerializer)
-
-## Running the example
-
-- Open this example in VS Code 1.25+
-- `npm install`
-- `npm run watch` or `npm run compile`
-- `F5` to start debugging
-
-Run the `Cat Coding: Start cat coding session` to create the webview.
diff --git a/deadlock-extension/demo.gif b/deadlock-extension/demo.gif
deleted file mode 100644
index 13b39b44dc8f90b657dcf20d5b42f850ef4da5ed..0000000000000000000000000000000000000000
Binary files a/deadlock-extension/demo.gif and /dev/null differ
diff --git a/deadlock-extension/media/cat.gif b/deadlock-extension/media/cat.gif
deleted file mode 100644
index 8a1648264b50d33bca81719fdce0a406037d02fb..0000000000000000000000000000000000000000
Binary files a/deadlock-extension/media/cat.gif and /dev/null differ
diff --git a/deadlock-extension/media/main.js b/deadlock-extension/media/main.js
deleted file mode 100644
index c71d8d2e72d3fd4446c13dc4fb00fd778f3d054e..0000000000000000000000000000000000000000
--- a/deadlock-extension/media/main.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// This script will be run within the webview itself
-// It cannot access the main VS Code APIs directly.
-(function () {
-    const vscode = acquireVsCodeApi();
-
-    const oldState = vscode.getState();
-
-    // const counter = document.getElementById('lines-of-code-counter');
-    // console.log(oldState);
-    // let currentCount = (oldState && oldState.count) || 0;
-    // counter.textContent = currentCount;
-
-    setInterval(() => {
-        
-        // counter.textContent = currentCount++;
-
-        // // Update state
-        // vscode.setState({ count: currentCount });
-
-        // // Alert the extension when the cat introduces a bug
-        // if (Math.random() < Math.min(0.001 * currentCount, 0.05)) {
-        //     // Send a message back to the extension
-        //     vscode.postMessage({
-        //         command: 'alert',
-        //         text: '🐛  on line ' + currentCount
-        //     });
-        // }
-    }, 700);
-
-    // // Handle messages sent from the extension to the webview
-    // window.addEventListener('message', event => {
-    //     const message = event.data; // The json data that the extension sent
-    //     switch (message.command) {
-    //         case 'refactor':
-    //             currentCount = Math.ceil(currentCount * 0.5);
-    //             counter.textContent = currentCount;
-    //             break;
-    //     }
-    // });
-}());
\ No newline at end of file
diff --git a/deadlock-extension/out/extension.js b/deadlock-extension/out/extension.js
deleted file mode 100644
index 83db82f6fb8023f7b9d6b687429236dab4792aa3..0000000000000000000000000000000000000000
--- a/deadlock-extension/out/extension.js
+++ /dev/null
@@ -1,189 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.activate = void 0;
-const path = require("path");
-const vscode = require("vscode");
-const vscode_1 = require("vscode");
-const marked = require("marked");
-const CONFIG_PATH = "/home/config/";
-let readMeContent = '';
-let userChallengeConfig = undefined;
-function init() {
-    const currentWorkspace = vscode.workspace.workspaceFolders;
-    if (currentWorkspace) {
-        // means at least one folder is open
-        vscode.workspace
-            .openTextDocument(vscode_1.Uri.parse(path.join(CONFIG_PATH, "user-challenge.json")))
-            .then((userConfig) => {
-            console.log('userConfig', userConfig.getText());
-            userChallengeConfig = JSON.parse(userConfig.getText());
-            DeadlockPanel.update();
-        });
-        vscode.workspace
-            .openTextDocument(vscode_1.Uri.parse(path.join(currentWorkspace[0].uri.path, "README.md")))
-            .then((document) => {
-            readMeContent = document.getText();
-            DeadlockPanel.update();
-        });
-    }
-}
-function activate(context) {
-    init();
-    if (vscode.window.registerWebviewPanelSerializer) {
-        // Make sure we register a serializer in activation event
-        vscode.window.registerWebviewPanelSerializer(DeadlockPanel.viewType, {
-            async deserializeWebviewPanel(webviewPanel, state) {
-                DeadlockPanel.revive(webviewPanel, context.extensionPath);
-            },
-        });
-    }
-    context.subscriptions.push(vscode.commands.registerCommand("deadlock.start", () => {
-        init();
-        DeadlockPanel.createOrShow(context.extensionPath);
-    }));
-    DeadlockPanel.createOrShow(context.extensionPath);
-}
-exports.activate = activate;
-/**
- * Manages cat coding webview panels
- */
-class DeadlockPanel {
-    constructor(panel, extensionPath) {
-        this._disposables = [];
-        this._panel = panel;
-        this._extensionPath = extensionPath;
-        // Listen for when the panel is disposed
-        // This happens when the user closes the panel or when the panel is closed programatically
-        this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
-        // Update the content based on view changes
-        this._panel.onDidChangeViewState((e) => {
-            if (this._panel.visible) {
-                this._update();
-            }
-        }, null, this._disposables);
-        // Handle messages from the webview
-        this._panel.webview.onDidReceiveMessage((message) => {
-            switch (message.command) {
-                case "alert":
-                    vscode.window.showErrorMessage(message.text);
-                    return;
-            }
-        }, null, this._disposables);
-    }
-    static update() {
-        if (DeadlockPanel.currentPanel) {
-            DeadlockPanel.currentPanel._update();
-        }
-        else {
-            console.warn('Cannot update DeadlockPanel has not been created.');
-        }
-    }
-    static createOrShow(extensionPath) {
-        const column = vscode.window.activeTextEditor
-            ? vscode.window.activeTextEditor.viewColumn
-            : undefined;
-        // If we already have a panel, show it.
-        if (DeadlockPanel.currentPanel) {
-            DeadlockPanel.currentPanel._panel.reveal(column);
-            return;
-        }
-        // Otherwise, create a new panel.
-        const panel = vscode.window.createWebviewPanel(DeadlockPanel.viewType, "Deadlock", column || vscode.ViewColumn.One, {
-            // Enable javascript in the webview
-            enableScripts: true,
-            // And restrict the webview to only loading content from our extension's `media` directory.
-            localResourceRoots: [
-                vscode.Uri.file(path.join(extensionPath, "media")),
-            ],
-        });
-        DeadlockPanel.currentPanel = new DeadlockPanel(panel, extensionPath);
-    }
-    static revive(panel, extensionPath) {
-        DeadlockPanel.currentPanel = new DeadlockPanel(panel, extensionPath);
-    }
-    doRefactor() {
-        // Send a message to the webview webview.
-        // You can send any JSON serializable data.
-        this._panel.webview.postMessage({ command: "refactor" });
-    }
-    dispose() {
-        DeadlockPanel.currentPanel = undefined;
-        // Clean up our resources
-        this._panel.dispose();
-        while (this._disposables.length) {
-            const x = this._disposables.pop();
-            if (x) {
-                x.dispose();
-            }
-        }
-    }
-    _update() {
-        const webview = this._panel.webview;
-        this._panel.title = "Deadlock";
-        this._panel.webview.html = this._getHtmlForWebview(webview);
-    }
-    _getHtmlForWebview(webview) {
-        // Local path to main script run in the webview
-        const scriptPathOnDisk = vscode.Uri.file(path.join(this._extensionPath, "media", "main.js"));
-        // And the uri we use to load this script in the webview
-        const scriptUri = webview.asWebviewUri(scriptPathOnDisk);
-        // Use a nonce to whitelist which scripts can be run
-        const nonce = getNonce();
-        return `<!DOCTYPE html>
-			<html lang="en">
-			<style type="text/css">
-			</style>
-            <head>
-                <meta charset="UTF-8">
-
-                <!--
-                Use a content security policy to only allow loading images from https or from our extension directory,
-                and only allow scripts that have a specific nonce.
-                -->
-                <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src ${webview.cspSource} https:; script-src 'nonce-${nonce}';">
-
-                <meta name="viewport" content="width=device-width, initial-scale=1.0">
-                <title>Deadlock</title>
-            </head>
-			<body>
-				<h1>Deadlock Mission</h1>
-				<div>
-					${this.showUserChallengeConfig()}
-				</div>
-				<div>
-					<h1>Mission Goal 🕶</h1>
-					${marked(readMeContent)}
-				</div>
-				
-
-                <script nonce="${nonce}" src="${scriptUri}"></script>
-            </body>
-            </html>`;
-    }
-    showUserChallengeConfig() {
-        let adresses = "";
-        if (userChallengeConfig) {
-            let pathsLength = 0;
-            for (let key in userChallengeConfig.paths) {
-                pathsLength++;
-                const path = userChallengeConfig.paths[key];
-                adresses += `<li>${key} binded on <a href="https://${userChallengeConfig.host}/${path}">${path}</a></li>`;
-            }
-            console.log(pathsLength);
-            if (pathsLength > 0) {
-                return `You have the following adresses availables for your challenge : <ul>${adresses}</ul>`;
-            }
-        }
-        return '';
-    }
-}
-DeadlockPanel.viewType = "deadlock";
-function getNonce() {
-    let text = "";
-    const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-    for (let i = 0; i < 32; i++) {
-        text += possible.charAt(Math.floor(Math.random() * possible.length));
-    }
-    return text;
-}
-//# sourceMappingURL=extension.js.map
\ No newline at end of file
diff --git a/deadlock-extension/out/extension.js.map b/deadlock-extension/out/extension.js.map
deleted file mode 100644
index 18e40fa4cdf6b6977bac553021fb0dc17d8e5f36..0000000000000000000000000000000000000000
--- a/deadlock-extension/out/extension.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/deadlock-extension/src/docs/briefing.md b/deadlock-extension/src/docs/briefing.md
deleted file mode 100644
index 6b3d67b2e175d0636ee1dd1463058b6fb3ef66a4..0000000000000000000000000000000000000000
--- a/deadlock-extension/src/docs/briefing.md
+++ /dev/null
@@ -1 +0,0 @@
-# Persist
\ No newline at end of file
diff --git a/deadlock-extension/src/docs/fr/briefing copy.md b/deadlock-extension/src/docs/fr/briefing copy.md
deleted file mode 100644
index 6b3d67b2e175d0636ee1dd1463058b6fb3ef66a4..0000000000000000000000000000000000000000
--- a/deadlock-extension/src/docs/fr/briefing copy.md	
+++ /dev/null
@@ -1 +0,0 @@
-# Persist
\ No newline at end of file
diff --git a/deadlock-extension/src/docs/fr/briefing.md b/deadlock-extension/src/docs/fr/briefing.md
deleted file mode 100644
index 02829eb3d531c53e5ee52fa9788590c411ede620..0000000000000000000000000000000000000000
--- a/deadlock-extension/src/docs/fr/briefing.md
+++ /dev/null
@@ -1 +0,0 @@
-# Persist
diff --git a/deadlock-extension/src/docs/fr/hint1.md b/deadlock-extension/src/docs/fr/hint1.md
deleted file mode 100644
index c4373ff8a9a7e75a626c36e8e1156cbc712e3581..0000000000000000000000000000000000000000
--- a/deadlock-extension/src/docs/fr/hint1.md
+++ /dev/null
@@ -1 +0,0 @@
-Vous pourriez penser à une méthode récursive.
\ No newline at end of file
diff --git a/deadlock-extension/src/docs/hint1.md b/deadlock-extension/src/docs/hint1.md
deleted file mode 100644
index 26eb0fad5f06389944e2abffb467167ba6303dcf..0000000000000000000000000000000000000000
--- a/deadlock-extension/src/docs/hint1.md
+++ /dev/null
@@ -1 +0,0 @@
-Think about a recursive method.
\ No newline at end of file
diff --git a/deadlock-extension/src/extension.ts b/deadlock-extension/src/extension.ts
deleted file mode 100644
index 1610839d698131692c1846a567a09fb9731b824b..0000000000000000000000000000000000000000
--- a/deadlock-extension/src/extension.ts
+++ /dev/null
@@ -1,253 +0,0 @@
-import * as path from "path";
-import * as vscode from "vscode";
-import { Uri } from "vscode";
-const marked = require("marked");
-
-const CONFIG_PATH = "/home/config/";
-let readMeContent = '';
-let userChallengeConfig = undefined;
-
-function init() {
-	const currentWorkspace = vscode.workspace.workspaceFolders;
-
-	if (currentWorkspace) {
-		// means at least one folder is open
-
-		vscode.workspace
-			.openTextDocument(
-				Uri.parse(path.join(CONFIG_PATH, "user-challenge.json"))
-			)
-			.then((userConfig) => {
-				console.log('userConfig', userConfig.getText());
-				userChallengeConfig = JSON.parse(userConfig.getText());
-				DeadlockPanel.update();
-
-			});
-		vscode.workspace
-			.openTextDocument(
-				Uri.parse(path.join(currentWorkspace[0].uri.path, "README.md"))
-			)
-			.then((document) => {
-				readMeContent = document.getText();
-				DeadlockPanel.update();
-			});
-	}
-}
-
-export function activate(context: vscode.ExtensionContext) {
-	init();
-
-	if (vscode.window.registerWebviewPanelSerializer) {
-		// Make sure we register a serializer in activation event
-		vscode.window.registerWebviewPanelSerializer(DeadlockPanel.viewType, {
-			async deserializeWebviewPanel(
-				webviewPanel: vscode.WebviewPanel,
-				state: any
-			) {
-				DeadlockPanel.revive(webviewPanel, context.extensionPath);
-			},
-		});
-	}
-
-	context.subscriptions.push(
-		vscode.commands.registerCommand("deadlock.start", () => {
-			init();
-			DeadlockPanel.createOrShow(context.extensionPath);
-		})
-	);
-
-	DeadlockPanel.createOrShow(context.extensionPath);
-}
-
-/**
- * Manages cat coding webview panels
- */
-class DeadlockPanel {
-	/**
-	 * Track the currently panel. Only allow a single panel to exist at a time.
-	 */
-	public static currentPanel: DeadlockPanel | undefined;
-
-	public static readonly viewType = "deadlock";
-
-	private readonly _panel: vscode.WebviewPanel;
-	private readonly _extensionPath: string;
-	private _disposables: vscode.Disposable[] = [];
-
-	public static update() {
-		if (DeadlockPanel.currentPanel) {
-			DeadlockPanel.currentPanel._update();
-		} else {
-			console.warn('Cannot update DeadlockPanel has not been created.');
-		}
-	}
-
-	public static createOrShow(extensionPath: string) {
-		const column = vscode.window.activeTextEditor
-			? vscode.window.activeTextEditor.viewColumn
-			: undefined;
-
-		// If we already have a panel, show it.
-		if (DeadlockPanel.currentPanel) {
-			DeadlockPanel.currentPanel._panel.reveal(column);
-			return;
-		}
-
-		// Otherwise, create a new panel.
-		const panel = vscode.window.createWebviewPanel(
-			DeadlockPanel.viewType,
-			"Deadlock",
-			column || vscode.ViewColumn.One,
-			{
-				// Enable javascript in the webview
-				enableScripts: true,
-
-				// And restrict the webview to only loading content from our extension's `media` directory.
-				localResourceRoots: [
-					vscode.Uri.file(path.join(extensionPath, "media")),
-				],
-			}
-		);
-
-		DeadlockPanel.currentPanel = new DeadlockPanel(panel, extensionPath);
-	}
-
-	public static revive(panel: vscode.WebviewPanel, extensionPath: string) {
-		DeadlockPanel.currentPanel = new DeadlockPanel(panel, extensionPath);
-	}
-
-	private constructor(panel: vscode.WebviewPanel, extensionPath: string) {
-		this._panel = panel;
-		this._extensionPath = extensionPath;
-
-
-		// Listen for when the panel is disposed
-		// This happens when the user closes the panel or when the panel is closed programatically
-		this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
-
-		// Update the content based on view changes
-		this._panel.onDidChangeViewState(
-			(e) => {
-				if (this._panel.visible) {
-					this._update();
-				}
-			},
-			null,
-			this._disposables
-		);
-
-		// Handle messages from the webview
-		this._panel.webview.onDidReceiveMessage(
-			(message) => {
-				switch (message.command) {
-					case "alert":
-						vscode.window.showErrorMessage(message.text);
-						return;
-				}
-			},
-			null,
-			this._disposables
-		);
-	}
-
-	public doRefactor() {
-		// Send a message to the webview webview.
-		// You can send any JSON serializable data.
-		this._panel.webview.postMessage({ command: "refactor" });
-	}
-
-	public dispose() {
-		DeadlockPanel.currentPanel = undefined;
-
-		// Clean up our resources
-		this._panel.dispose();
-
-		while (this._disposables.length) {
-			const x = this._disposables.pop();
-			if (x) {
-				x.dispose();
-			}
-		}
-	}
-
-	private _update() {
-		const webview = this._panel.webview;
-		this._panel.title = "Deadlock";
-		this._panel.webview.html = this._getHtmlForWebview(webview);
-	}
-
-	private _getHtmlForWebview(webview: vscode.Webview) {
-		// Local path to main script run in the webview
-		const scriptPathOnDisk = vscode.Uri.file(
-			path.join(this._extensionPath, "media", "main.js")
-		);
-
-		// And the uri we use to load this script in the webview
-		const scriptUri = webview.asWebviewUri(scriptPathOnDisk);
-
-		// Use a nonce to whitelist which scripts can be run
-		const nonce = getNonce();
-
-		return `<!DOCTYPE html>
-			<html lang="en">
-			<style type="text/css">
-			</style>
-            <head>
-                <meta charset="UTF-8">
-
-                <!--
-                Use a content security policy to only allow loading images from https or from our extension directory,
-                and only allow scripts that have a specific nonce.
-                -->
-                <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src ${
-			webview.cspSource
-			} https:; script-src 'nonce-${nonce}';">
-
-                <meta name="viewport" content="width=device-width, initial-scale=1.0">
-                <title>Deadlock</title>
-            </head>
-			<body>
-				<h1>Deadlock Mission</h1>
-				<div>
-					${this.showUserChallengeConfig()}
-				</div>
-				<div>
-					<h1>Mission Goal 🕶</h1>
-					${marked(readMeContent)}
-				</div>
-				
-
-                <script nonce="${nonce}" src="${scriptUri}"></script>
-            </body>
-            </html>`;
-	}
-
-	showUserChallengeConfig() {
-		let adresses = "";
-
-		if (userChallengeConfig) {
-			let pathsLength = 0;
-			for (let key in userChallengeConfig.paths) {
-				pathsLength++;
-				const path = userChallengeConfig.paths[key];
-				adresses += `<li>${key} binded on <a href="https://${userChallengeConfig.host}/${path}">${path}</a></li>`;
-			}
-
-			console.log(pathsLength);
-			if (pathsLength > 0) {
-				return `You have the following adresses availables for your challenge : <ul>${adresses}</ul>`;
-			}
-		}
-		return '';
-	}
-}
-
-function getNonce() {
-	let text = "";
-	const possible =
-		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-	for (let i = 0; i < 32; i++) {
-		text += possible.charAt(Math.floor(Math.random() * possible.length));
-	}
-	return text;
-}
diff --git a/deadlock-extension/.eslintrc.js b/plugins/deadlock-extension/.eslintrc.js
similarity index 87%
rename from deadlock-extension/.eslintrc.js
rename to plugins/deadlock-extension/.eslintrc.js
index f660e395fe255b0615b4f6caf4509c3faee7cee9..cd15cf93f5de58e6be674beb72643e473d6bdb8d 100644
--- a/deadlock-extension/.eslintrc.js
+++ b/plugins/deadlock-extension/.eslintrc.js
@@ -11,7 +11,8 @@ module.exports = {
 		'plugin:@typescript-eslint/recommended',
 	],
 	rules: {
-		'semi': [2, "always"],
+		'semi': [2, 'always'],
+		'quotes': [2, 'single', 'avoid-escape'],
 		'@typescript-eslint/no-unused-vars': 0,
 		'@typescript-eslint/no-explicit-any': 0,
 		'@typescript-eslint/explicit-module-boundary-types': 0,
diff --git a/deadlock-extension/.vscode/extensions.json b/plugins/deadlock-extension/.vscode/extensions.json
similarity index 100%
rename from deadlock-extension/.vscode/extensions.json
rename to plugins/deadlock-extension/.vscode/extensions.json
diff --git a/deadlock-extension/.vscode/launch.json b/plugins/deadlock-extension/.vscode/launch.json
similarity index 100%
rename from deadlock-extension/.vscode/launch.json
rename to plugins/deadlock-extension/.vscode/launch.json
diff --git a/deadlock-extension/.vscode/settings.json b/plugins/deadlock-extension/.vscode/settings.json
similarity index 100%
rename from deadlock-extension/.vscode/settings.json
rename to plugins/deadlock-extension/.vscode/settings.json
diff --git a/deadlock-extension/.vscode/tasks.json b/plugins/deadlock-extension/.vscode/tasks.json
similarity index 100%
rename from deadlock-extension/.vscode/tasks.json
rename to plugins/deadlock-extension/.vscode/tasks.json
diff --git a/plugins/deadlock-extension/README.md b/plugins/deadlock-extension/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9a5ab4bce2ddd3b97bc58549f348bea137ff2fd5
--- /dev/null
+++ b/plugins/deadlock-extension/README.md
@@ -0,0 +1,6 @@
+# Deadlock Coding
+
+Vscode extension to show a panel with :
+* adresses availables for the current challenge pulled from `/home/config/user-challenge.json`
+* challenge instruction pulled from the `README.md`
+
diff --git a/plugins/deadlock-extension/media/main.js b/plugins/deadlock-extension/media/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..8c580996a1f8797d52b3db8b6fe6e150fbd69869
--- /dev/null
+++ b/plugins/deadlock-extension/media/main.js
@@ -0,0 +1,8 @@
+// This script will be run within the webview itself
+// It cannot access the main VS Code APIs directly.
+(function () {
+    const vscode = acquireVsCodeApi();
+
+    const oldState = vscode.getState();
+
+}());
\ No newline at end of file
diff --git a/deadlock-extension/media/spinner.png b/plugins/deadlock-extension/media/spinner.png
similarity index 100%
rename from deadlock-extension/media/spinner.png
rename to plugins/deadlock-extension/media/spinner.png
diff --git a/deadlock-extension/package-lock.json b/plugins/deadlock-extension/package-lock.json
similarity index 99%
rename from deadlock-extension/package-lock.json
rename to plugins/deadlock-extension/package-lock.json
index 5c4d4fa3beb6f54adeeb1050d5d0d1f0867520e4..3c1a051e4b24d8b79f82e896c77a8502b3a137d8 100644
--- a/deadlock-extension/package-lock.json
+++ b/plugins/deadlock-extension/package-lock.json
@@ -1,5 +1,5 @@
 {
-	"name": "cat-coding",
+	"name": "deadlock-coding",
 	"version": "0.0.1",
 	"lockfileVersion": 1,
 	"requires": true,
diff --git a/deadlock-extension/package.json b/plugins/deadlock-extension/package.json
similarity index 92%
rename from deadlock-extension/package.json
rename to plugins/deadlock-extension/package.json
index fd12f5a890c066fad27a0aa3ec3d126fef6d72e2..e9d216ca64b1cec6d39ec3466d4c074257a50aa4 100644
--- a/deadlock-extension/package.json
+++ b/plugins/deadlock-extension/package.json
@@ -1,6 +1,6 @@
 {
-	"name": "cat-coding",
-	"description": "Cat Coding - A Webview API Sample",
+	"name": "deadlock-coding",
+	"description": "Deadlock Coding",
 	"version": "0.0.1",
 	"publisher": "vscode-samples",
 	"engines": {
diff --git a/plugins/deadlock-extension/src/extension.ts b/plugins/deadlock-extension/src/extension.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f4e553fb34083190fdd79e938c7b1d6ec2298682
--- /dev/null
+++ b/plugins/deadlock-extension/src/extension.ts
@@ -0,0 +1,249 @@
+import * as path from 'path';
+import * as vscode from 'vscode';
+import { Uri } from 'vscode';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+const marked = require('marked');
+
+interface UserChallengeConfig {
+  paths: Record<string, string>;
+  host: string;
+}
+
+const CONFIG_PATH = '/home/config/';
+let readMeContent = '';
+let userChallengeConfig: UserChallengeConfig;
+
+function init() {
+  const currentWorkspace = vscode.workspace.workspaceFolders;
+
+  vscode.workspace
+    .openTextDocument(Uri.parse(path.join(CONFIG_PATH, 'user-challenge.json')))
+    .then((userConfig) => {
+      userChallengeConfig = JSON.parse(userConfig.getText());
+      DeadlockPanel.update();
+    });
+
+  if (currentWorkspace) {
+    // means at least one folder is open within vscode
+
+    vscode.workspace
+      .openTextDocument(
+        Uri.parse(path.join(currentWorkspace[0].uri.path, 'README.md'))
+      )
+      .then((document) => {
+        readMeContent = document.getText();
+        DeadlockPanel.update();
+      });
+  }
+}
+
+export function activate(context: vscode.ExtensionContext) {
+  init();
+
+  if (vscode.window.registerWebviewPanelSerializer) {
+    // Make sure we register a serializer in activation event
+    vscode.window.registerWebviewPanelSerializer(DeadlockPanel.viewType, {
+      async deserializeWebviewPanel(
+        webviewPanel: vscode.WebviewPanel,
+        state: any
+      ) {
+        DeadlockPanel.revive(webviewPanel, context.extensionPath);
+      },
+    });
+  }
+
+  context.subscriptions.push(
+    vscode.commands.registerCommand('deadlock.start', () => {
+      init();
+      DeadlockPanel.createOrShow(context.extensionPath);
+    })
+  );
+
+  DeadlockPanel.createOrShow(context.extensionPath);
+}
+
+class DeadlockPanel {
+  /**
+   * Track the currently panel. Only allow a single panel to exist at a time.
+   */
+  public static currentPanel: DeadlockPanel | undefined;
+
+  public static readonly viewType = 'deadlock';
+
+  private readonly _panel: vscode.WebviewPanel;
+  private readonly _extensionPath: string;
+  private _disposables: vscode.Disposable[] = [];
+
+  public static update() {
+    if (DeadlockPanel.currentPanel) {
+      DeadlockPanel.currentPanel._update();
+    } else {
+      console.warn('Cannot update DeadlockPanel has not been created.');
+    }
+  }
+
+  public static createOrShow(extensionPath: string) {
+    const column = vscode.window.activeTextEditor
+      ? vscode.window.activeTextEditor.viewColumn
+      : undefined;
+
+    // If we already have a panel, show it.
+    if (DeadlockPanel.currentPanel) {
+      DeadlockPanel.currentPanel._panel.reveal(column);
+      return;
+    }
+
+    // Otherwise, create a new panel.
+    const panel = vscode.window.createWebviewPanel(
+      DeadlockPanel.viewType,
+      'Deadlock',
+      column || vscode.ViewColumn.One,
+      {
+        // Enable javascript in the webview
+        enableScripts: true,
+
+        // And restrict the webview to only loading content from our extension's `media` directory.
+        localResourceRoots: [
+          vscode.Uri.file(path.join(extensionPath, 'media')),
+        ],
+      }
+    );
+
+    DeadlockPanel.currentPanel = new DeadlockPanel(panel, extensionPath);
+  }
+
+  public static revive(panel: vscode.WebviewPanel, extensionPath: string) {
+    DeadlockPanel.currentPanel = new DeadlockPanel(panel, extensionPath);
+  }
+
+  private constructor(panel: vscode.WebviewPanel, extensionPath: string) {
+    this._panel = panel;
+    this._extensionPath = extensionPath;
+
+    // Listen for when the panel is disposed
+    // This happens when the user closes the panel or when the panel is closed programatically
+    this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
+
+    // Update the content based on view changes
+    this._panel.onDidChangeViewState(
+      (e) => {
+        if (this._panel.visible) {
+          this._update();
+        }
+      },
+      null,
+      this._disposables
+    );
+
+    // Handle messages from the webview
+    this._panel.webview.onDidReceiveMessage(
+      (message) => {
+        switch (message.command) {
+          case 'alert':
+            vscode.window.showErrorMessage(message.text);
+            return;
+        }
+      },
+      null,
+      this._disposables
+    );
+  }
+
+  public doRefactor() {
+    // Send a message to the webview webview.
+    // You can send any JSON serializable data.
+    this._panel.webview.postMessage({ command: 'refactor' });
+  }
+
+  public dispose() {
+    DeadlockPanel.currentPanel = undefined;
+
+    // Clean up our resources
+    this._panel.dispose();
+
+    while (this._disposables.length) {
+      const x = this._disposables.pop();
+      if (x) {
+        x.dispose();
+      }
+    }
+  }
+
+  private _update() {
+    const webview = this._panel.webview;
+    this._panel.title = 'Deadlock';
+    this._panel.webview.html = this._getHtmlForWebview(webview);
+  }
+
+  private _getHtmlForWebview(webview: vscode.Webview) {
+    // Local path to main script run in the webview
+    const scriptPathOnDisk = vscode.Uri.file(
+      path.join(this._extensionPath, 'media', 'main.js')
+    );
+
+    // And the uri we use to load this script in the webview
+    const scriptUri = webview.asWebviewUri(scriptPathOnDisk);
+
+    // Use a nonce to whitelist which scripts can be run
+    const nonce = getNonce();
+
+    return `<!DOCTYPE html>
+			<html lang="en">
+			<style type="text/css">
+			</style>
+            <head>
+                <meta charset="UTF-8">
+
+                <!--
+                Use a content security policy to only allow loading images from https or from our extension directory,
+                and only allow scripts that have a specific nonce.
+                -->
+                <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src ${
+                  webview.cspSource
+                } https:; script-src 'nonce-${nonce}';">
+
+                <meta name="viewport" content="width=device-width, initial-scale=1.0">
+                <title>Deadlock</title>
+            </head>
+			<body>
+				<h1>Deadlock Mission</h1>
+				<div>
+					${this.showUserChallengeConfig()}
+				</div>
+				<div>
+					<h1>Mission Goal 🕶</h1>
+					${marked(readMeContent)}
+				</div>
+          <script nonce="${nonce}" src="${scriptUri}"></script>
+        </body>
+        </html>`;
+  }
+
+  showUserChallengeConfig() {
+    let adresses = '';
+
+    if (userChallengeConfig) {
+      let pathsLength = 0;
+      for (const key in userChallengeConfig.paths) {
+        pathsLength++;
+        const path = userChallengeConfig.paths[key];
+        adresses += `<li>${key} binded on <a href="https://${userChallengeConfig.host}/${path}">${path}</a></li>`;
+      }
+
+      if (pathsLength > 0) {
+        return `You have the following adresses availables for your challenge : <ul>${adresses}</ul>`;
+      }
+    }
+    return '';
+  }
+}
+
+function getNonce() {
+  let text = '';
+  const possible =
+    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+  for (let i = 0; i < 32; i++) {
+    text += possible.charAt(Math.floor(Math.random() * possible.length));
+  }
+  return text;
+}
diff --git a/deadlock-extension/tsconfig.json b/plugins/deadlock-extension/tsconfig.json
similarity index 100%
rename from deadlock-extension/tsconfig.json
rename to plugins/deadlock-extension/tsconfig.json