Next.js Discord

Discord Forum

API routing issues

Unanswered
Polar bear posted this in #help-forum
Open in Discord
Polar bearOP
Hi! I have been working on a full-stack task tracker app (similar to trello) using Next13 (app structure), Planetscale, and Prisma. For the API calls, I was able to set up a good structure in app/api/task/route.ts for basic CRUD features.

On the front-end, I want to fetch requests to the endpoint 'api/task' (similar to how it was in the pages structures). But after trying it, I am only able to request the endpoint to http://localhost:3000/api/task. While this works, it won't work once I deploy to Vercel. Does anyone have suggestions on how I can set up my endpoints on the front-end?


import Sidebar from '@/app/components/Sidebar';

export default async function Dashboard() {
    const tasks = await fetch('api/task') // this doesn't work
    const tasks2 = await fetch('http://localhost:3000/api/task') // this works

    return (
        <div className='container w-screen h-screen'>
            <div className='bg-white h-full w-[314px] border-solid border-r-[1px] border-tertiary'>
                <Sidebar />
            </div>
            <div className='main-content'></div>
        </div>
    );
}

29 Replies

Asian black bear
Hey,
Try /api/task when fetching
just inlcude api route
Polar bearOP
I tried this, but I get the below error.

const tasks = await fetch('/api/task');

Unhandled Runtime Error
Error: Failed to parse URL from /api/task
Asian black bear
try to add the GET as method

const task = await fetch("/api/task", { method: "GET", });
Polar bearOP
I am getting the same error unfortunately. I also tried axios get and got the same error. it only works if i use localhost:3000/api/task
Asian black bear
I hope you are following the right folder structure for api routes
https://nextjs.org/docs/app/building-your-application/routing/route-handlers

/api/task/route.ts this must be for you
Polar bearOP
Yes, I am. app/api/task/route.ts
the only issue is the fetch url
unfortunately, the docs don't really have much about it
Asian black bear
I think I get it. You are using fetch in the server component. So the fetch in the server component might not call the api route this way. To use fetch in the server Component I guess you will have to give full url
that means https://your-domain/api/task
Polar bearOP
Yeah that's what i was worried about and assumed that was the case. I guess I could just use pages/api and connect like that
i was just hoping there would be something else I could try. I dont want to have to set up a separate server for this
Asian black bear
I dont think you need to set up a server for this
just add the your domain before the "/api"
For example, const tasks = await fetch(${process.env.API_BASE_URL}/api/task);
Polar bearOP
this would work with vercel?
so setting up dev and production variables? Dev variable being localhost:3000 and then prod being test.vercel.app/?
Asian black bear
If your domain is "test.vercel.app"
Polar bearOP
ok thank you! i'll give this a try
that actually makes a lot of sense and is quite simple haha
Asian black bear
Yup
Polar bearOP
thank you for helping me get my head straight!
this should work now
Asian black bear
just found this
https://nextjs-faq.com/fetch-api-in-rsc
I think calling your route from a server component is not a recommended way. You should move that server logic to the server component itself.

But the way i told you might work but its not recommended.
Polar bearOP
thank you! ill give this a read
Polar bearOP
I get what this article is saying, but some of my components are client-components, so i cannot use the prisma queries. i think i will just have to use the environment method
I'll post in here if it works or issues arise
Polar bearOP
If anyone has an alternate suggestion for what I'm doing, please let me know.

'use client';
import React, { useState, useEffect } from 'react';
import Sidebar from '@/app/components/Sidebar';
import { Task } from '@/types';

const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;

export default function Dashboard() {
    const [selectedItem, setSelectedItem] = useState<string | null>(null);

    useEffect(() => {
        console.log(selectedItem);
        async function fetchTasks() {
            const res = await fetch(`${BASE_URL}/api/task`, { method: 'GET' });
            const tasks: Task[] = await res.json();
        }
        fetchTasks();
    }, [selectedItem]);

    return (
        <div className='container w-screen h-screen'>
            <div className='bg-white h-full w-[314px] border-solid border-r-[1px] border-tertiary'>
                <Sidebar setSelectedItem={setSelectedItem} />
            </div>
            <div className='main-content'></div>
        </div>
    );
}
Asian black bear
Now, you can converted your component to a cleint side component, you dont have to use Base url.