diff --git a/apps/client/src/print.tsx b/apps/client/src/print.tsx
index 4d74fd90c..0ff7522f9 100644
--- a/apps/client/src/print.tsx
+++ b/apps/client/src/print.tsx
@@ -2,6 +2,7 @@ import FNote from "./entities/fnote";
 import { render } from "preact";
 import { CustomNoteList } from "./widgets/collections/NoteList";
 import "./print.css";
+import { useCallback, useRef } from "preact/hooks";
 
 async function main() {
     const notePath = window.location.hash.substring(1);
@@ -12,10 +13,25 @@ async function main() {
     const note = await froca.getNote(noteId);
 
     if (!note) return;
-    render(getElementForNote(note), document.body);
+    render(, document.body);
 }
 
-function getElementForNote(note: FNote) {
+function App({ note }: { note: FNote }) {
+    return (
+        <>
+            
+        >
+    );
+}
+
+function ContentRenderer({ note }: { note: FNote }) {
+    const sentReadyEvent = useRef(false);
+    const onReady = useCallback(() => {
+        if (sentReadyEvent.current) return;
+        window.dispatchEvent(new Event("note-ready"));
+        sentReadyEvent.current = true;
+    }, []);
+
     // Collections.
     if (note.type === "book") {
         return ;
     }
 
diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css
index 03d1bd8ff..fd8383130 100644
--- a/apps/client/src/stylesheets/style.css
+++ b/apps/client/src/stylesheets/style.css
@@ -2422,4 +2422,14 @@ footer.webview-footer button {
 .revision-diff-removed {
     background: rgba(255, 100, 100, 0.5);
     text-decoration: line-through;
+}
+
+iframe.print-iframe {
+    position: absolute;
+    top: 0;
+    left: -600px;
+    right: -600px;
+    bottom: 0;
+    width: 0;
+    height: 0;
 }
\ No newline at end of file
diff --git a/apps/client/src/widgets/collections/NoteList.tsx b/apps/client/src/widgets/collections/NoteList.tsx
index 11abcc5c2..f9c9ba5d1 100644
--- a/apps/client/src/widgets/collections/NoteList.tsx
+++ b/apps/client/src/widgets/collections/NoteList.tsx
@@ -23,9 +23,10 @@ interface NoteListProps {
     isEnabled: boolean;
     ntxId: string | null | undefined;
     media: ViewModeMedia;
+    onReady: () => void;
 }
 
-export default function NoteList(props: Pick) {
+export default function NoteList(props: Pick) {
     const { note, noteContext, notePath, ntxId } = useNoteContext();
     const isEnabled = noteContext?.hasNoteList();
     return 
diff --git a/apps/client/src/widgets/collections/interface.ts b/apps/client/src/widgets/collections/interface.ts
index 81a8e4d3d..7bec23a64 100644
--- a/apps/client/src/widgets/collections/interface.ts
+++ b/apps/client/src/widgets/collections/interface.ts
@@ -16,4 +16,5 @@ export interface ViewModeProps {
     viewConfig: T | undefined;
     saveConfig(newConfig: T): void;
     media: ViewModeMedia;
+    onReady(): void;
 }
diff --git a/apps/client/src/widgets/collections/presentation/index.tsx b/apps/client/src/widgets/collections/presentation/index.tsx
index 44341688a..dfa4574e0 100644
--- a/apps/client/src/widgets/collections/presentation/index.tsx
+++ b/apps/client/src/widgets/collections/presentation/index.tsx
@@ -14,7 +14,7 @@ import { t } from "../../../services/i18n";
 import { DEFAULT_THEME, loadPresentationTheme } from "./themes";
 import FNote from "../../../entities/fnote";
 
-export default function PresentationView({ note, noteIds, media }: ViewModeProps<{}>) {
+export default function PresentationView({ note, noteIds, media, onReady }: ViewModeProps<{}>) {
     const [ presentation, setPresentation ] = useState();
     const containerRef = useRef(null);
     const [ api, setApi ] = useState();
@@ -33,6 +33,14 @@ export default function PresentationView({ note, noteIds, media }: ViewModeProps
 
     useLayoutEffect(refresh, [ note, noteIds ]);
 
+    useEffect(() => {
+        // We need to wait for Reveal.js to initialize (by setting api) and for the presentation to become available.
+        if (api && presentation) {
+            // Timeout is necessary because it otherwise can cause flakiness by rendering only the first slide.
+            setTimeout(onReady, 200);
+        }
+    }, [ api, presentation ]);
+
     if (!presentation || !stylesheets) return;
     const content = (
         <>
diff --git a/apps/client/src/widgets/note_detail.ts b/apps/client/src/widgets/note_detail.ts
index 5b798a06a..0ec68060c 100644
--- a/apps/client/src/widgets/note_detail.ts
+++ b/apps/client/src/widgets/note_detail.ts
@@ -297,8 +297,19 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
             return;
         }
 
-        // Trigger in timeout to dismiss the menu while printing.
-        setTimeout(window.print, 0);
+        const iframe = document.createElement('iframe');
+        iframe.src = `?print#${this.notePath}`;
+        iframe.className = "print-iframe";
+        document.body.appendChild(iframe);
+        iframe.onload = () => {
+            console.log("Got ", iframe, iframe.contentWindow);
+            if (iframe.contentWindow) {
+                iframe.contentWindow.addEventListener("note-ready", () => {
+                    iframe.contentWindow?.print();
+                    document.body.removeChild(iframe);
+                });
+            }
+        };
     }
 
     async exportAsPdfEvent() {
diff --git a/apps/client/src/widgets/ribbon/NoteActions.tsx b/apps/client/src/widgets/ribbon/NoteActions.tsx
index f780eab8b..2fed2ea02 100644
--- a/apps/client/src/widgets/ribbon/NoteActions.tsx
+++ b/apps/client/src/widgets/ribbon/NoteActions.tsx
@@ -47,11 +47,11 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
   const canBeConvertedToAttachment = note?.isEligibleForConversionToAttachment();
   const isSearchable = ["text", "code", "book", "mindMap", "doc"].includes(note.type);
   const isInOptions = note.noteId.startsWith("_options");
-  const isPrintable = ["text", "code"].includes(note.type);
+  const isPrintable = ["text", "code", "book"].includes(note.type);
   const isElectron = getIsElectron();
   const isMac = getIsMac();
   const hasSource = ["text", "code", "relationMap", "mermaid", "canvas", "mindMap"].includes(note.type);
-  const isSearchOrBook = ["search", "book"].includes(note.type);  
+  const isSearchOrBook = ["search", "book"].includes(note.type);
 
   return (
      noteContext?.notePath && parentComponent?.triggerCommand("showExportDialog", {
-          notePath: noteContext.notePath, 
+          notePath: noteContext.notePath,
           defaultType: "single"
         })} />
       
@@ -133,4 +133,4 @@ function ConvertToAttachment({ note }: { note: FNote }) {
         }}
       >{t("note_actions.convert_into_attachment")}
   )
-}
\ No newline at end of file
+}