I tried to replicate two different APIs in different projects and both give me the same error. I am really not sure what the problem is and if someone could guide me on what to fix I would really appreciate it.
Unhandled Runtime Error
SyntaxError: Unexpected end of JSON input
let result = await response.json();
Page.tsx file
"use client";
import { useState, useRef } from "react";
import { ReactSketchCanvas, ReactSketchCanvasRef } from "react-sketch-canvas";
import { FaUndo, FaTrash } from "react-icons/fa";
export default function Home() {
const [prompt, setPrompt] = useState("");
const [error, setError] = useState<string | null>(null);
const [outputImage, setOutputImage] = useState<string | null>(null);
const canvasRef = useRef<ReactSketchCanvasRef>(null);
const handleUndo = () => {
canvasRef.current!.undo();
};
const handleClear = () => {
canvasRef.current!.clearCanvas();
};
const handleGenerate = async () => {
// user need to provide prompt
if (prompt === "") {
alert("Please enter your prompt first!");
return;
}
// convert sketch to base64
const base64 = await canvasRef.current!.exportImage("png");
console.log(base64);
generateAIImage(base64);
};
const generateAIImage = async (base64image: any) => {
const response = await fetch("/api/replicate", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
image: base64image,
prompt,
}),
});
let result = await response.json();
console.log(result);
if (result.error) {
setError(result.error);
return;
}
setOutputImage(result.output[1]);
};
return (
<div className="max-w-3xl mx-auto my-10 px-4">
{/* Header Section */}
<section className="flex items-center justify-center mb-10">
<h1 className="font-semibold text-transparent text-5xl bg-gradient-to-r from-blue-600 via-green-500 to-yellow-400 inline-block bg-clip-text">
Scribble For Fun
</h1>
</section>
{/* Sketch Canvas Section */}
<section className="w-[400px] h-[400px] mx-auto mb-16 mt-6">
<div className="w-full aspect-square border-none">
<ReactSketchCanvas
ref={canvasRef}
width="100%"
height="100%"
strokeWidth={4}
strokeColor="#000000"
/>
</div>
<div className="flex items-center justify-between mt-2">
<button
onClick={handleUndo}
className=" text-gray-300 text-md flex items-center hover:scale-110 duration-300 hover:text-yellow-500">
<FaUndo className="mr-2" /> Undo
</button>
<button className=" text-gray-300 text-md flex items-center hover:scale-110 duration-300 hover:text-red-500">
<FaTrash
onClick={handleClear}
className="mr-2" /> Clear
</button>
</div>
</section>
{/* Prompt Section */}
<section className="w-[400px] flex items-center mx-auto">
<input
type="text"
name="prompt"
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
className="rounded-l-lg py-3 px-4 w-full focus:outline-none text-black"
placeholder="Enter your prompt here"
/>
<button
onClick={handleGenerate}
className="rounded-r-lg py-3.5 px-4 ml-1 text-white bg-gradient-to-br from-yellow-400 to-red-600 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-green-200 dark:focus:ring-green-800 font-medium text-sm text-center">
Generate
</button>
</section>
{/* Output Image Section */}
<section className="w-[400px] h-[400px] flex items-center justify-center mx-auto mt-12">
{error && (
<div className="flex justify-center">
<p className="text-lg text-red-500">{error}</p>
</div>
)}
{outputImage && (
<img
src={outputImage}
className="object-cover w-full aspect-square rounded-lg mb-12"
/>
)}
</section>
</div>
);
}
route.ts file
import { NextResponse } from "next/server";
import Replicate from "replicate";
export async function POST(request: Request) {
// 1. Get the request data (in JSON format) from the client
const { image, prompt } = await request.json();
// 2. Initialize the replicate object with our Replicate API token
const replicate = new Replicate({
auth: process.env.REPLICATE_API_TOKEN as string,
});
// 3. Set the model that we're about to run
const model =
"jagilley/controlnet-scribble:435061a1b5a4c1e26740464bf786efdfa9cb3a3ac488595a2de23e143fdb0117";
// 4. Set the input image which is the image we uploaded from the client
const input = {
image,
prompt,
a_prompt: "best quality, extremely detailed",
n_prompt:
"longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality",
};
// 5. Run the Replicate's model (to remove background) and get the output image
const output = await replicate.run(model, { input });
// 6. Check if output is NULL then return error back to the client
if (!output) {
console.log("Something went wrong");
return NextResponse.json(
{ error: "Something went wrong" },
{ status: 500 }
);
}
// 7. Otherwise, we show output in the console (SERVER side)
// and return output back to the client
console.log("OUTPUT: ", output);
return NextResponse.json({ output }, { status: 201 });
}