diff --git a/.circleci/config.yml b/.circleci/config.yml
index 13074f6bf..9f87e4712 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -58,6 +58,7 @@ jobs:
           command: |
             yarn install
             yarn run fmt:clj:check
+            yarn run fmt:js:check
 
       - run:
           name: "common linter check"
diff --git a/frontend/.prettierrc b/frontend/.prettierrc
deleted file mode 100644
index eb8da3b69..000000000
--- a/frontend/.prettierrc
+++ /dev/null
@@ -1,2 +0,0 @@
----
-printWidth: 110
\ No newline at end of file
diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json
new file mode 100644
index 000000000..f6769669c
--- /dev/null
+++ b/frontend/.prettierrc.json
@@ -0,0 +1,11 @@
+{
+  "overrides": [
+    {
+      "files": "*.scss",
+      "options": {
+        "printWidth": 110
+      }
+    }
+  ]
+}
+
diff --git a/frontend/package.json b/frontend/package.json
index 57df55eda..e716c82fb 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -19,6 +19,8 @@
   "scripts": {
     "fmt:clj:check": "cljfmt check --parallel=false src/ test/",
     "fmt:clj": "cljfmt fix --parallel=true src/ test/",
+    "fmt:js:check": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js",
+    "fmt:js": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -w",
     "lint:scss": "yarn run prettier -c resources/styles -c src/**/*.scss",
     "lint:scss:fix": "yarn run prettier -c resources/styles -c src/**/*.scss -w",
     "lint:clj": "clj-kondo --parallel --lint src/",
@@ -73,7 +75,7 @@
     "p-limit": "^5.0.0",
     "postcss": "^8.4.38",
     "postcss-clean": "^1.2.2",
-    "prettier": "^3.2.5",
+    "prettier": "3.3.2",
     "pretty-time": "^1.1.0",
     "prop-types": "^15.8.1",
     "rimraf": "^5.0.7",
diff --git a/frontend/playwright/helpers/MockWebSocketHelper.js b/frontend/playwright/helpers/MockWebSocketHelper.js
index 42d06d5eb..8cf63f973 100644
--- a/frontend/playwright/helpers/MockWebSocketHelper.js
+++ b/frontend/playwright/helpers/MockWebSocketHelper.js
@@ -14,12 +14,17 @@ export class MockWebSocketHelper extends EventTarget {
       }
       this.#mocks.get(url).dispatchEvent(new MessageEvent("message", { data }));
     });
-    await page.exposeFunction("onMockWebSocketSpyClose", (url, code, reason) => {
-      if (!this.#mocks.has(url)) {
-        throw new Error(`WebSocket with URL ${url} not found`);
-      }
-      this.#mocks.get(url).dispatchEvent(new CloseEvent("close", { code, reason }));
-    });
+    await page.exposeFunction(
+      "onMockWebSocketSpyClose",
+      (url, code, reason) => {
+        if (!this.#mocks.has(url)) {
+          throw new Error(`WebSocket with URL ${url} not found`);
+        }
+        this.#mocks
+          .get(url)
+          .dispatchEvent(new CloseEvent("close", { code, reason }));
+      },
+    );
     await page.addInitScript({ path: "playwright/scripts/MockWebSocket.js" });
   }
 
