Next.js Discord

Discord Forum

Notify client component of a server event

Unanswered
Cape lion posted this in #help-forum
Open in Discord
Cape lionOP
I have a pdf creation happening server-side that dumps in public/ and I want a download button to re-render to point to the new file path.

I have the button set up as follows to enable/disable it based on the pdf availability:
"use client";

export default function DownloadButton(pdfPath: string | null = null) {
  if (!pdfPath) {
    return (
      <button disabled className="px-4 py-2 rounded-md bg-gray-100 text-gray-400 cursor-not-allowed">
        Download
      </button>
    );
  }

  return (
    <a
      href={pdfPath}
      download="resume.pdf"
      className="px-4 py-2 rounded-md bg-gray-200 hover:bg-gray-300 inline-block no-underline text-black"
    >
      Download
    </a>
  );
}

How can its pdfPath react to the creation of a new pdf server-side?

3 Replies

Roseate Spoonbill
Highly depends on average time it takes to create the pdf. I'll assume it's long enough, so that it cannot be put in single request to server.

1. Without websockets you cannot push that kind of info to browser directly
2. Instead, a job registration pattern can be used:
1. Client requests PDF
2. Server registers pdf creation job and puts it into DB. It returns job id to client.
3. Client uses polling to check creation status via api or server action.
4. Once server is done, it saves pdf (e.g. to S3), and puts URL into the job record
5. Client notices job done, and continues with results on the browser

If the generation takes less than 30s, then you could do it in API route handler and return generated PDF directly. Way faster, and less of a setup work, but only if you can guarantee fast response.

Also, you mentioned using /public folder - make sure this can be done at all. Some deployment environments (e.g. vercel or cloudflare) won't work with this setup directly and will require separate solution for hosting and downloading generated files.
@Roseate Spoonbill Highly depends on average time it takes to create the pdf. I'll assume it's long enough, so that it cannot be put in single request to server. 1. Without websockets you cannot push that kind of info to browser directly 2. Instead, a job registration pattern can be used: 1. Client requests PDF 2. Server registers pdf creation job and puts it into DB. It returns job id to client. 3. Client uses polling to check creation status via api or server action. 4. Once server is done, it saves pdf (e.g. to S3), and puts URL into the job record 5. Client notices job done, and continues with results on the browser If the generation takes less than 30s, then you could do it in API route handler and return generated PDF directly. Way faster, and less of a setup work, but only if you can guarantee fast response. Also, you mentioned using `/public` folder - make sure this can be done at all. Some deployment environments (e.g. vercel or cloudflare) won't work with this setup directly and will require separate solution for hosting and downloading generated files.
Cape lionOP
Thank you for the reply!

The time it takes to create a pdf is around 10 seconds, which puts me in your second scenario. Is using API routes preferable to a Server Action here?

If possible, I would like to avoid polling as it feels a bit wasteful...there is a specific event that happens server-side (also called there) that triggers pdf creation...the client just needs to know about when the creation is done so that it links the download button to it.

The /public folder approach worked with railway deployment back when I implemented my app in Solara (a React-as-Python framework), though I'm indeed probably going to switch to Vercel now that I'm working with nextjs...Plus, it's probably the wrong approach since I want the user to only access the pdf via my Download button, not through the browser console or other in public/
Roseate Spoonbill
If possible, I would like to avoid polling as it feels a bit wasteful

I don't think polling is bad technique. It's definitely ok for something that only checks status every now and again. Having that said, 10s should be enough to run generation serverside. I am not sure how Server Action would preform here, but that's definitely what I would try to start with. And I wouldn't say api routes are better than server actions (unless your pdf gneration would be called from outside client, in which case api route is something I would prefer).

If you are going to use vercel, please start by testing putting something there first. I doubt it will work as on vercel deployed components of the system all go to different infra components. But then again I might be wrong, so best if you simply test it.