diff --git a/apps/fullstack/components/editor/worker/pageWorker/pageworker.ts b/apps/fullstack/components/editor/worker/pageWorker/pageworker.ts
index 8d1d3cc0cdf75f2938a1ae8f3e628774b0127693..14cc908fc2694f870e925fc3a4620d1faf45e7bf 100644
--- a/apps/fullstack/components/editor/worker/pageWorker/pageworker.ts
+++ b/apps/fullstack/components/editor/worker/pageWorker/pageworker.ts
@@ -33,7 +33,7 @@ const debug = (...args: unknown[]) => {
 export class PageWorker {
     static #instance: PageWorker;
 
-    private constructor() { }
+    private constructor() {}
 
     public static get instance(): PageWorker {
         if (!PageWorker.#instance) {
@@ -221,6 +221,7 @@ export class PageWorker {
             throw new Error("Page needs to be initialized to place snips!");
         }
         debug("[placeOnPage]", "Placing snip", data.snip.id);
+        data.snip.book_id = this.page.data.book_id;
         const snip = await loadSnip(data.snip);
         debug("[placeOnPage]", "Got snip", snip.type);
         snip.socket = this.page.socket;
diff --git a/apps/fullstack/lib/hooks/useDevicePixelRatio.ts b/apps/fullstack/lib/hooks/useDevicePixelRatio.ts
index 24797e119ecea999d126a8888d35842dfd98e18e..7f4bba47164d8642fe0b225999d8ed00d35c27f5 100644
--- a/apps/fullstack/lib/hooks/useDevicePixelRatio.ts
+++ b/apps/fullstack/lib/hooks/useDevicePixelRatio.ts
@@ -2,7 +2,7 @@
 import { useCallback, useEffect, useState } from "react";
 
 const useDevicePixelRatio = () => {
-    const [pixelRatio, setPixelRatio] = useState(window?.devicePixelRatio || 1);
+    const [pixelRatio, setPixelRatio] = useState(getDevicePixelRatio());
 
     const handleChange = useCallback(() => {
         setPixelRatio(window.devicePixelRatio);
@@ -31,4 +31,17 @@ const useDevicePixelRatio = () => {
     return pixelRatio;
 };
 
+/**
+ * Returns the current device pixel ratio (DPR) given the passed options
+ *
+ * @param options
+ * @returns current device pixel ratio
+ */
+export function getDevicePixelRatio(): number {
+    const hasDprProp =
+        typeof window !== "undefined" &&
+        typeof window.devicePixelRatio === "number";
+    return hasDprProp ? window.devicePixelRatio : 1; //defaults to 1
+}
+
 export default useDevicePixelRatio;
diff --git a/apps/images/src/render/overrides.ts b/apps/images/src/render/overrides.ts
index ad57975fd5986e20548a6dca3aa09eb069d1ffa8..27e9b46c1e1d14874e1ec528fe9af29e36c4f8a9 100644
--- a/apps/images/src/render/overrides.ts
+++ b/apps/images/src/render/overrides.ts
@@ -1,9 +1,13 @@
-import { createCanvas, Image } from "canvas";
+import { Canvas, Image } from "canvas";
 import sharp from "sharp";
 
+import { BaseSnip } from "@snip/snips/general/base";
 import { ImageSnip } from "@snip/snips/general/image";
 import { ImageSnipLegacy } from "@snip/snips/general/legacy/image";
-import { TextSnip } from "@snip/snips/general/text";
+
+BaseSnip.prototype.createCanvas = function (width: number, height: number) {
+    return new Canvas(width, height);
+};
 
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
 const get_bitmap = async function (this: any) {
@@ -40,63 +44,3 @@ const get_bitmap = async function (this: any) {
 
 ImageSnipLegacy.prototype.get_bitmap = get_bitmap;
 ImageSnip.prototype.get_bitmap = get_bitmap;
-
-TextSnip.prototype.get_overlap_index_v3 = function (str, maxWidth, font) {
-    if (maxWidth == -1) {
-        return undefined;
-    }
-    const canvas = createCanvas(1, 1);
-    const ctx = canvas.getContext("2d");
-    ctx.font = font;
-
-    let width = 0;
-    for (let c = 0; c < str.length; c++) {
-        const char = str.charAt(c);
-        width += ctx.measureText(char).width;
-        if (width > maxWidth) {
-            return c;
-        }
-    }
-    return undefined;
-};
-
-TextSnip.prototype.splitStringAtWrap = function (
-    str: string,
-    maxWidth: number,
-    font: string,
-): string[] {
-    if (maxWidth == -1) {
-        return [str];
-    }
-
-    const canvas = createCanvas(1, 1);
-    const ctx = canvas.getContext("2d");
-    ctx.font = font;
-
-    let width = 0;
-    const splits = [];
-    for (let c = 0; c < str.length; c++) {
-        const char = str.charAt(c);
-        const cWidth = ctx.measureText(char).width;
-        width += cWidth;
-        if (width >= maxWidth) {
-            splits.push(c);
-            width = cWidth;
-        }
-    }
-
-    // split into segments
-    const segments: string[] = [];
-    let start = 0;
-
-    for (const split of splits) {
-        segments.push(str.slice(start, split));
-        start = split;
-    }
-
-    // Add the last segment if there's any remaining part of the string
-    if (start < str.length) {
-        segments.push(str.slice(start));
-    }
-    return segments;
-};
diff --git a/apps/socket/src/prefixes/snip/socket.ts b/apps/socket/src/prefixes/snip/socket.ts
index 0d2b9f96b929f5d249ca002e9d5177ffb75ea0e2..405cbc458c7d52709ead055a87787bc7db3739ab 100644
--- a/apps/socket/src/prefixes/snip/socket.ts
+++ b/apps/socket/src/prefixes/snip/socket.ts
@@ -212,7 +212,13 @@ async function update(
     await triggerRender(socket.book_id, page_id, server);
 }
 
-async function remove({ socket, server }: SocketData, id: ID, callback) {
+async function remove(
+    { socket, server }: SocketData,
+    id: ID,
+    callback: (
+        res: { success: true } | { success: false; details: string },
+    ) => void,
+) {
     // Snips can only be removed/erased if one has created them oneself
     // and if they are placed in the last 5 mins
     let page_id;
@@ -221,8 +227,9 @@ async function remove({ socket, server }: SocketData, id: ID, callback) {
         page_id = snip.page_id;
         if (
             snip.created_by != socket.data.id ||
-            snip.last_updated.getTime() <
-                Date.now() - client_config.TOOLS.ERASER.TIMEOUT * 1000
+            (snip.last_updated &&
+                snip.last_updated.getTime() <
+                    Date.now() - client_config.TOOLS.ERASER.TIMEOUT * 1000)
         ) {
             throw new Error("Cant delete snip!");
         }
@@ -236,7 +243,7 @@ async function remove({ socket, server }: SocketData, id: ID, callback) {
     } catch (e) {
         callback?.({
             success: false,
-            details: e.message,
+            details: ((e as Error)?.message as string) || "",
         });
     }
 
diff --git a/packages/database/src/services/snip.ts b/packages/database/src/services/snip.ts
index 2222bf7a6c5187413f59196eab4d87569b03e53d..d1e6fdec861e8b32fe2b7840df25ebf4cdea4fef 100644
--- a/packages/database/src/services/snip.ts
+++ b/packages/database/src/services/snip.ts
@@ -97,6 +97,10 @@ export class SnipService implements SnipStrategy {
             console.warn("SnipService.insert: id is set, inserting new snip");
         }
 
+        if (!snipData.created_by) {
+            console.warn(`Inserting without owner (created_by)!`);
+        }
+
         // Check if snip has blob and insert
         let blob_id: number | null = null;
         if (hasOwnProperty(snipData.data, "blob")) {
@@ -118,6 +122,10 @@ export class SnipService implements SnipStrategy {
             // Insert nested snips
             snip_data.snips = await Promise.all(
                 snip_data.snips.map(async (snipd) => {
+                    // Sanity overwrite for book id and created by
+                    snipd.created_by = snipData.created_by;
+                    snipd.book_id = snipData.book_id;
+
                     return await this.insert(snipd);
                 }),
             );
@@ -129,6 +137,11 @@ export class SnipService implements SnipStrategy {
             const snip_data = snipData.data as BaseData & {
                 snip: SnipData<BaseData, BaseView>;
             };
+
+            // Sanity overwrite for book id and created by
+            snip_data.snip.created_by = snipData.created_by;
+            snip_data.snip.book_id = snipData.book_id;
+
             snip_data.snip = await this.insert(snip_data.snip);
             snipData.data = snip_data;
         }