diff --git a/frontend/playwright/scripts/MockWebSocket.js b/frontend/playwright/scripts/MockWebSocket.js
index aa54067da..a401e6552 100644
--- a/frontend/playwright/scripts/MockWebSocket.js
+++ b/frontend/playwright/scripts/MockWebSocket.js
@@ -188,13 +188,18 @@ window.WebSocket = class MockWebSocket extends EventTarget {
 
   mockClose(code, reason) {
     this.#readyState = MockWebSocket.CLOSED;
-    this.dispatchEvent(new CloseEvent("close", { code: code || 1000, reason: reason || "" }));
+    this.dispatchEvent(
+      new CloseEvent("close", { code: code || 1000, reason: reason || "" }),
+    );
     return this;
   }
 
   send(data) {
     if (this.#readyState === MockWebSocket.CONNECTING) {
-      throw new DOMException("InvalidStateError", "MockWebSocket is not connected");
+      throw new DOMException(
+        "InvalidStateError",
+        "MockWebSocket is not connected",
+      );
     }
 
     if (this.#spyMessage) {
@@ -203,7 +208,12 @@ window.WebSocket = class MockWebSocket extends EventTarget {
   }
 
   close(code, reason) {
-    if (code && !Number.isInteger(code) && code !== 1000 && (code < 3000 || code > 4999)) {
+    if (
+      code &&
+      !Number.isInteger(code) &&
+      code !== 1000 &&
+      (code < 3000 || code > 4999)
+    ) {
       throw new DOMException("InvalidAccessError", "Invalid code");
     }
 
@@ -214,7 +224,9 @@ window.WebSocket = class MockWebSocket extends EventTarget {
       }
     }
 
-    if ([MockWebSocket.CLOSED, MockWebSocket.CLOSING].includes(this.#readyState)) {
+    if (
+      [MockWebSocket.CLOSED, MockWebSocket.CLOSING].includes(this.#readyState)
+    ) {
       return;
     }
 
diff --git a/frontend/playwright/ui/pages/BasePage.js b/frontend/playwright/ui/pages/BasePage.js
index 076bf13f6..b233be060 100644
--- a/frontend/playwright/ui/pages/BasePage.js
+++ b/frontend/playwright/ui/pages/BasePage.js
@@ -4,7 +4,9 @@ export class BasePage {
       throw new TypeError("Invalid page argument. Must be a Playwright page.");
     }
     if (typeof path !== "string" && !(path instanceof RegExp)) {
-      throw new TypeError("Invalid path argument. Must be a string or a RegExp.");
+      throw new TypeError(
+        "Invalid path argument. Must be a string or a RegExp.",
+      );
     }
 
     const url = typeof path === "string" ? `**/api/rpc/command/${path}` : path;
diff --git a/frontend/playwright/ui/pages/DashboardPage.js b/frontend/playwright/ui/pages/DashboardPage.js
index 0c9bff0e9..6d340c62e 100644
--- a/frontend/playwright/ui/pages/DashboardPage.js
+++ b/frontend/playwright/ui/pages/DashboardPage.js
@@ -5,7 +5,11 @@ export class DashboardPage extends BaseWebSocketPage {
   static async init(page) {
     await BaseWebSocketPage.initWebSockets(page);
 
-    await BaseWebSocketPage.mockRPC(page, "get-teams", "logged-in-user/get-teams-default.json");
+    await BaseWebSocketPage.mockRPC(
+      page,
+      "get-teams",
+      "logged-in-user/get-teams-default.json",
+    );
     await BaseWebSocketPage.mockRPC(
       page,
       "get-font-variants?team-id=*",
@@ -58,7 +62,9 @@ export class DashboardPage extends BaseWebSocketPage {
 
     this.sidebar = page.getByTestId("dashboard-sidebar");
     this.sidebarMenu = this.sidebar.getByRole("menu");
-    this.mainHeading = page.getByTestId("dashboard-header").getByRole("heading", { level: 1 });
+    this.mainHeading = page
+      .getByTestId("dashboard-header")
+      .getByRole("heading", { level: 1 });
 
     this.addProjectButton = page.getByRole("button", { name: "+ NEW PROJECT" });
     this.projectName = page.getByText("Project 1");
@@ -70,13 +76,20 @@ export class DashboardPage extends BaseWebSocketPage {
     this.searchButton = page.getByRole("button", { name: "dashboard-search" });
     this.searchInput = page.getByPlaceholder("Search…");
 
-    this.teamDropdown = this.sidebar.getByRole("button", { name: "Your Penpot" });
-    this.userAccount = this.sidebar.getByRole("button", { name: /Princesa Leia/ });
+    this.teamDropdown = this.sidebar.getByRole("button", {
+      name: "Your Penpot",
+    });
+    this.userAccount = this.sidebar.getByRole("button", {
+      name: /Princesa Leia/,
+    });
     this.userProfileOption = this.sidebarMenu.getByText("Your account");
   }
 
   async setupDraftsEmpty() {
-    await this.mockRPC("get-project-files?project-id=*", "dashboard/get-project-files-empty.json");
+    await this.mockRPC(
+      "get-project-files?project-id=*",
+      "dashboard/get-project-files-empty.json",
+    );
   }
 
   async setupSearchEmpty() {
@@ -86,36 +99,74 @@ export class DashboardPage extends BaseWebSocketPage {
   }
 
   async setupLibrariesEmpty() {
-    await this.mockRPC("get-team-shared-files?team-id=*", "dashboard/get-shared-files-empty.json");
+    await this.mockRPC(
+      "get-team-shared-files?team-id=*",
+      "dashboard/get-shared-files-empty.json",
+    );
   }
 
   async setupDrafts() {
-    await this.mockRPC("get-project-files?project-id=*", "dashboard/get-project-files.json");
+    await this.mockRPC(
+      "get-project-files?project-id=*",
+      "dashboard/get-project-files.json",
+    );
   }
 
   async setupNewProject() {
-    await this.mockRPC("create-project", "dashboard/create-project.json", { method: "POST" });
-    await this.mockRPC("get-projects?team-id=*", "dashboard/get-projects-new.json");
+    await this.mockRPC("create-project", "dashboard/create-project.json", {
+      method: "POST",
+    });
+    await this.mockRPC(
+      "get-projects?team-id=*",
+      "dashboard/get-projects-new.json",
+    );
   }
 
   async setupDashboardFull() {
-    await this.mockRPC("get-projects?team-id=*", "dashboard/get-projects-full.json");
-    await this.mockRPC("get-project-files?project-id=*", "dashboard/get-project-files.json");
-    await this.mockRPC("get-team-shared-files?team-id=*", "dashboard/get-shared-files.json");
-    await this.mockRPC("get-team-shared-files?project-id=*", "dashboard/get-shared-files.json");
-    await this.mockRPC("get-team-recent-files?team-id=*", "dashboard/get-team-recent-files.json");
-    await this.mockRPC("get-font-variants?team-id=*", "dashboard/get-font-variants.json");
-    await this.mockRPC("search-files", "dashboard/search-files.json", { method: "POST" });
+    await this.mockRPC(
+      "get-projects?team-id=*",
+      "dashboard/get-projects-full.json",
+    );
+    await this.mockRPC(
+      "get-project-files?project-id=*",
+      "dashboard/get-project-files.json",
+    );
+    await this.mockRPC(
+      "get-team-shared-files?team-id=*",
+      "dashboard/get-shared-files.json",
+    );
+    await this.mockRPC(
+      "get-team-shared-files?project-id=*",
+      "dashboard/get-shared-files.json",
+    );
+    await this.mockRPC(
+      "get-team-recent-files?team-id=*",
+      "dashboard/get-team-recent-files.json",
+    );
+    await this.mockRPC(
+      "get-font-variants?team-id=*",
+      "dashboard/get-font-variants.json",
+    );
+    await this.mockRPC("search-files", "dashboard/search-files.json", {
+      method: "POST",
+    });
     await this.mockRPC("search-files", "dashboard/search-files.json");
     await this.mockRPC("get-teams", "logged-in-user/get-teams-complete.json");
   }
 
   async setupAccessTokensEmpty() {
-    await this.mockRPC("get-access-tokens", "dashboard/get-access-tokens-empty.json");
+    await this.mockRPC(
+      "get-access-tokens",
+      "dashboard/get-access-tokens-empty.json",
+    );
   }
 
   async createAccessToken() {
-    await this.mockRPC("create-access-token", "dashboard/create-access-token.json", { method: "POST" });
+    await this.mockRPC(
+      "create-access-token",
+      "dashboard/create-access-token.json",
+      { method: "POST" },
+    );
   }
 
   async setupAccessTokens() {
@@ -123,15 +174,24 @@ export class DashboardPage extends BaseWebSocketPage {
   }
 
   async setupTeamInvitationsEmpty() {
-    await this.mockRPC("get-team-invitations?team-id=*", "dashboard/get-team-invitations-empty.json");
+    await this.mockRPC(
+      "get-team-invitations?team-id=*",
+      "dashboard/get-team-invitations-empty.json",
+    );
   }
 
   async setupTeamInvitations() {
-    await this.mockRPC("get-team-invitations?team-id=*", "dashboard/get-team-invitations.json");
+    await this.mockRPC(
+      "get-team-invitations?team-id=*",
+      "dashboard/get-team-invitations.json",
+    );
   }
 
   async setupTeamWebhooksEmpty() {
-    await this.mockRPC("get-webhooks?team-id=*", "dashboard/get-webhooks-empty.json");
+    await this.mockRPC(
+      "get-webhooks?team-id=*",
+      "dashboard/get-webhooks-empty.json",
+    );
   }
 
   async setupTeamWebhooks() {
@@ -139,36 +199,53 @@ export class DashboardPage extends BaseWebSocketPage {
   }
 
   async setupTeamSettings() {
-    await this.mockRPC("get-team-stats?team-id=*", "dashboard/get-team-stats.json");
+    await this.mockRPC(
+      "get-team-stats?team-id=*",
+      "dashboard/get-team-stats.json",
+    );
   }
 
   async goToDashboard() {
-    await this.page.goto(`#/dashboard/team/${DashboardPage.anyTeamId}/projects`);
+    await this.page.goto(
+      `#/dashboard/team/${DashboardPage.anyTeamId}/projects`,
+    );
     await expect(this.mainHeading).toBeVisible();
   }
 
   async goToSecondTeamDashboard() {
-    await this.page.goto(`#/dashboard/team/${DashboardPage.secondTeamId}/projects`);
+    await this.page.goto(
+      `#/dashboard/team/${DashboardPage.secondTeamId}/projects`,
+    );
   }
 
   async goToSecondTeamMembersSection() {
-    await this.page.goto(`#/dashboard/team/${DashboardPage.secondTeamId}/members`);
+    await this.page.goto(
+      `#/dashboard/team/${DashboardPage.secondTeamId}/members`,
+    );
   }
 
   async goToSecondTeamInvitationsSection() {
-    await this.page.goto(`#/dashboard/team/${DashboardPage.secondTeamId}/invitations`);
+    await this.page.goto(
+      `#/dashboard/team/${DashboardPage.secondTeamId}/invitations`,
+    );
   }
 
   async goToSecondTeamWebhooksSection() {
-    await this.page.goto(`#/dashboard/team/${DashboardPage.secondTeamId}/webhooks`);
+    await this.page.goto(
+      `#/dashboard/team/${DashboardPage.secondTeamId}/webhooks`,
+    );
   }
 
   async goToSecondTeamWebhooksSection() {
-    await this.page.goto(`#/dashboard/team/${DashboardPage.secondTeamId}/webhooks`);
+    await this.page.goto(
+      `#/dashboard/team/${DashboardPage.secondTeamId}/webhooks`,
+    );
   }
 
   async goToSecondTeamSettingsSection() {
-    await this.page.goto(`#/dashboard/team/${DashboardPage.secondTeamId}/settings`);
+    await this.page.goto(
+      `#/dashboard/team/${DashboardPage.secondTeamId}/settings`,
+    );
   }
 
   async goToSearch() {
diff --git a/frontend/playwright/ui/pages/LoginPage.js b/frontend/playwright/ui/pages/LoginPage.js
index 965719714..0ee5f863c 100644
--- a/frontend/playwright/ui/pages/LoginPage.js
+++ b/frontend/playwright/ui/pages/LoginPage.js
@@ -6,9 +6,13 @@ export class LoginPage extends BasePage {
     this.loginButton = page.getByRole("button", { name: "Login" });
     this.password = page.getByLabel("Password");
     this.userName = page.getByLabel("Email");
-    this.invalidCredentialsError = page.getByText("Email or password is incorrect");
+    this.invalidCredentialsError = page.getByText(
+      "Email or password is incorrect",
+    );
     this.invalidEmailError = page.getByText("Enter a valid email please");
-    this.initialHeading = page.getByRole("heading", { name: "Log into my account" });
+    this.initialHeading = page.getByRole("heading", {
+      name: "Log into my account",
+    });
   }
 
   async fillEmailAndPasswordInputs(email, password) {
@@ -25,17 +29,35 @@ export class LoginPage extends BasePage {
   }
 
   async setupLoggedInUser() {
-    await this.mockRPC("get-profile", "logged-in-user/get-profile-logged-in.json");
+    await this.mockRPC(
+      "get-profile",
+      "logged-in-user/get-profile-logged-in.json",
+    );
     await this.mockRPC("get-teams", "logged-in-user/get-teams-default.json");
-    await this.mockRPC("get-font-variants?team-id=*", "logged-in-user/get-font-variants-empty.json");
-    await this.mockRPC("get-projects?team-id=*", "logged-in-user/get-projects-default.json");
-    await this.mockRPC("get-team-members?team-id=*", "logged-in-user/get-team-members-your-penpot.json");
-    await this.mockRPC("get-team-users?team-id=*", "logged-in-user/get-team-users-single-user.json");
+    await this.mockRPC(
+      "get-font-variants?team-id=*",
+      "logged-in-user/get-font-variants-empty.json",
+    );
+    await this.mockRPC(
+      "get-projects?team-id=*",
+      "logged-in-user/get-projects-default.json",
+    );
+    await this.mockRPC(
+      "get-team-members?team-id=*",
+      "logged-in-user/get-team-members-your-penpot.json",
+    );
+    await this.mockRPC(
+      "get-team-users?team-id=*",
+      "logged-in-user/get-team-users-single-user.json",
+    );
     await this.mockRPC(
       "get-unread-comment-threads?team-id=*",
       "logged-in-user/get-team-users-single-user.json",
     );
-    await this.mockRPC("get-team-recent-files?team-id=*", "logged-in-user/get-team-recent-files-empty.json");
+    await this.mockRPC(
+      "get-team-recent-files?team-id=*",
+      "logged-in-user/get-team-recent-files-empty.json",
+    );
     await this.mockRPC(
       "get-profiles-for-file-comments",
       "logged-in-user/get-profiles-for-file-comments-empty.json",
@@ -43,11 +65,18 @@ export class LoginPage extends BasePage {
   }
 
   async setupLoginSuccess() {
-    await this.mockRPC("login-with-password", "logged-in-user/login-with-password-success.json");
+    await this.mockRPC(
+      "login-with-password",
+      "logged-in-user/login-with-password-success.json",
+    );
   }
 
   async setupLoginError() {
-    await this.mockRPC("login-with-password", "login-with-password-error.json", { status: 400 });
+    await this.mockRPC(
+      "login-with-password",
+      "login-with-password-error.json",
+      { status: 400 },
+    );
   }
 }
 
diff --git a/frontend/playwright/ui/pages/OnboardingPage.js b/frontend/playwright/ui/pages/OnboardingPage.js
index 0fe68e78a..81e199588 100644
--- a/frontend/playwright/ui/pages/OnboardingPage.js
+++ b/frontend/playwright/ui/pages/OnboardingPage.js
@@ -3,42 +3,42 @@ import { BaseWebSocketPage } from "./BaseWebSocketPage";
 export class OnboardingPage extends BaseWebSocketPage {
   constructor(page) {
     super(page);
-    this.submitButton = page.getByRole("Button",{ name: "Next" })
+    this.submitButton = page.getByRole("Button", { name: "Next" });
   }
 
   async fillOnboardingInputsStep1() {
-    await this.page.getByText('Personal').click();
-    await this.page.getByText('Select option').click();
-    await this.page.getByText('Testing before self-hosting').click();
+    await this.page.getByText("Personal").click();
+    await this.page.getByText("Select option").click();
+    await this.page.getByText("Testing before self-hosting").click();
 
     await this.submitButton.click();
   }
 
   async fillOnboardingInputsStep2() {
-    await this.page.getByText('Figma').click();
+    await this.page.getByText("Figma").click();
 
     await this.submitButton.click();
   }
 
   async fillOnboardingInputsStep3() {
-    await this.page.getByText('Select option').first().click();
-    await this.page.getByText('Product Managment').click();
-    await this.page.getByText('Select option').first().click();
-    await this.page.getByText('Director').click();
-    await this.page.getByText('Select option').click();
-    await this.page.getByText('11-30').click();
+    await this.page.getByText("Select option").first().click();
+    await this.page.getByText("Product Managment").click();
+    await this.page.getByText("Select option").first().click();
+    await this.page.getByText("Director").click();
+    await this.page.getByText("Select option").click();
+    await this.page.getByText("11-30").click();
 
     await this.submitButton.click();
   }
 
   async fillOnboardingInputsStep4() {
-    await this.page.getByText('Other').click();
-    await this.page.getByPlaceholder('Other (specify)').fill("Another");
+    await this.page.getByText("Other").click();
+    await this.page.getByPlaceholder("Other (specify)").fill("Another");
     await this.submitButton.click();
   }
 
   async fillOnboardingInputsStep5() {
-    await this.page.getByText('Event').click();
+    await this.page.getByText("Event").click();
   }
 }
 
diff --git a/frontend/playwright/ui/pages/ViewerPage.js b/frontend/playwright/ui/pages/ViewerPage.js
index fa0622641..41fd45a23 100644
--- a/frontend/playwright/ui/pages/ViewerPage.js
+++ b/frontend/playwright/ui/pages/ViewerPage.js
@@ -15,12 +15,21 @@ export class ViewerPage extends BaseWebSocketPage {
   }
 
   async setupLoggedInUser() {
-    await this.mockRPC("get-profile", "logged-in-user/get-profile-logged-in.json");
+    await this.mockRPC(
+      "get-profile",
+      "logged-in-user/get-profile-logged-in.json",
+    );
   }
 
   async setupEmptyFile() {
-    await this.mockRPC(/get\-view\-only\-bundle\?/, "viewer/get-view-only-bundle-empty-file.json");
-    await this.mockRPC("get-comment-threads?file-id=*", "workspace/get-comment-threads-empty.json");
+    await this.mockRPC(
+      /get\-view\-only\-bundle\?/,
+      "viewer/get-view-only-bundle-empty-file.json",
+    );
+    await this.mockRPC(
+      "get-comment-threads?file-id=*",
+      "workspace/get-comment-threads-empty.json",
+    );
     await this.mockRPC(
       "get-file-fragment?file-id=*&fragment-id=*",
       "viewer/get-file-fragment-empty-file.json",
@@ -28,24 +37,42 @@ export class ViewerPage extends BaseWebSocketPage {
   }
 
   async setupFileWithSingleBoard() {
-    await this.mockRPC(/get\-view\-only\-bundle\?/, "viewer/get-view-only-bundle-single-board.json");
-    await this.mockRPC("get-comment-threads?file-id=*", "workspace/get-comment-threads-empty.json");
+    await this.mockRPC(
+      /get\-view\-only\-bundle\?/,
+      "viewer/get-view-only-bundle-single-board.json",
+    );
+    await this.mockRPC(
+      "get-comment-threads?file-id=*",
+      "workspace/get-comment-threads-empty.json",
+    );
     await this.mockRPC(
       "get-file-fragment?file-id=*&fragment-id=*",
       "viewer/get-file-fragment-single-board.json",
     );
-  };
+  }
 
   async setupFileWithComments() {
-    await this.mockRPC(/get\-view\-only\-bundle\?/, "viewer/get-view-only-bundle-single-board.json");
-    await this.mockRPC("get-comment-threads?file-id=*", "workspace/get-comment-threads-not-empty.json");
+    await this.mockRPC(
+      /get\-view\-only\-bundle\?/,
+      "viewer/get-view-only-bundle-single-board.json",
+    );
+    await this.mockRPC(
+      "get-comment-threads?file-id=*",
+      "workspace/get-comment-threads-not-empty.json",
+    );
     await this.mockRPC(
       "get-file-fragment?file-id=*&fragment-id=*",
       "viewer/get-file-fragment-single-board.json",
     );
-    await this.mockRPC("get-comments?thread-id=*", "workspace/get-thread-comments.json");
-    await this.mockRPC("update-comment-thread-status", "workspace/update-comment-thread-status.json");
-  };
+    await this.mockRPC(
+      "get-comments?thread-id=*",
+      "workspace/get-thread-comments.json",
+    );
+    await this.mockRPC(
+      "update-comment-thread-status",
+      "workspace/update-comment-thread-status.json",
+    );
+  }
 
   #ws = null;
 
@@ -53,8 +80,13 @@ export class ViewerPage extends BaseWebSocketPage {
     super(page);
   }
 
-  async goToViewer({ fileId = ViewerPage.anyFileId, pageId = ViewerPage.anyPageId } = {}) {
-    await this.page.goto(`/#/view/${fileId}?page-id=${pageId}&section=interactions&index=0`);
+  async goToViewer({
+    fileId = ViewerPage.anyFileId,
+    pageId = ViewerPage.anyPageId,
+  } = {}) {
+    await this.page.goto(
+      `/#/view/${fileId}?page-id=${pageId}&section=interactions&index=0`,
+    );
 
     this.#ws = await this.waitForNotificationsWebSocket();
     await this.#ws.mockOpen();
@@ -72,15 +104,14 @@ export class ViewerPage extends BaseWebSocketPage {
 
   async showCommentsThread(number, clickOptions = {}) {
     await this.page
-    .getByTestId("floating-thread-bubble")
-    .filter({ hasText: number.toString() })
-    .click(clickOptions);
+      .getByTestId("floating-thread-bubble")
+      .filter({ hasText: number.toString() })
+      .click(clickOptions);
   }
 
   async showCode(clickOptions = {}) {
     await this.page
-      .getByRole("button", { name: 'Inspect (G I)' })
+      .getByRole("button", { name: "Inspect (G I)" })
       .click(clickOptions);
   }
 }
-
diff --git a/frontend/playwright/ui/pages/WorkspacePage.js b/frontend/playwright/ui/pages/WorkspacePage.js
index 6e6c8b597..76f0c0534 100644
--- a/frontend/playwright/ui/pages/WorkspacePage.js
+++ b/frontend/playwright/ui/pages/WorkspacePage.js
@@ -11,7 +11,11 @@ export class WorkspacePage extends BaseWebSocketPage {
   static async init(page) {
     await BaseWebSocketPage.initWebSockets(page);
 
-    await BaseWebSocketPage.mockRPC(page, "get-profile", "logged-in-user/get-profile-logged-in.json");
+    await BaseWebSocketPage.mockRPC(
+      page,
+      "get-profile",
+      "logged-in-user/get-profile-logged-in.json",
+    );
     await BaseWebSocketPage.mockRPC(
       page,
       "get-team-users?file-id=*",
@@ -22,8 +26,16 @@ export class WorkspacePage extends BaseWebSocketPage {
       "get-comment-threads?file-id=*",
       "workspace/get-comment-threads-empty.json",
     );
-    await BaseWebSocketPage.mockRPC(page, "get-project?id=*", "workspace/get-project-default.json");
-    await BaseWebSocketPage.mockRPC(page, "get-team?id=*", "workspace/get-team-default.json");
+    await BaseWebSocketPage.mockRPC(
+      page,
+      "get-project?id=*",
+      "workspace/get-project-default.json",
+    );
+    await BaseWebSocketPage.mockRPC(
+      page,
+      "get-team?id=*",
+      "workspace/get-team-default.json",
+    );
     await BaseWebSocketPage.mockRPC(
       page,
       "get-profiles-for-file-comments?file-id=*",
@@ -40,12 +52,18 @@ export class WorkspacePage extends BaseWebSocketPage {
   constructor(page) {
     super(page);
     this.pageName = page.getByTestId("page-name");
-    this.presentUserListItems = page.getByTestId("active-users-list").getByAltText("Princesa Leia");
+    this.presentUserListItems = page
+      .getByTestId("active-users-list")
+      .getByAltText("Princesa Leia");
     this.viewport = page.getByTestId("viewport");
-    this.rootShape = page.locator(`[id="shape-00000000-0000-0000-0000-000000000000"]`);
+    this.rootShape = page.locator(
+      `[id="shape-00000000-0000-0000-0000-000000000000"]`,
+    );
     this.toolbarOptions = page.getByTestId("toolbar-options");
     this.rectShapeButton = page.getByRole("button", { name: "Rectangle (R)" });
-    this.toggleToolbarButton = page.getByRole("button", { name: "Toggle toolbar" });
+    this.toggleToolbarButton = page.getByRole("button", {
+      name: "Toggle toolbar",
+    });
     this.colorpicker = page.getByTestId("colorpicker");
     this.layers = page.getByTestId("layer-tree");
     this.palette = page.getByTestId("palette");
@@ -54,11 +72,18 @@ export class WorkspacePage extends BaseWebSocketPage {
     this.selectionRect = page.getByTestId("workspace-selection-rect");
     this.horizontalScrollbar = page.getByTestId("horizontal-scrollbar");
     this.librariesModal = page.getByTestId("libraries-modal");
-    this.togglePalettesVisibility = page.getByTestId("toggle-palettes-visibility");
+    this.togglePalettesVisibility = page.getByTestId(
+      "toggle-palettes-visibility",
+    );
   }
 
-  async goToWorkspace({ fileId = WorkspacePage.anyFileId, pageId = WorkspacePage.anyPageId } = {}) {
-    await this.page.goto(`/#/workspace/${WorkspacePage.anyProjectId}/${fileId}?page-id=${pageId}`);
+  async goToWorkspace({
+    fileId = WorkspacePage.anyFileId,
+    pageId = WorkspacePage.anyPageId,
+  } = {}) {
+    await this.page.goto(
+      `/#/workspace/${WorkspacePage.anyProjectId}/${fileId}?page-id=${pageId}`,
+    );
 
     this.#ws = await this.waitForNotificationsWebSocket();
     await this.#ws.mockOpen();
@@ -79,10 +104,22 @@ export class WorkspacePage extends BaseWebSocketPage {
   }
 
   async setupEmptyFile() {
-    await this.mockRPC("get-profile", "logged-in-user/get-profile-logged-in.json");
-    await this.mockRPC("get-team-users?file-id=*", "logged-in-user/get-team-users-single-user.json");
-    await this.mockRPC("get-comment-threads?file-id=*", "workspace/get-comment-threads-empty.json");
-    await this.mockRPC("get-project?id=*", "workspace/get-project-default.json");
+    await this.mockRPC(
+      "get-profile",
+      "logged-in-user/get-profile-logged-in.json",
+    );
+    await this.mockRPC(
+      "get-team-users?file-id=*",
+      "logged-in-user/get-team-users-single-user.json",
+    );
+    await this.mockRPC(
+      "get-comment-threads?file-id=*",
+      "workspace/get-comment-threads-empty.json",
+    );
+    await this.mockRPC(
+      "get-project?id=*",
+      "workspace/get-project-default.json",
+    );
     await this.mockRPC("get-team?id=*", "workspace/get-team-default.json");
     await this.mockRPC(
       "get-profiles-for-file-comments?file-id=*",
@@ -93,9 +130,18 @@ export class WorkspacePage extends BaseWebSocketPage {
       "get-file-object-thumbnails?file-id=*",
       "workspace/get-file-object-thumbnails-blank.json",
     );
-    await this.mockRPC("get-font-variants?team-id=*", "workspace/get-font-variants-empty.json");
-    await this.mockRPC("get-file-fragment?file-id=*", "workspace/get-file-fragment-blank.json");
-    await this.mockRPC("get-file-libraries?file-id=*", "workspace/get-file-libraries-empty.json");
+    await this.mockRPC(
+      "get-font-variants?team-id=*",
+      "workspace/get-font-variants-empty.json",
+    );
+    await this.mockRPC(
+      "get-file-fragment?file-id=*",
+      "workspace/get-file-fragment-blank.json",
+    );
+    await this.mockRPC(
+      "get-file-libraries?file-id=*",
+      "workspace/get-file-libraries-empty.json",
+    );
   }
 
   async clickWithDragViewportAt(x, y, width, height) {
@@ -132,14 +178,18 @@ export class WorkspacePage extends BaseWebSocketPage {
   }
 
   async clickToggableLayer(name, clickOptions = {}) {
-    const layer = this.layers.getByTestId("layer-item").filter({ has: this.page.getByText(name) });
+    const layer = this.layers
+      .getByTestId("layer-item")
+      .filter({ has: this.page.getByText(name) });
     await layer.getByRole("button").click(clickOptions);
   }
 
   async expectSelectedLayer(name) {
-    await expect(this.layers.getByTestId("layer-row").filter({ has: this.page.getByText(name) })).toHaveClass(
-      /selected/,
-    );
+    await expect(
+      this.layers
+        .getByTestId("layer-row")
+        .filter({ has: this.page.getByText(name) }),
+    ).toHaveClass(/selected/);
   }
 
   async expectHiddenToolbarOptions() {
@@ -163,19 +213,24 @@ export class WorkspacePage extends BaseWebSocketPage {
   }
 
   async closeLibrariesModal(clickOptions = {}) {
-    await this.librariesModal.getByRole("button", { name: "Close" }).click(clickOptions);
+    await this.librariesModal
+      .getByRole("button", { name: "Close" })
+      .click(clickOptions);
   }
 
   async clickColorPalette(clickOptions = {}) {
-    await this.palette.getByRole("button", { name: "Color Palette (Alt+P)" }).click(clickOptions);
+    await this.palette
+      .getByRole("button", { name: "Color Palette (Alt+P)" })
+      .click(clickOptions);
   }
 
   async clickColorPalette(clickOptions = {}) {
-    await this.palette.getByRole("button", { name: "Color Palette (Alt+P)" }).click(clickOptions);
+    await this.palette
+      .getByRole("button", { name: "Color Palette (Alt+P)" })
+      .click(clickOptions);
   }
 
   async clickTogglePalettesVisibility(clickOptions = {}) {
-    await this.togglePalettesVisibility
-    .click(clickOptions);
+    await this.togglePalettesVisibility.click(clickOptions);
   }
 }
diff --git a/frontend/playwright/ui/specs/colorpicker.spec.js b/frontend/playwright/ui/specs/colorpicker.spec.js
index 1793f7ade..0ea20f52b 100644
--- a/frontend/playwright/ui/specs/colorpicker.spec.js
+++ b/frontend/playwright/ui/specs/colorpicker.spec.js
@@ -6,7 +6,9 @@ test.beforeEach(async ({ page }) => {
 });
 
 // Fix for https://tree.taiga.io/project/penpot/issue/7549
-test("Bug 7549 - User clicks on color swatch to display the color picker next to it", async ({ page }) => {
+test("Bug 7549 - User clicks on color swatch to display the color picker next to it", async ({
+  page,
+}) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile(page);
 
diff --git a/frontend/playwright/ui/specs/dashboard.spec.js b/frontend/playwright/ui/specs/dashboard.spec.js
index 3e105199c..b11e1a326 100644
--- a/frontend/playwright/ui/specs/dashboard.spec.js
+++ b/frontend/playwright/ui/specs/dashboard.spec.js
@@ -3,7 +3,11 @@ import DashboardPage from "../pages/DashboardPage";
 
 test.beforeEach(async ({ page }) => {
   await DashboardPage.init(page);
-  await DashboardPage.mockRPC(page, "get-profile", "logged-in-user/get-profile-logged-in-no-onboarding.json");
+  await DashboardPage.mockRPC(
+    page,
+    "get-profile",
+    "logged-in-user/get-profile-logged-in-no-onboarding.json",
+  );
 });
 
 test("Dashboad page has title ", async ({ page }) => {
@@ -41,6 +45,10 @@ test("Lists files in the drafts page", async ({ page }) => {
 
   await dashboardPage.goToDrafts();
 
-  await expect(dashboardPage.page.getByRole("button", { name: /New File 1/ })).toBeVisible();
-  await expect(dashboardPage.page.getByRole("button", { name: /New File 2/ })).toBeVisible();
+  await expect(
+    dashboardPage.page.getByRole("button", { name: /New File 1/ }),
+  ).toBeVisible();
+  await expect(
+    dashboardPage.page.getByRole("button", { name: /New File 2/ }),
+  ).toBeVisible();
 });
diff --git a/frontend/playwright/ui/specs/design-tab.spec.js b/frontend/playwright/ui/specs/design-tab.spec.js
index 7a43aa166..3b28bb534 100644
--- a/frontend/playwright/ui/specs/design-tab.spec.js
+++ b/frontend/playwright/ui/specs/design-tab.spec.js
@@ -12,7 +12,10 @@ const multipleAttributesPageId = `1795a568-0df0-8095-8004-7ba741f56be3`;
 
 const setupFileWithMultipeConstraints = async (workspace) => {
   await workspace.setupEmptyFile();
-  await workspace.mockRPC(/get\-file\?/, "design/get-file-multiple-constraints.json");
+  await workspace.mockRPC(
+    /get\-file\?/,
+    "design/get-file-multiple-constraints.json",
+  );
   await workspace.mockRPC(
     "get-file-object-thumbnails?file-id=*",
     "design/get-file-object-thumbnails-multiple-constraints.json",
@@ -25,7 +28,10 @@ const setupFileWithMultipeConstraints = async (workspace) => {
 
 const setupFileWithMultipeAttributes = async (workspace) => {
   await workspace.setupEmptyFile();
-  await workspace.mockRPC(/get\-file\?/, "design/get-file-multiple-attributes.json");
+  await workspace.mockRPC(
+    /get\-file\?/,
+    "design/get-file-multiple-attributes.json",
+  );
   await workspace.mockRPC(
     "get-file-object-thumbnails?file-id=*",
     "design/get-file-object-thumbnails-multiple-attributes.json",
@@ -47,9 +53,13 @@ test.describe("Constraints", () => {
     await workspace.clickLeafLayer("Ellipse");
     await workspace.clickLeafLayer("Rectangle", { modifiers: ["Shift"] });
 
-    const constraintVDropdown = workspace.page.getByTestId("constraint-v-select");
+    const constraintVDropdown = workspace.page.getByTestId(
+      "constraint-v-select",
+    );
     await expect(constraintVDropdown).toContainText("Mixed");
-    const constraintHDropdown = workspace.page.getByTestId("constraint-h-select");
+    const constraintHDropdown = workspace.page.getByTestId(
+      "constraint-h-select",
+    );
     await expect(constraintHDropdown).toContainText("Mixed");
 
     expect(false);
@@ -57,7 +67,9 @@ test.describe("Constraints", () => {
 });
 
 test.describe("Multiple shapes attributes", () => {
-  test("User selects multiple shapes with sames fills, strokes, shadows and blur", async ({ page }) => {
+  test("User selects multiple shapes with sames fills, strokes, shadows and blur", async ({
+    page,
+  }) => {
     const workspace = new WorkspacePage(page);
     await setupFileWithMultipeConstraints(workspace);
     await workspace.goToWorkspace({
@@ -75,7 +87,9 @@ test.describe("Multiple shapes attributes", () => {
     await expect(workspace.page.getByTestId("add-blur")).toBeVisible();
   });
 
-  test("User selects multiple shapes with different fills, strokes, shadows and blur", async ({ page }) => {
+  test("User selects multiple shapes with different fills, strokes, shadows and blur", async ({
+    page,
+  }) => {
     const workspace = new WorkspacePage(page);
     await setupFileWithMultipeAttributes(workspace);
     await workspace.goToWorkspace({
@@ -93,7 +107,9 @@ test.describe("Multiple shapes attributes", () => {
   });
 });
 
-test("BUG 7760 - Layout losing properties when changing parents", async ({ page }) => {
+test("BUG 7760 - Layout losing properties when changing parents", async ({
+  page,
+}) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
   await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-7760.json");
@@ -101,7 +117,10 @@ test("BUG 7760 - Layout losing properties when changing parents", async ({ page
     "get-file-fragment?file-id=*&fragment-id=*",
     "workspace/get-file-fragment-7760.json",
   );
-  await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-create-rect.json");
+  await workspacePage.mockRPC(
+    "update-file?id=*",
+    "workspace/update-file-create-rect.json",
+  );
 
   await workspacePage.goToWorkspace({
     fileId: "cd90e028-326a-80b4-8004-7cdec16ffad5",
diff --git a/frontend/playwright/ui/specs/login.spec.js b/frontend/playwright/ui/specs/login.spec.js
index d730fb91e..4a2604f4b 100644
--- a/frontend/playwright/ui/specs/login.spec.js
+++ b/frontend/playwright/ui/specs/login.spec.js
@@ -8,7 +8,9 @@ test.beforeEach(async ({ page }) => {
   await page.goto("/#/auth/login");
 });
 
-test("User is redirected to the login page when logged out", async ({ page }) => {
+test("User is redirected to the login page when logged out", async ({
+  page,
+}) => {
   const loginPage = new LoginPage(page);
 
   await loginPage.setupLoggedInUser();
@@ -30,7 +32,9 @@ test.describe("Login form", () => {
     await expect(loginPage.page).toHaveURL(/dashboard/);
   });
 
-  test("User gets error message when submitting an bad formatted email ", async ({ page }) => {
+  test("User gets error message when submitting an bad formatted email ", async ({
+    page,
+  }) => {
     const loginPage = new LoginPage(page);
     await loginPage.setupLoginSuccess();
 
@@ -39,11 +43,16 @@ test.describe("Login form", () => {
     await expect(loginPage.invalidEmailError).toBeVisible();
   });
 
-  test("User gets error message when submitting wrong credentials", async ({ page }) => {
+  test("User gets error message when submitting wrong credentials", async ({
+    page,
+  }) => {
     const loginPage = new LoginPage(page);
     await loginPage.setupLoginError();
 
-    await loginPage.fillEmailAndPasswordInputs("test@example.com", "loremipsum");
+    await loginPage.fillEmailAndPasswordInputs(
+      "test@example.com",
+      "loremipsum",
+    );
     await loginPage.clickLoginButton();
 
     await expect(loginPage.invalidCredentialsError).toBeVisible();
diff --git a/frontend/playwright/ui/specs/onboarding.spec.js b/frontend/playwright/ui/specs/onboarding.spec.js
index 68e00fc50..968c88825 100644
--- a/frontend/playwright/ui/specs/onboarding.spec.js
+++ b/frontend/playwright/ui/specs/onboarding.spec.js
@@ -1,31 +1,44 @@
 import { test, expect } from "@playwright/test";
 import DashboardPage from "../pages/DashboardPage";
- import OnboardingPage from "../pages/OnboardingPage"
+import OnboardingPage from "../pages/OnboardingPage";
 
 test.beforeEach(async ({ page }) => {
   await DashboardPage.init(page);
-  await DashboardPage.mockRPC(page, "get-profile", "logged-in-user/get-profile-logged-in.json");
+  await DashboardPage.mockRPC(
+    page,
+    "get-profile",
+    "logged-in-user/get-profile-logged-in.json",
+  );
 });
 
-
 test("User can complete the onboarding", async ({ page }) => {
   const dashboardPage = new DashboardPage(page);
   const onboardingPage = new OnboardingPage(page);
 
   await dashboardPage.goToDashboard();
-  await expect(page.getByRole("heading", { name: "Help us get to know you" })).toBeVisible();
+  await expect(
+    page.getByRole("heading", { name: "Help us get to know you" }),
+  ).toBeVisible();
 
   await onboardingPage.fillOnboardingInputsStep1();
-  await expect(page.getByRole("heading", { name: "Which one of these tools do" })).toBeVisible();
+  await expect(
+    page.getByRole("heading", { name: "Which one of these tools do" }),
+  ).toBeVisible();
 
   await onboardingPage.fillOnboardingInputsStep2();
-  await expect(page.getByRole("heading", { name: "Tell us about your job" })).toBeVisible();
+  await expect(
+    page.getByRole("heading", { name: "Tell us about your job" }),
+  ).toBeVisible();
 
   await onboardingPage.fillOnboardingInputsStep3();
-  await expect(page.getByRole("heading", { name: "Where would you like to get" })).toBeVisible();
+  await expect(
+    page.getByRole("heading", { name: "Where would you like to get" }),
+  ).toBeVisible();
 
   await onboardingPage.fillOnboardingInputsStep4();
-  await expect(page.getByRole("heading", { name: "How did you hear about Penpot?" })).toBeVisible();
+  await expect(
+    page.getByRole("heading", { name: "How did you hear about Penpot?" }),
+  ).toBeVisible();
 
   await onboardingPage.fillOnboardingInputsStep5();
   await expect(page.getByRole("button", { name: "Start" })).toBeEnabled();
diff --git a/frontend/playwright/ui/specs/sidebar.spec.js b/frontend/playwright/ui/specs/sidebar.spec.js
index bb0a4d451..b97301889 100644
--- a/frontend/playwright/ui/specs/sidebar.spec.js
+++ b/frontend/playwright/ui/specs/sidebar.spec.js
@@ -6,7 +6,9 @@ test.beforeEach(async ({ page }) => {
 });
 
 test.describe("Layers tab", () => {
-  test("BUG 7466 - Layers tab height extends to the bottom when 'Pages' is collapsed", async ({ page }) => {
+  test("BUG 7466 - Layers tab height extends to the bottom when 'Pages' is collapsed", async ({
+    page,
+  }) => {
     const workspace = new WorkspacePage(page);
     await workspace.setupEmptyFile();
 
@@ -21,11 +23,19 @@ test.describe("Layers tab", () => {
 });
 
 test.describe("Assets tab", () => {
-  test("User adds a library and its automatically selected in the color palette", async ({ page }) => {
+  test("User adds a library and its automatically selected in the color palette", async ({
+    page,
+  }) => {
     const workspacePage = new WorkspacePage(page);
     await workspacePage.setupEmptyFile();
-    await workspacePage.mockRPC("link-file-to-library", "workspace/link-file-to-library.json");
-    await workspacePage.mockRPC("unlink-file-from-library", "workspace/unlink-file-from-library.json");
+    await workspacePage.mockRPC(
+      "link-file-to-library",
+      "workspace/link-file-to-library.json",
+    );
+    await workspacePage.mockRPC(
+      "unlink-file-from-library",
+      "workspace/unlink-file-from-library.json",
+    );
     await workspacePage.mockRPC(
       "get-team-shared-files?team-id=*",
       "workspace/get-team-shared-libraries-non-empty.json",
@@ -37,12 +47,17 @@ test.describe("Assets tab", () => {
     await workspacePage.clickColorPalette();
     await workspacePage.clickAssets();
     // Now the get-file call should return a library
-    await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-library.json");
+    await workspacePage.mockRPC(
+      /get\-file\?/,
+      "workspace/get-file-library.json",
+    );
     await workspacePage.openLibrariesModal();
     await workspacePage.clickLibrary("Testing library 1");
     await workspacePage.closeLibrariesModal();
 
-    await expect(workspacePage.palette.getByRole("button", { name: "test-color-187cd5" })).toBeVisible();
+    await expect(
+      workspacePage.palette.getByRole("button", { name: "test-color-187cd5" }),
+    ).toBeVisible();
 
     // Remove Testing library 1
     await workspacePage.openLibrariesModal();
@@ -50,7 +65,9 @@ test.describe("Assets tab", () => {
     await workspacePage.closeLibrariesModal();
 
     await expect(
-      workspacePage.palette.getByText("There are no color styles in your library yet"),
+      workspacePage.palette.getByText(
+        "There are no color styles in your library yet",
+      ),
     ).toBeVisible();
   });
 });
diff --git a/frontend/playwright/ui/specs/viewer-comments.spec.js b/frontend/playwright/ui/specs/viewer-comments.spec.js
index 7d7b637ea..4ed32135a 100644
--- a/frontend/playwright/ui/specs/viewer-comments.spec.js
+++ b/frontend/playwright/ui/specs/viewer-comments.spec.js
@@ -8,17 +8,23 @@ test.beforeEach(async ({ page }) => {
 const singleBoardFileId = "dd5cc0bb-91ff-81b9-8004-77df9cd3edb1";
 const singleBoardPageId = "dd5cc0bb-91ff-81b9-8004-77df9cd3edb2";
 
-
 test("Comment is shown with scroll and valid position", async ({ page }) => {
   const viewer = new ViewerPage(page);
   await viewer.setupLoggedInUser();
   await viewer.setupFileWithComments();
 
-  await viewer.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewer.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
   await viewer.showComments();
   await viewer.showCommentsThread(1);
-  await expect(viewer.page.getByRole("textbox", { name: "Reply" })).toBeVisible();
+  await expect(
+    viewer.page.getByRole("textbox", { name: "Reply" }),
+  ).toBeVisible();
   await viewer.showCommentsThread(1);
   await viewer.showCommentsThread(2);
-  await expect(viewer.page.getByRole("textbox", { name: "Reply" })).toBeVisible();
+  await expect(
+    viewer.page.getByRole("textbox", { name: "Reply" }),
+  ).toBeVisible();
 });
diff --git a/frontend/playwright/ui/specs/viewer-header.spec.js b/frontend/playwright/ui/specs/viewer-header.spec.js
index 81c01ee05..805d31c66 100644
--- a/frontend/playwright/ui/specs/viewer-header.spec.js
+++ b/frontend/playwright/ui/specs/viewer-header.spec.js
@@ -30,7 +30,10 @@ test("Updates URL with zoom type", async ({ page }) => {
   await viewer.setupLoggedInUser();
   await viewer.setupFileWithSingleBoard(viewer);
 
-  await viewer.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewer.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await viewer.page.getByTitle("Zoom").click();
   await viewer.page.getByText(/Fit/).click();
diff --git a/frontend/playwright/ui/specs/workspace.spec.js b/frontend/playwright/ui/specs/workspace.spec.js
index f069ed246..066486f50 100644
--- a/frontend/playwright/ui/specs/workspace.spec.js
+++ b/frontend/playwright/ui/specs/workspace.spec.js
@@ -15,20 +15,27 @@ test("User loads worskpace with empty file", async ({ page }) => {
   await expect(workspacePage.pageName).toHaveText("Page 1");
 });
 
-test("User receives presence notifications updates in the workspace", async ({ page }) => {
+test("User receives presence notifications updates in the workspace", async ({
+  page,
+}) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
 
   await workspacePage.goToWorkspace();
   await workspacePage.sendPresenceMessage(presenceFixture);
 
-  await expect(page.getByTestId("active-users-list").getByAltText("Princesa Leia")).toHaveCount(2);
+  await expect(
+    page.getByTestId("active-users-list").getByAltText("Princesa Leia"),
+  ).toHaveCount(2);
 });
 
 test("User draws a rect", async ({ page }) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
-  await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-create-rect.json");
+  await workspacePage.mockRPC(
+    "update-file?id=*",
+    "workspace/update-file-create-rect.json",
+  );
 
   await workspacePage.goToWorkspace();
   await workspacePage.rectShapeButton.click();
@@ -42,8 +49,14 @@ test("User draws a rect", async ({ page }) => {
 test("User makes a group", async ({ page }) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
-  await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-not-empty.json");
-  await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-create-rect.json");
+  await workspacePage.mockRPC(
+    /get\-file\?/,
+    "workspace/get-file-not-empty.json",
+  );
+  await workspacePage.mockRPC(
+    "update-file?id=*",
+    "workspace/update-file-create-rect.json",
+  );
 
   await workspacePage.goToWorkspace({
     fileId: "6191cd35-bb1f-81f7-8004-7cc63d087374",
@@ -54,7 +67,9 @@ test("User makes a group", async ({ page }) => {
   await workspacePage.expectSelectedLayer("Group");
 });
 
-test("Bug 7654 - Toolbar keeps toggling on and off on spacebar press", async ({ page }) => {
+test("Bug 7654 - Toolbar keeps toggling on and off on spacebar press", async ({
+  page,
+}) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
   await workspacePage.goToWorkspace();
@@ -65,11 +80,19 @@ test("Bug 7654 - Toolbar keeps toggling on and off on spacebar press", async ({
   await workspacePage.expectHiddenToolbarOptions();
 });
 
-test("Bug 7525 - User moves a scrollbar and no selciont rectangle appears", async ({ page }) => {
+test("Bug 7525 - User moves a scrollbar and no selciont rectangle appears", async ({
+  page,
+}) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
-  await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-not-empty.json");
-  await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-create-rect.json");
+  await workspacePage.mockRPC(
+    /get\-file\?/,
+    "workspace/get-file-not-empty.json",
+  );
+  await workspacePage.mockRPC(
+    "update-file?id=*",
+    "workspace/update-file-create-rect.json",
+  );
 
   await workspacePage.goToWorkspace({
     fileId: "6191cd35-bb1f-81f7-8004-7cc63d087374",
@@ -84,7 +107,7 @@ test("Bug 7525 - User moves a scrollbar and no selciont rectangle appears", asyn
   await expect(horizontalScrollbar).toBeVisible();
 
   // Grab scrollbar and move
-  const {x, y} = await horizontalScrollbar.boundingBox();
+  const { x, y } = await horizontalScrollbar.boundingBox();
   await page.waitForTimeout(100);
   await workspacePage.viewport.hover({ position: { x: x, y: y + 5 } });
   await page.mouse.down();
@@ -93,13 +116,24 @@ test("Bug 7525 - User moves a scrollbar and no selciont rectangle appears", asyn
   await expect(workspacePage.selectionRect).not.toBeInViewport();
 });
 
-test("User adds a library and its automatically selected in the color palette", async ({ page }) => {
+test("User adds a library and its automatically selected in the color palette", async ({
+  page,
+}) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
-  await workspacePage.mockRPC("link-file-to-library", "workspace/link-file-to-library.json");
-  await workspacePage.mockRPC("unlink-file-from-library", "workspace/unlink-file-from-library.json");
-  await workspacePage.mockRPC("get-team-shared-files?team-id=*", "workspace/get-team-shared-libraries-non-empty.json");
-  
+  await workspacePage.mockRPC(
+    "link-file-to-library",
+    "workspace/link-file-to-library.json",
+  );
+  await workspacePage.mockRPC(
+    "unlink-file-from-library",
+    "workspace/unlink-file-from-library.json",
+  );
+  await workspacePage.mockRPC(
+    "get-team-shared-files?team-id=*",
+    "workspace/get-team-shared-libraries-non-empty.json",
+  );
+
   await workspacePage.goToWorkspace();
 
   // Add Testing library 1
@@ -108,20 +142,28 @@ test("User adds a library and its automatically selected in the color palette",
   // Now the get-file call should return a library
   await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-library.json");
   await workspacePage.openLibrariesModal();
-  await workspacePage.clickLibrary("Testing library 1")
-  await workspacePage.closeLibrariesModal(); 
+  await workspacePage.clickLibrary("Testing library 1");
+  await workspacePage.closeLibrariesModal();
 
-  await expect(workspacePage.palette.getByRole("button", { name: "test-color-187cd5" })).toBeVisible();
+  await expect(
+    workspacePage.palette.getByRole("button", { name: "test-color-187cd5" }),
+  ).toBeVisible();
 
   // Remove Testing library 1
   await workspacePage.openLibrariesModal();
-  await workspacePage.clickLibrary("Testing library 1")
+  await workspacePage.clickLibrary("Testing library 1");
   await workspacePage.closeLibrariesModal();
 
-  await expect(workspacePage.palette.getByText('There are no color styles in your library yet')).toBeVisible();
+  await expect(
+    workspacePage.palette.getByText(
+      "There are no color styles in your library yet",
+    ),
+  ).toBeVisible();
 });
 
-test("Bug 7489 - Workspace-palette items stay hidden when opening with keyboard-shortcut", async ({ page }) => {
+test("Bug 7489 - Workspace-palette items stay hidden when opening with keyboard-shortcut", async ({
+  page,
+}) => {
   const workspacePage = new WorkspacePage(page);
   await workspacePage.setupEmptyFile();
   await workspacePage.goToWorkspace();
@@ -129,5 +171,9 @@ test("Bug 7489 - Workspace-palette items stay hidden when opening with keyboard-
   await workspacePage.clickTogglePalettesVisibility();
   await workspacePage.page.keyboard.press("Alt+t");
 
-  await expect(workspacePage.palette.getByText("There are no typography styles in your library yet")).toBeVisible();
+  await expect(
+    workspacePage.palette.getByText(
+      "There are no typography styles in your library yet",
+    ),
+  ).toBeVisible();
 });
diff --git a/frontend/playwright/ui/visual-specs/visual-dashboard.spec.js b/frontend/playwright/ui/visual-specs/visual-dashboard.spec.js
index d0dfa9677..44bfb9abb 100644
--- a/frontend/playwright/ui/visual-specs/visual-dashboard.spec.js
+++ b/frontend/playwright/ui/visual-specs/visual-dashboard.spec.js
@@ -3,7 +3,11 @@ import DashboardPage from "../pages/DashboardPage";
 
 test.beforeEach(async ({ page }) => {
   await DashboardPage.init(page);
-  await DashboardPage.mockRPC(page, "get-profile", "logged-in-user/get-profile-logged-in-no-onboarding.json");
+  await DashboardPage.mockRPC(
+    page,
+    "get-profile",
+    "logged-in-user/get-profile-logged-in-no-onboarding.json",
+  );
 });
 
 test("User goes to an empty dashboard", async ({ page }) => {
@@ -123,7 +127,9 @@ test("User goes to a full search page", async ({ page }) => {
   await dashboardPage.searchInput.fill("3");
 
   await expect(dashboardPage.mainHeading).toHaveText("Search results");
-  await expect(dashboardPage.page.getByRole("button", { name: "New File 3" })).toBeVisible();
+  await expect(
+    dashboardPage.page.getByRole("button", { name: "New File 3" }),
+  ).toBeVisible();
   await expect(dashboardPage.page).toHaveScreenshot();
 });
 
@@ -157,7 +163,9 @@ test("User goes to password management section", async ({ page }) => {
 
   await page.getByText("Password").click();
 
-  await expect(page.getByRole("heading", { name: "Change Password" })).toBeVisible();
+  await expect(
+    page.getByRole("heading", { name: "Change Password" }),
+  ).toBeVisible();
   await expect(dashboardPage.page).toHaveScreenshot();
 });
 
diff --git a/frontend/playwright/ui/visual-specs/visual-viewer.spec.js b/frontend/playwright/ui/visual-specs/visual-viewer.spec.js
index 48afc1a60..a3eeddc82 100644
--- a/frontend/playwright/ui/visual-specs/visual-viewer.spec.js
+++ b/frontend/playwright/ui/visual-specs/visual-viewer.spec.js
@@ -3,7 +3,6 @@ import { ViewerPage } from "../pages/ViewerPage";
 
 test.beforeEach(async ({ page }) => {
   await ViewerPage.init(page);
-
 });
 
 const singleBoardFileId = "dd5cc0bb-91ff-81b9-8004-77df9cd3edb1";
@@ -25,7 +24,10 @@ test("User goes to the Viewer", async ({ page }) => {
   await viewerPage.setupLoggedInUser();
   await viewerPage.setupFileWithSingleBoard();
 
-  await viewerPage.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewerPage.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await expect(viewerPage.page.getByTestId("penpot-logo-link")).toBeVisible();
   await expect(viewerPage.page).toHaveScreenshot();
@@ -36,7 +38,10 @@ test("User goes to the Viewer and opens zoom modal", async ({ page }) => {
   await viewerPage.setupLoggedInUser();
   await viewerPage.setupFileWithSingleBoard();
 
-  await viewerPage.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewerPage.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await viewerPage.page.getByTitle("Zoom").click();
 
@@ -49,11 +54,16 @@ test("User goes to the Viewer Comments", async ({ page }) => {
   await viewerPage.setupLoggedInUser();
   await viewerPage.setupFileWithComments();
 
-  await viewerPage.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewerPage.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await viewerPage.showComments();
   await viewerPage.showCommentsThread(1);
-  await expect(viewerPage.page.getByRole("textbox", { name: "Reply" })).toBeVisible();
+  await expect(
+    viewerPage.page.getByRole("textbox", { name: "Reply" }),
+  ).toBeVisible();
 
   await expect(viewerPage.page).toHaveScreenshot();
 });
@@ -63,14 +73,19 @@ test("User opens Viewer comment list", async ({ page }) => {
   await viewerPage.setupLoggedInUser();
   await viewerPage.setupFileWithComments();
 
-  await viewerPage.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewerPage.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await viewerPage.showComments();
   await viewerPage.page.getByTestId("viewer-comments-dropdown").click();
 
   await viewerPage.page.getByText("Show comments list").click();
 
-  await expect(viewerPage.page.getByRole("button", { name: "Show all comments" })).toBeVisible();
+  await expect(
+    viewerPage.page.getByRole("button", { name: "Show all comments" }),
+  ).toBeVisible();
   await expect(viewerPage.page).toHaveScreenshot();
 });
 
@@ -79,7 +94,10 @@ test("User goes to the Viewer Inspect code", async ({ page }) => {
   await viewerPage.setupLoggedInUser();
   await viewerPage.setupFileWithComments();
 
-  await viewerPage.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewerPage.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await viewerPage.showCode();
 
@@ -93,12 +111,17 @@ test("User goes to the Viewer Inspect code, code tab", async ({ page }) => {
   await viewerPage.setupLoggedInUser();
   await viewerPage.setupFileWithComments();
 
-  await viewerPage.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewerPage.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await viewerPage.showCode();
   await viewerPage.page.getByTestId("code").click();
 
-  await expect(viewerPage.page.getByRole("button", { name: "Copy all code" })).toBeVisible();
+  await expect(
+    viewerPage.page.getByRole("button", { name: "Copy all code" }),
+  ).toBeVisible();
 
   await expect(viewerPage.page).toHaveScreenshot();
 });
@@ -108,10 +131,15 @@ test("User opens Share modal", async ({ page }) => {
   await viewerPage.setupLoggedInUser();
   await viewerPage.setupFileWithSingleBoard();
 
-  await viewerPage.goToViewer({ fileId: singleBoardFileId, pageId: singleBoardPageId });
+  await viewerPage.goToViewer({
+    fileId: singleBoardFileId,
+    pageId: singleBoardPageId,
+  });
 
   await viewerPage.page.getByRole("button", { name: "Share" }).click();
 
-  await expect(viewerPage.page.getByRole("button", { name: "Get link" })).toBeVisible();
+  await expect(
+    viewerPage.page.getByRole("button", { name: "Get link" }),
+  ).toBeVisible();
   await expect(viewerPage.page).toHaveScreenshot();
 });
diff --git a/frontend/playwright/ui/visual-specs/workspace.spec.js b/frontend/playwright/ui/visual-specs/workspace.spec.js
index b21f13996..69cc5a34d 100644
--- a/frontend/playwright/ui/visual-specs/workspace.spec.js
+++ b/frontend/playwright/ui/visual-specs/workspace.spec.js
@@ -9,15 +9,20 @@ const setupFileWithAssets = async (workspace) => {
   const fileId = "015fda4f-caa6-8103-8004-862a00dd4f31";
   const pageId = "015fda4f-caa6-8103-8004-862a00ddbe94";
   const fragments = {
-    "015fda4f-caa6-8103-8004-862a9e4b4d4b": "assets/get-file-fragment-with-assets-components.json",
-    "015fda4f-caa6-8103-8004-862a9e4ad279": "assets/get-file-fragmnet-with-assets-page.json",
+    "015fda4f-caa6-8103-8004-862a9e4b4d4b":
+      "assets/get-file-fragment-with-assets-components.json",
+    "015fda4f-caa6-8103-8004-862a9e4ad279":
+      "assets/get-file-fragmnet-with-assets-page.json",
   };
 
   await workspace.setupEmptyFile();
   await workspace.mockRPC(/get\-file\?/, "assets/get-file-with-assets.json");
 
   for (const [id, fixture] of Object.entries(fragments)) {
-    await workspace.mockRPC(`get-file-fragment?file-id=*&fragment-id=${id}`, fixture);
+    await workspace.mockRPC(
+      `get-file-fragment?file-id=*&fragment-id=${id}`,
+      fixture,
+    );
   }
 
   return { fileId, pageId };
@@ -69,7 +74,10 @@ test.describe("Assets tab", () => {
   test("Shows the libraries modal correctly", async ({ page }) => {
     const workspace = new WorkspacePage(page);
     await workspace.setupEmptyFile();
-    await workspace.mockRPC("link-file-to-library", "workspace/link-file-to-library.json");
+    await workspace.mockRPC(
+      "link-file-to-library",
+      "workspace/link-file-to-library.json",
+    );
     await workspace.mockRPC(
       "get-team-shared-files?team-id=*",
       "workspace/get-team-shared-libraries-non-empty.json",
@@ -95,7 +103,9 @@ test.describe("Assets tab", () => {
     await workspace.clickAssets();
     await workspace.sidebar.getByRole("button", { name: "Components" }).click();
     await workspace.sidebar.getByRole("button", { name: "Colors" }).click();
-    await workspace.sidebar.getByRole("button", { name: "Typographies" }).click();
+    await workspace.sidebar
+      .getByRole("button", { name: "Typographies" })
+      .click();
 
     await expect(workspace.page).toHaveScreenshot();
 
@@ -114,11 +124,19 @@ test.describe("Palette", () => {
 
     await expect(workspace.page).toHaveScreenshot();
 
-    await workspace.palette.getByRole("button", { name: "Typographies" }).click();
-    await expect(workspace.palette.getByText("Source Sans Pro Regular")).toBeVisible();
+    await workspace.palette
+      .getByRole("button", { name: "Typographies" })
+      .click();
+    await expect(
+      workspace.palette.getByText("Source Sans Pro Regular"),
+    ).toBeVisible();
     await expect(workspace.page).toHaveScreenshot();
 
-    await workspace.palette.getByRole("button", { name: "Color Palette" }).click();
-    await expect(workspace.palette.getByRole("button", { name: "#7798ff" })).toBeVisible();
+    await workspace.palette
+      .getByRole("button", { name: "Color Palette" })
+      .click();
+    await expect(
+      workspace.palette.getByRole("button", { name: "#7798ff" }),
+    ).toBeVisible();
   });
 });
diff --git a/frontend/scripts/_helpers.js b/frontend/scripts/_helpers.js
index 0e284111d..1dc4fb963 100644
--- a/frontend/scripts/_helpers.js
+++ b/frontend/scripts/_helpers.js
@@ -34,7 +34,9 @@ async function findFiles(basePath, predicate, options = {}) {
       return true;
     };
 
-  let files = await fs.readdir(basePath, { recursive: options.recursive ?? false });
+  let files = await fs.readdir(basePath, {
+    recursive: options.recursive ?? false,
+  });
   files = files.map((path) => ph.join(basePath, path));
 
   return files;
@@ -232,7 +234,9 @@ async function readTranslations() {
       lang = lang[0];
     }
 
-    const content = await fs.readFile(`./translations/${filename}`, { encoding: "utf-8" });
+    const content = await fs.readFile(`./translations/${filename}`, {
+      encoding: "utf-8",
+    });
 
     lang = lang.toLowerCase();
 
@@ -291,15 +295,23 @@ async function generateSvgSprite(files, prefix) {
 }
 
 async function generateSvgSprites() {
-  await fs.mkdir("resources/public/images/sprites/symbol/", { recursive: true });
+  await fs.mkdir("resources/public/images/sprites/symbol/", {
+    recursive: true,
+  });
 
   const icons = await findFiles("resources/images/icons/", isSvgFile);
   const iconsSprite = await generateSvgSprite(icons, "icon-");
-  await fs.writeFile("resources/public/images/sprites/symbol/icons.svg", iconsSprite);
+  await fs.writeFile(
+    "resources/public/images/sprites/symbol/icons.svg",
+    iconsSprite,
+  );
 
   const cursors = await findFiles("resources/images/cursors/", isSvgFile);
   const cursorsSprite = await generateSvgSprite(icons, "cursor-");
-  await fs.writeFile("resources/public/images/sprites/symbol/cursors.svg", cursorsSprite);
+  await fs.writeFile(
+    "resources/public/images/sprites/symbol/cursors.svg",
+    cursorsSprite,
+  );
 }
 
 async function generateTemplates() {
@@ -310,15 +322,23 @@ async function generateTemplates() {
   const manifest = await readShadowManifest();
   let content;
 
-  const iconsSprite = await fs.readFile("resources/public/images/sprites/symbol/icons.svg", "utf8");
-  const cursorsSprite = await fs.readFile("resources/public/images/sprites/symbol/cursors.svg", "utf8");
+  const iconsSprite = await fs.readFile(
+    "resources/public/images/sprites/symbol/icons.svg",
+    "utf8",
+  );
+  const cursorsSprite = await fs.readFile(
+    "resources/public/images/sprites/symbol/cursors.svg",
+    "utf8",
+  );
   const partials = {
     "../public/images/sprites/symbol/icons.svg": iconsSprite,
     "../public/images/sprites/symbol/cursors.svg": cursorsSprite,
   };
 
   const pluginRuntimeUri =
-    process.env.PENPOT_PLUGIN_DEV === "true" ? "http://localhost:4200" : "./plugins-runtime";
+    process.env.PENPOT_PLUGIN_DEV === "true"
+      ? "http://localhost:4200"
+      : "./plugins-runtime";
 
   content = await renderTemplate(
     "resources/templates/index.mustache",
@@ -411,7 +431,10 @@ export async function copyAssets() {
 
   await syncDirs("resources/images/", "resources/public/images/");
   await syncDirs("resources/fonts/", "resources/public/fonts/");
-  await syncDirs("resources/plugins-runtime/", "resources/public/plugins-runtime/");
+  await syncDirs(
+    "resources/plugins-runtime/",
+    "resources/public/plugins-runtime/",
+  );
 
   const end = process.hrtime(start);
   log.info("done: copy assets", `(${ppt(end)})`);
diff --git a/frontend/scripts/_worker.js b/frontend/scripts/_worker.js
index eab272fbf..47e333664 100644
--- a/frontend/scripts/_worker.js
+++ b/frontend/scripts/_worker.js
@@ -17,18 +17,21 @@ async function compileFile(path) {
   const name = ph.basename(path, ".scss");
   const dest = `${dir}${ph.sep}${name}.css`;
 
-
   return new Promise(async (resolve, reject) => {
     try {
       const result = await compiler.compileAsync(path, {
-        loadPaths: ["node_modules/animate.css", "resources/styles/common/", "resources/styles"],
-        sourceMap: false
+        loadPaths: [
+          "node_modules/animate.css",
+          "resources/styles/common/",
+          "resources/styles",
+        ],
+        sourceMap: false,
       });
       // console.dir(result);
       resolve({
         inputPath: path,
         outputPath: dest,
-        css: result.css
+        css: result.css,
       });
     } catch (cause) {
       // console.error(cause);
@@ -56,7 +59,7 @@ function configureModulesProcessor(options) {
   });
 }
 
-function configureProcessor(options={}) {
+function configureProcessor(options = {}) {
   const processors = [];
 
   if (options.modules) {
@@ -78,7 +81,7 @@ async function postProcessFile(data, options) {
   });
 
   return Object.assign(data, {
-    css: result.css
+    css: result.css,
   });
 }
 
@@ -87,11 +90,14 @@ async function compile(path, options) {
   return await postProcessFile(result, options);
 }
 
-wpool.worker({
-  compileSass: compile
-}, {
-  onTerminate: async (code) => {
-    // log.info("worker: terminate");
-    await compiler.dispose();
-  }
-});
+wpool.worker(
+  {
+    compileSass: compile,
+  },
+  {
+    onTerminate: async (code) => {
+      // log.info("worker: terminate");
+      await compiler.dispose();
+    },
+  },
+);
diff --git a/frontend/scripts/compile.js b/frontend/scripts/compile.js
index e04d07001..8ee6dc977 100644
--- a/frontend/scripts/compile.js
+++ b/frontend/scripts/compile.js
@@ -4,7 +4,7 @@ import log from "fancy-log";
 import * as h from "./_helpers.js";
 
 await h.compileStyles();
-await h.copyAssets()
-await h.compileSvgSprites()
+await h.copyAssets();
+await h.compileSvgSprites();
 await h.compileTemplates();
 await h.compilePolyfills();
diff --git a/frontend/scripts/e2e-server.js b/frontend/scripts/e2e-server.js
index c05743813..77be5fcca 100644
--- a/frontend/scripts/e2e-server.js
+++ b/frontend/scripts/e2e-server.js
@@ -9,7 +9,10 @@ const port = 3000;
 
 app.use(compression());
 
-const staticPath = path.join(fileURLToPath(import.meta.url), "../../resources/public");
+const staticPath = path.join(
+  fileURLToPath(import.meta.url),
+  "../../resources/public",
+);
 app.use(express.static(staticPath));
 
 app.listen(port, () => {
diff --git a/frontend/scripts/find-unused-translations.js b/frontend/scripts/find-unused-translations.js
index 3369e4dce..6a02198a4 100644
--- a/frontend/scripts/find-unused-translations.js
+++ b/frontend/scripts/find-unused-translations.js
@@ -1,26 +1,25 @@
-const fs = require('fs').promises;
+const fs = require("fs").promises;
 const gt = require("gettext-parser");
-const path = require('path');
-const util = require('node:util');
-const execFile = util.promisify(require('node:child_process').execFile);
+const path = require("path");
+const util = require("node:util");
+const execFile = util.promisify(require("node:child_process").execFile);
 
-
-async function processMsgId(msgId){
-  return execFile('grep', ['-r', '-o', msgId, './src'])
-  .catch(()=> { return msgId})
+async function processMsgId(msgId) {
+  return execFile("grep", ["-r", "-o", msgId, "./src"]).catch(() => {
+    return msgId;
+  });
 }
 
-
 async function processFile(f) {
   const content = await fs.readFile(f);
-  const data = gt.po.parse(content, "utf-8")
-  const translations = data.translations[''];
+  const data = gt.po.parse(content, "utf-8");
+  const translations = data.translations[""];
   const badIds = [];
 
   for (const property in translations) {
     const data = await processMsgId(translations[property].msgid);
-    if (data!=null && data.stdout === undefined){
-      badIds.push(data)
+    if (data != null && data.stdout === undefined) {
+      badIds.push(data);
     }
   }
 
@@ -28,63 +27,77 @@ async function processFile(f) {
 }
 
 async function cleanFile(f, badIds) {
-  console.log ("\n\nDoing automatic cleanup")
+  console.log("\n\nDoing automatic cleanup");
 
   const content = await fs.readFile(f);
   const data = gt.po.parse(content, "utf-8");
-  const translations = data.translations[''];
+  const translations = data.translations[""];
   const keys = Object.keys(translations);
 
   for (const key of keys) {
     property = translations[key];
-    if (badIds.includes(property.msgid)){
-      console.log ('----> deleting', property.msgid)
-      delete data.translations[''][key];
+    if (badIds.includes(property.msgid)) {
+      console.log("----> deleting", property.msgid);
+      delete data.translations[""][key];
     }
   }
 
-  const buff = gt.po.compile(data, {sort: true});
+  const buff = gt.po.compile(data, { sort: true });
   await fs.writeFile(f, buff);
 }
 
-
-
 async function findExecutionTimeTranslations() {
-  const { stdout } = await execFile('grep', ['-r', '-h', '-F', '(tr (', './src']);
+  const { stdout } = await execFile("grep", [
+    "-r",
+    "-h",
+    "-F",
+    "(tr (",
+    "./src",
+  ]);
   console.log(stdout);
 }
 
 async function welcome() {
-  console.log ('####################################################################')
-  console.log ('#                UNUSED TRANSLATIONS FINDER                        #')
-  console.log ('####################################################################')
-  console.log ('\n');
-  console.log ('DISCLAIMER: Some translations are only available at execution time.')
-  console.log ('            This finder can\'t process them, so there can be')
-  console.log ('            false positives.\n')
-  console.log ('            If you want to do an automatic clean anyway,')
-  console.log ('            call the script with:')
-  console.log ('            npm run find-unused-translations -- --clean')
-  console.log ('            For example:');
-  console.log ('--------------------------------------------------------------------');
+  console.log(
+    "####################################################################",
+  );
+  console.log(
+    "#                UNUSED TRANSLATIONS FINDER                        #",
+  );
+  console.log(
+    "####################################################################",
+  );
+  console.log("\n");
+  console.log(
+    "DISCLAIMER: Some translations are only available at execution time.",
+  );
+  console.log("            This finder can't process them, so there can be");
+  console.log("            false positives.\n");
+  console.log("            If you want to do an automatic clean anyway,");
+  console.log("            call the script with:");
+  console.log("            npm run find-unused-translations -- --clean");
+  console.log("            For example:");
+  console.log(
+    "--------------------------------------------------------------------",
+  );
   await findExecutionTimeTranslations();
-  console.log ('--------------------------------------------------------------------');
+  console.log(
+    "--------------------------------------------------------------------",
+  );
 }
 
-
 const doCleanup = process.argv.slice(2)[0] == "--clean";
 
-
-;(async () => {
+(async () => {
   await welcome();
   const target = path.normalize("./translations/en.po");
   const badIds = await processFile(target);
 
-  if (doCleanup){
+  if (doCleanup) {
     cleanFile(target, badIds);
   } else {
-    for (const badId of badIds){
+    for (const badId of badIds) {
       console.log(badId);
     }
   }
-})()
+})();
diff --git a/frontend/scripts/validate-translations.js b/frontend/scripts/validate-translations.js
index f6ec245ca..0fe05e2c9 100644
--- a/frontend/scripts/validate-translations.js
+++ b/frontend/scripts/validate-translations.js
@@ -1,7 +1,7 @@
-import {promises as fs} from 'fs';
-import gt from 'gettext-parser';
-import l from 'lodash';
-import path from 'path';
+import { promises as fs } from "fs";
+import gt from "gettext-parser";
+import l from "lodash";
+import path from "path";
 
 async function* getFiles(dir) {
   const dirents = await fs.readdir(dir, { withFileTypes: true });
@@ -15,7 +15,7 @@ async function* getFiles(dir) {
   }
 }
 
-;(async () => {
+(async () => {
   const fileRe = /.+\.po$/;
   const target = path.normalize("./translations/");
   const parent = path.join(target, "..");
@@ -24,8 +24,8 @@ async function* getFiles(dir) {
     const entry = path.relative(parent, f);
     console.log(`=> processing: ${entry}`);
     const content = await fs.readFile(f);
-    const data = gt.po.parse(content, "utf-8")
-    const buff = gt.po.compile(data, {sort: true});
+    const data = gt.po.parse(content, "utf-8");
+    const buff = gt.po.compile(data, { sort: true });
     await fs.writeFile(f, buff);
   }
-})()
+})();
diff --git a/frontend/scripts/watch.js b/frontend/scripts/watch.js
index f2c6b376c..99ced7b70 100644
--- a/frontend/scripts/watch.js
+++ b/frontend/scripts/watch.js
@@ -11,7 +11,7 @@ let sass = null;
 
 async function compileSassAll() {
   const start = process.hrtime();
-  log.info("init: compile styles")
+  log.info("init: compile styles");
 
   sass = await h.compileSassAll(worker);
   let output = await h.concatSass(sass);
@@ -24,7 +24,7 @@ async function compileSassAll() {
 async function compileSass(path) {
   const start = process.hrtime();
   log.info("changed:", path);
-  const result = await h.compileSass(worker, path, {modules:true});
+  const result = await h.compileSass(worker, path, { modules: true });
   sass.index[result.outputPath] = result.css;
 
   const output = h.concatSass(sass);
@@ -37,12 +37,12 @@ async function compileSass(path) {
 
 await fs.mkdir("./resources/public/css/", { recursive: true });
 await compileSassAll();
-await h.copyAssets()
-await h.compileSvgSprites()
+await h.copyAssets();
+await h.compileSvgSprites();
 await h.compileTemplates();
 await h.compilePolyfills();
 
-log.info("watch: scss src (~)")
+log.info("watch: scss src (~)");
 
 h.watch("src", h.isSassFile, async function (path) {
   if (path.includes("common")) {
@@ -52,30 +52,34 @@ h.watch("src", h.isSassFile, async function (path) {
   }
 });
 
-log.info("watch: scss: resources (~)")
+log.info("watch: scss: resources (~)");
 h.watch("resources/styles", h.isSassFile, async function (path) {
   log.info("changed:", path);
-  await compileSassAll()
+  await compileSassAll();
 });
 
-log.info("watch: templates (~)")
+log.info("watch: templates (~)");
 h.watch("resources/templates", null, async function (path) {
   log.info("changed:", path);
   await h.compileTemplates();
 });
 
-log.info("watch: translations (~)")
+log.info("watch: translations (~)");
 h.watch("translations", null, async function (path) {
   log.info("changed:", path);
   await h.compileTemplates();
 });
 
-log.info("watch: assets (~)")
-h.watch(["resources/images", "resources/fonts", "resources/plugins-runtime"], null, async function (path) {
-  log.info("changed:", path);
-  await h.compileSvgSprites();
-  await h.copyAssets();
-  await h.compileTemplates();
-});
+log.info("watch: assets (~)");
+h.watch(
+  ["resources/images", "resources/fonts", "resources/plugins-runtime"],
+  null,
+  async function (path) {
+    log.info("changed:", path);
+    await h.compileSvgSprites();
+    await h.copyAssets();
+    await h.compileTemplates();
+  },
+);
 
 worker.terminate();
diff --git a/frontend/src/app/main/ui/components/buttons/simple_button.stories.jsx b/frontend/src/app/main/ui/components/buttons/simple_button.stories.jsx
index 33142e12c..d53eaf638 100644
--- a/frontend/src/app/main/ui/components/buttons/simple_button.stories.jsx
+++ b/frontend/src/app/main/ui/components/buttons/simple_button.stories.jsx
@@ -4,16 +4,14 @@ import Components from "@target/components";
 import Icons from "@target/icons";
 
 export default {
-  title: 'Buttons/Simple Button',
+  title: "Buttons/Simple Button",
   component: Components.SimpleButton,
 };
 
 export const Default = {
   render: () => (
     <Components.StoryWrapper>
-      <Components.SimpleButton>
-        Simple Button
-      </Components.SimpleButton>
+      <Components.SimpleButton>Simple Button</Components.SimpleButton>
     </Components.StoryWrapper>
   ),
 };
@@ -27,4 +25,4 @@ export const WithIcon = {
       </Components.SimpleButton>
     </Components.StoryWrapper>
   ),
-}
+};
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index d96dca56a..36f2b0f36 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -7950,7 +7950,7 @@ __metadata:
     postcss: "npm:^8.4.38"
     postcss-clean: "npm:^1.2.2"
     postcss-modules: "npm:^6.0.0"
-    prettier: "npm:^3.2.5"
+    prettier: "npm:3.3.2"
     pretty-time: "npm:^1.1.0"
     prop-types: "npm:^15.8.1"
     randomcolor: "npm:^0.6.2"
@@ -12093,6 +12093,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"prettier@npm:3.3.2":
+  version: 3.3.2
+  resolution: "prettier@npm:3.3.2"
+  bin:
+    prettier: bin/prettier.cjs
+  checksum: 10c0/39ed27d17f0238da6dd6571d63026566bd790d3d0edac57c285fbab525982060c8f1e01955fe38134ab10f0951a6076da37f015db8173c02f14bc7f0803a384c
+  languageName: node
+  linkType: hard
+
 "prettier@npm:^2.8.0":
   version: 2.8.8
   resolution: "prettier@npm:2.8.8"
@@ -12102,15 +12111,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"prettier@npm:^3.2.5":
-  version: 3.2.5
-  resolution: "prettier@npm:3.2.5"
-  bin:
-    prettier: bin/prettier.cjs
-  checksum: 10c0/ea327f37a7d46f2324a34ad35292af2ad4c4c3c3355da07313339d7e554320f66f65f91e856add8530157a733c6c4a897dc41b577056be5c24c40f739f5ee8c6
-  languageName: node
-  linkType: hard
-
 "pretty-format@npm:^27.0.2":
   version: 27.5.1
   resolution: "pretty-format@npm:27.5.1"