diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1dd2c973..13335737 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,19 @@
-## Version 1.3.9 - in dev
+## Version 1.4.x-dev
+
+### Updates
+
+- Added the ability to have animated tiles in maps #1216 #1217
+- Enabled outlines on actionable item again (they were disabled when migrating to Phaser 3.50) #1218
+- Enabled outlines on player names (when the mouse hovers on a player you can interact with) #1219
+- Migrated the admin console to Svelte, and redesigned the console #1211
+
+## Version 1.4.1
+
+### Bugfixes
+
+- Loading errors after the preload stage should not crash the game anymore
+
+## Version 1.4.0
### BREAKING CHANGES
diff --git a/docs/maps/animations.md b/docs/maps/animations.md
new file mode 100644
index 00000000..276f2332
--- /dev/null
+++ b/docs/maps/animations.md
@@ -0,0 +1,33 @@
+{.section-title.accent.text-primary}
+# Animating WorkAdventure maps
+
+A tile can run an animation in loops, for example to render water or blinking lights. Each animation frame is a single
+32x32 tile. To create an animation, edit the tileset in Tiled and click on the tile to animate (or pick a free tile to
+not overwrite existing ones) and click on the animation editor:
+
+
+
+
+
+
+You can now add all tiles that should be part of the animation via drag and drop to the "playlist" and adjust the frame duration:
+
+
+
+
+ The tile animation editor
+
+
+
+You can preview animations directly in Tiled, using the "Show tile animations" option:
+
+
+
+
+
+ The Show Tile Animations option
+
+
+
+{.alert.alert-info}
+**Tip:** The engine does tile-updates every 100ms, animations with a shorter frame duration will most likely not look that good or may even do not work.
diff --git a/docs/maps/api-chat.md b/docs/maps/api-chat.md
new file mode 100644
index 00000000..49a40f97
--- /dev/null
+++ b/docs/maps/api-chat.md
@@ -0,0 +1,37 @@
+{.section-title.accent.text-primary}
+# API Chat functions reference
+
+### Sending a message in the chat
+
+```
+WA.chat.sendChatMessage(message: string, author: string): void
+```
+
+Sends a message in the chat. The message is only visible in the browser of the current user.
+
+* **message**: the message to be displayed in the chat
+* **author**: the name displayed for the author of the message. It does not have to be a real user.
+
+Example:
+
+```javascript
+WA.chat.sendChatMessage('Hello world', 'Mr Robot');
+```
+
+### Listening to messages from the chat
+
+```javascript
+WA.chat.onChatMessage(callback: (message: string) => void): void
+```
+
+Listens to messages typed by the current user and calls the callback. Messages from other users in the chat cannot be listened to.
+
+* **callback**: the function that will be called when a message is received. It contains the message typed by the user.
+
+Example:
+
+```javascript
+WA.chat.onChatMessage((message => {
+ console.log('The user typed a message', message);
+}));
+```
diff --git a/docs/maps/api-controls.md b/docs/maps/api-controls.md
new file mode 100644
index 00000000..dcb0f17b
--- /dev/null
+++ b/docs/maps/api-controls.md
@@ -0,0 +1,29 @@
+{.section-title.accent.text-primary}
+# API Controls functions Reference
+
+### Disabling / restoring controls
+
+```
+WA.controls.disablePlayerControls(): void
+WA.controls.restorePlayerControls(): void
+```
+
+These 2 methods can be used to completely disable player controls and to enable them again.
+
+When controls are disabled, the user cannot move anymore using keyboard input. This can be useful in a "First Time User Experience" part, to display an important message to a user before letting him/her move again.
+
+Example:
+
+```javascript
+WA.room.onEnterZone('myZone', () => {
+ WA.controls.disablePlayerControls();
+ WA.ui.openPopup("popupRectangle", 'This is an imporant message!', [{
+ label: "Got it!",
+ className: "primary",
+ callback: (popup) => {
+ WA.controls.restorePlayerControls();
+ popup.close();
+ }
+ }]);
+});
+```
diff --git a/docs/maps/api-deprecated.md b/docs/maps/api-deprecated.md
new file mode 100644
index 00000000..930caebe
--- /dev/null
+++ b/docs/maps/api-deprecated.md
@@ -0,0 +1,20 @@
+{.section-title.accent.text-primary}
+# API Reference - Deprecated functions
+
+The list of functions below is **deprecated**. You should not use those but. use the replacement functions.
+
+- Method `WA.sendChatMessage` is deprecated. It has been renamed to `WA.chat.sendChatMessage`.
+- Method `WA.disablePlayerControls` is deprecated. It has been renamed to `WA.controls.disablePlayerControls`.
+- Method `WA.restorePlayerControls` is deprecated. It has been renamed to `WA.controls.restorePlayerControls`.
+- Method `WA.displayBubble` is deprecated. It has been renamed to `WA.ui.displayBubble`.
+- Method `WA.removeBubble` is deprecated. It has been renamed to `WA.ui.removeBubble`.
+- Method `WA.openTab` is deprecated. It has been renamed to `WA.nav.openTab`.
+- Method `WA.loadSound` is deprecated. It has been renamed to `WA.sound.loadSound`.
+- Method `WA.goToPage` is deprecated. It has been renamed to `WA.nav.goToPage`.
+- Method `WA.goToRoom` is deprecated. It has been renamed to `WA.nav.goToRoom`.
+- Method `WA.openCoWebSite` is deprecated. It has been renamed to `WA.nav.openCoWebSite`.
+- Method `WA.closeCoWebSite` is deprecated. It has been renamed to `WA.nav.closeCoWebSite`.
+- Method `WA.openPopup` is deprecated. It has been renamed to `WA.ui.openPopup`.
+- Method `WA.onChatMessage` is deprecated. It has been renamed to `WA.chat.onChatMessage`.
+- Method `WA.onEnterZone` is deprecated. It has been renamed to `WA.room.onEnterZone`.
+- Method `WA.onLeaveZone` is deprecated. It has been renamed to `WA.room.onLeaveZone`.
diff --git a/docs/maps/api-nav.md b/docs/maps/api-nav.md
new file mode 100644
index 00000000..29323632
--- /dev/null
+++ b/docs/maps/api-nav.md
@@ -0,0 +1,68 @@
+{.section-title.accent.text-primary}
+# API Navigation functions reference
+
+### Opening a web page in a new tab
+
+```
+WA.nav.openTab(url: string): void
+```
+
+Opens the webpage at "url" in your browser, in a new tab.
+
+Example:
+
+```javascript
+WA.nav.openTab('https://www.wikipedia.org/');
+```
+
+### Opening a web page in the current tab
+
+```
+WA.nav.goToPage(url: string): void
+```
+
+Opens the webpage at "url" in your browser in place of WorkAdventure. WorkAdventure will be completely unloaded.
+
+Example:
+
+```javascript
+WA.nav.goToPage('https://www.wikipedia.org/');
+```
+
+### Going to a different map from the script
+
+```
+
+WA.nav.goToRoom(url: string): void
+```
+
+Load the map at url without unloading workadventure
+
+relative urls: "../subFolder/map.json[#start-layer-name]"
+global urls: "/_/global/domain/path/map.json[#start-layer-name]"
+
+Example:
+
+```javascript
+WA.nav.goToRoom("/@/tcm/workadventure/floor0") // workadventure urls
+WA.nav.goToRoom('../otherMap/map.json');
+WA.nav.goToRoom("/_/global/.json#start-layer-2")
+```
+
+### Opening/closing a web page in an iFrame
+
+```
+WA.nav.openCoWebSite(url: string): void
+WA.nav.closeCoWebSite(): void
+```
+
+Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame.
+
+Example:
+
+```javascript
+WA.nav.openCoWebSite('https://www.wikipedia.org/');
+// ...
+WA.nav.closeCoWebSite();
+```
+
diff --git a/docs/maps/api-reference.md b/docs/maps/api-reference.md
index b9525d3c..251edfa2 100644
--- a/docs/maps/api-reference.md
+++ b/docs/maps/api-reference.md
@@ -1,257 +1,11 @@
{.section-title.accent.text-primary}
# API Reference
-### Sending a message in the chat
-
-```
-sendChatMessage(message: string, author: string): void
-```
-
-Sends a message in the chat. The message is only visible in the browser of the current user.
-
-* **message**: the message to be displayed in the chat
-* **author**: the name displayed for the author of the message. It does not have to be a real user.
-
-Example:
-
-```javascript
-WA.sendChatMessage('Hello world', 'Mr Robot');
-```
-
-### Listening to messages from the chat
-
-```javascript
-onChatMessage(callback: (message: string) => void): void
-```
-
-Listens to messages typed by the current user and calls the callback. Messages from other users in the chat cannot be listened to.
-
-* **callback**: the function that will be called when a message is received. It contains the message typed by the user.
-
-Example:
-
-```javascript
-WA.onChatMessage((message => {
- console.log('The user typed a message', message);
-}));
-```
-
-### Detecting when the user enters/leaves a zone
-
-```
-onEnterZone(name: string, callback: () => void): void
-onLeaveZone(name: string, callback: () => void): void
-```
-
-Listens to the position of the current user. The event is triggered when the user enters or leaves a given zone. The name of the zone is stored in the map, on a dedicated layer with the `zone` property.
-
-
-
-
- The `zone` property, applied on a layer
-
-
-
-* **name**: the name of the zone, as defined in the `zone` property.
-* **callback**: the function that will be called when a user enters or leaves the zone.
-
-Example:
-
-```javascript
-WA.onEnterZone('myZone', () => {
- WA.sendChatMessage("Hello!", 'Mr Robot');
-})
-
-WA.onLeaveZone('myZone', () => {
- WA.sendChatMessage("Goodbye!", 'Mr Robot');
-})
-```
-
-### Opening a popup
-
-In order to open a popup window, you must first define the position of the popup on your map.
-
-You can position this popup by using a "rectangle" object in Tiled that you will place on an "object" layer.
-
-
-
-
-
-
-
-
-
-
-```
-openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup
-```
-
-* **targetObject**: the name of the rectangle object defined in Tiled.
-* **message**: the message to display in the popup.
-* **buttons**: an array of action buttons defined underneath the popup.
-
-Action buttons are `ButtonDescriptor` objects containing these properties.
-
-* **label (_string_)**: The label of the button.
-* **className (_string_)**: The visual type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled".
-* **callback (_(popup: Popup)=>void_)**: Callback called when the button is pressed.
-
-Please note that `openPopup` returns an object of the `Popup` class. Also, the callback called when a button is clicked is passed a `Popup` object.
-
-The `Popup` class that represents an open popup contains a single method: `close()`. This will obviously close the popup when called.
-
-```javascript
-class Popup {
- /**
- * Closes the popup
- */
- close() {};
-}
-```
-
-Example:
-
-```javascript
-let helloWorldPopup;
-
-// Open the popup when we enter a given zone
-helloWorldPopup = WA.onEnterZone('myZone', () => {
- WA.openPopup("popupRectangle", 'Hello world!', [{
- label: "Close",
- className: "primary",
- callback: (popup) => {
- // Close the popup when the "Close" button is pressed.
- popup.close();
- }
- });
-}]);
-
-// Close the popup when we leave the zone.
-WA.onLeaveZone('myZone', () => {
- helloWorldPopup.close();
-});
-```
-
-### Disabling / restoring controls
-
-```
-disablePlayerControls(): void
-restorePlayerControls(): void
-```
-
-These 2 methods can be used to completely disable player controls and to enable them again.
-
-When controls are disabled, the user cannot move anymore using keyboard input. This can be useful in a "First Time User Experience" part, to display an important message to a user before letting him/her move again.
-
-Example:
-
-```javascript
-WA.onEnterZone('myZone', () => {
- WA.disablePlayerControls();
- WA.openPopup("popupRectangle", 'This is an imporant message!', [{
- label: "Got it!",
- className: "primary",
- callback: (popup) => {
- WA.restorePlayerControls();
- popup.close();
- }
- }]);
-});
-```
-
-### Opening a web page in a new tab
-
-```
-openTab(url: string): void
-```
-
-Opens the webpage at "url" in your browser, in a new tab.
-
-Example:
-
-```javascript
-WA.openTab('https://www.wikipedia.org/');
-```
-
-### Opening a web page in the current tab
-
-```
-goToPage(url: string): void
-```
-
-Opens the webpage at "url" in your browser in place of WorkAdventure. WorkAdventure will be completely unloaded.
-
-Example:
-
-```javascript
-WA.goToPage('https://www.wikipedia.org/');
-```
-
-### Going to a different map from the script
-
-```
-
-goToRoom(url: string): void
-```
-
-Load the map at url without unloading workadventure
-
-relative urls: "../subFolder/map.json[#start-layer-name]"
-global urls: "/_/global/domain/path/map.json[#start-layer-name]"
-
-Example:
-
-```javascript
-WA.goToRoom("/@/tcm/workadventure/floor0") // workadventure urls
-WA.goToRoom('../otherMap/map.json');
-WA.goToRoom("/_/global/.json#start-layer-2")
-```
-
-### Opening/closing a web page in an iFrame
-
-```
-openCoWebSite(url: string): void
-closeCoWebSite(): void
-```
-
-Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame.
-
-Example:
-
-```javascript
-WA.openCoWebSite('https://www.wikipedia.org/');
-// ...
-WA.closeCoWebSite();
-```
-
-### Load a sound from an url
-
-```
-loadSound(url: string): Sound
-```
-
-Load a sound from an url
-
-Please note that `loadSound` returns an object of the `Sound` class
-
-The `Sound` class that represents a loaded sound contains two methods: `play(soundConfig : SoundConfig|undefined)` and `stop()`
-
-The parameter soundConfig is optional, if you call play without a Sound config the sound will be played with the basic configuration.
-
-Example:
-
-```javascript
-var mySound = WA.loadSound("Sound.ogg");
-var config = {
- volume : 0.5,
- loop : false,
- rate : 1,
- detune : 1,
- delay : 0,
- seek : 0,
- mute : false
-}
-mySound.play(config);
-// ...
-mySound.stop();
-```
+- [Navigation functions](api-nav.md)
+- [Chat functions](api-chat.md)
+- [Room functions](api-room.md)
+- [UI functions](api-ui.md)
+- [Sound functions](api-sound.md)
+- [Controls functions](api-controls.md)
+
+- [List of deprecated functions](api-deprecated.md)
diff --git a/docs/maps/api-room.md b/docs/maps/api-room.md
new file mode 100644
index 00000000..dc7a8612
--- /dev/null
+++ b/docs/maps/api-room.md
@@ -0,0 +1,33 @@
+{.section-title.accent.text-primary}
+# API Room functions Reference
+
+### Detecting when the user enters/leaves a zone
+
+```
+WA.room.onEnterZone(name: string, callback: () => void): void
+WA.room.onLeaveZone(name: string, callback: () => void): void
+```
+
+Listens to the position of the current user. The event is triggered when the user enters or leaves a given zone. The name of the zone is stored in the map, on a dedicated layer with the `zone` property.
+
+
+
+
+ The `zone` property, applied on a layer
+
+
+
+* **name**: the name of the zone, as defined in the `zone` property.
+* **callback**: the function that will be called when a user enters or leaves the zone.
+
+Example:
+
+```javascript
+WA.room.onEnterZone('myZone', () => {
+ WA.chat.sendChatMessage("Hello!", 'Mr Robot');
+})
+
+WA.room.onLeaveZone('myZone', () => {
+ WA.chat.sendChatMessage("Goodbye!", 'Mr Robot');
+})
+```
diff --git a/docs/maps/api-sound.md b/docs/maps/api-sound.md
new file mode 100644
index 00000000..3c57ecae
--- /dev/null
+++ b/docs/maps/api-sound.md
@@ -0,0 +1,34 @@
+{.section-title.accent.text-primary}
+# API Sound functions Reference
+
+### Load a sound from an url
+
+```
+WA.sound.loadSound(url: string): Sound
+```
+
+Load a sound from an url
+
+Please note that `loadSound` returns an object of the `Sound` class
+
+The `Sound` class that represents a loaded sound contains two methods: `play(soundConfig : SoundConfig|undefined)` and `stop()`
+
+The parameter soundConfig is optional, if you call play without a Sound config the sound will be played with the basic configuration.
+
+Example:
+
+```javascript
+var mySound = WA.sound.loadSound("Sound.ogg");
+var config = {
+ volume : 0.5,
+ loop : false,
+ rate : 1,
+ detune : 1,
+ delay : 0,
+ seek : 0,
+ mute : false
+}
+mySound.play(config);
+// ...
+mySound.stop();
+```
diff --git a/docs/maps/api-ui.md b/docs/maps/api-ui.md
new file mode 100644
index 00000000..f15de5df
--- /dev/null
+++ b/docs/maps/api-ui.md
@@ -0,0 +1,67 @@
+{.section-title.accent.text-primary}
+# API UI functions Reference
+
+### Opening a popup
+
+In order to open a popup window, you must first define the position of the popup on your map.
+
+You can position this popup by using a "rectangle" object in Tiled that you will place on an "object" layer.
+
+