diff --git a/src/app/page.tsx b/src/app/page.tsx
index d35b1b2..3112b11 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -55,6 +55,12 @@ const shapeUtils = [LiveImageShapeUtil]
const tools = [LiveImageTool]
export default function Home() {
+ // Server-side rendering check
+ if (typeof window === 'undefined') {
+ // Return a minimal placeholder for SSR
+ return
Loading editor...
+ }
+
const onEditorMount = (editor: Editor) => {
// We need the editor to think that the live image shape is a frame
// @ts-expect-error: patch
diff --git a/src/hooks/useLiveImage.tsx b/src/hooks/useLiveImage.tsx
index c13607a..d52221b 100644
--- a/src/hooks/useLiveImage.tsx
+++ b/src/hooks/useLiveImage.tsx
@@ -121,6 +121,9 @@ export function useLiveImage(
if (!fetchImage) throw new Error('Missing LiveImageProvider')
useEffect(() => {
+ // Skip on server-side
+ if (typeof window === 'undefined') return;
+
let prevHash = ''
let prevPrompt = ''
diff --git a/src/utils/screenshot.ts b/src/utils/screenshot.ts
index 378a249..91a39db 100644
--- a/src/utils/screenshot.ts
+++ b/src/utils/screenshot.ts
@@ -1,11 +1,21 @@
-import { type } from 'os'
+'use client'
-const fileReader = new FileReader()
+import { type } from 'os'
+import { blobToDataUri } from './blob'
let _canvas: HTMLCanvasElement | null = null
let _ctx: CanvasRenderingContext2D | null = null
+function getFileReader() {
+ if (typeof window === 'undefined') return null
+ return new FileReader()
+}
+
async function fastGetSvgAsString(svg: SVGElement) {
+ if (typeof window === 'undefined') {
+ return ''
+ }
+
const clone = svg.cloneNode(true) as SVGGraphicsElement
svg.setAttribute('width', +svg.getAttribute('width')! + '')
@@ -17,13 +27,13 @@ async function fastGetSvgAsString(svg: SVGElement) {
const src = img.getAttribute('xlink:href')
if (src) {
if (!src.startsWith('data:')) {
- const blob = await (await fetch(src)).blob()
- const base64 = await new Promise((resolve, reject) => {
- fileReader.onload = () => resolve(fileReader.result as string)
- fileReader.onerror = () => reject(fileReader.error)
- fileReader.readAsDataURL(blob)
- })
- img.setAttribute('xlink:href', base64)
+ try {
+ const blob = await (await fetch(src)).blob()
+ const base64 = await blobToDataUri(blob)
+ img.setAttribute('xlink:href', base64)
+ } catch (error) {
+ console.error('Error processing image:', error)
+ }
}
}
}
@@ -45,6 +55,10 @@ export async function fastGetSvgAsImage(
height: number
}
) {
+ if (typeof window === 'undefined') {
+ return null
+ }
+
const svgUrl = URL.createObjectURL(new Blob([svgString], { type: 'image/svg+xml' }))
if (!_canvas) {
@@ -84,18 +98,13 @@ export async function fastGetSvgAsImage(
if (!canvas) return null
- const blobPromise = new Promise((resolve) =>
+ return new Promise((resolve) =>
canvas.toBlob(
(blob) => {
- if (!blob) {
- resolve(null)
- }
resolve(blob)
},
- 'image/' + type,
+ `image/${options.type}`,
options.quality
)
)
-
- return blobPromise
}