Leveraging NextJS14 Static Site Generation (SSG) for seamless Authentication with Clerk

Having a bit of trouble with Next.js Static Site Generation (SSG) and protected routes. SSG requires data to be available at build time, while protected routes need user authentication which isn't possible during this phase. The pages I'm trying to load require heavy database calls that result in static information updated once a day through a revalidation process at night.

Is there a way to bypass the Authentication phase during the building process so that "npm run build" still generates pre-rendered pages correctly while keeping them protected in production?

The typical implementation for Clerk involves addressing the Layout layer first:


import { ClerkProvider, SignInButton, SignedIn, SignedOut, UserButton } from '@clerk/nextjs';
import './globals.css';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <ClerkProvider>
      <html lang="en">
        <body>
          <header>
            <SignedOut>
              <SignInButton />
            </SignedOut>
            <SignedIn>
              <UserButton />
            </SignedIn>
          </header>
          <main>{children}</main>
        </body>
      </html>
    </ClerkProvider>
  )
}

However, if one of my pages involves heavy server-side actions like retrieving employee data from the database:


import { getAllEmployeesFromDatabase } from "@/lib/serverEmployeeLib";
import { EmployeeDataTable } from "@/components/EmployeeDataTable";
import React from "react";

async function EmployeesPage() {
  const employeeData = await getAllEmployeesFromDatabase(); 

  return (
    <div>
      <EmployeeDataTable
        data={employeeData}
      />
    </div>
  );
}

export default EmployeesPage;

The getAllEmployeesFromDatabase() won't be called during build time if it's part of a protected route.

I've considered an alternative approach but it seems cumbersome and counterintuitive as it goes against the idea of having a centralized protected layout. It would entail adding extra authentication logic to individual pages:


import { getAllEmployeesFromDatabase } from "@/lib/serverEmployeeLib";
import { EmployeeDataTable } from "@/components/EmployeeDataTable";
import React from "react";

async function EmployeesPage() {
  const employeeData = await getAllEmployeesFromDatabase();

  return (
    <ClerkProvider>
      <SignedOut>
        <SignInButton />
      </SignedOut>
      <SignedIn>
        <UserButton />
      </SignedIn>
      <div>
        <EmployeeDataTable data={employeeData} />
      </div>
    </ClerkProvider>
  );
}

export default EmployeesPage;

Any thoughts on a proper way to handle this? Thanks!

Answer №1

It's a bit of an enigma, but it did the trick for me.

Using ClerkProvider as a client component, wrapped in a suspense boundary, allows Next to statically generate the rest of the page smoothly.

Quoted from the corresponding github issue.

Possibly utilizing the new PPR feature of Next.js

"use client";

import { Suspense } from "react";
import { ClerkProvider, SignInButton, SignedIn, SignedOut, UserButton } from '@clerk/nextjs'
import './globals.css'

export const experimental_ppr = true;

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
   <Suspense>
    <ClerkProvider>
      <html lang="en">
        <body>
          <header>
            <SignedOut>
              <SignInButton />
            </SignedOut>
            <SignedIn>
              <UserButton />
            </SignedIn>
          </header>
          <main>{children}</main>
        </body>
      </html>
    </ClerkProvider>
  </Suspense>
  )
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Searching for the index of a clicked element? Here's how to do

I am trying to determine the index of a clicked anchor element in my navigation using jQuery. However, when I use the following code snippet, I always get zero in the console: $('.navigation ul li a').click(function(e) { e.preventDefault(); ...

"AngularJS fails to pass the value of a checkbox within ng-repeat and

I have already asked this question, but the previous solutions did not resolve my issue. I am attempting to pass the value of a checkbox to a controller in AngularJS, but I keep getting an 'undefined' message. I am new to AngularJS. Here is the ...

Tips for setting up npm dependencies in a subfolder

Within the main directory, I have a package.json file that contains this command: "install": "cd packages/my-package && yarn". Every time I execute yarn run install, my intention is for it to enter into the specified package, set up the node modul ...

Ember.js Helper that mimics an Ajax request response

After extensive exploration and experimentation, it seems that returning a value from an ajax request in Emberjs is quite challenging. (I could be mistaken.) The issue appears to be related to the asynchronous nature of callbacks. Here lies my predicament ...

Leverage the Frontend (Headless Commerce) to utilize the Admin API and retrieve products from Shopify

Attempting to retrieve products from Shopify using the Admin API (GraphQL) through my frontend. I utilized the following code: *I implemented "axios" on Quasar Framework, utilizing Headless Commerce const response = await this.$axios({ url: "https: ...

Tips for ensuring a consistent highlight for an active link in Bootstrap

Does anyone have a solution for maintaining highlighted links on a web page? <div id="productnav"> <nav> <ul class="nav"> <li><a href="<?php echo $prefix; ?>pages/one.php?category=1" id="navelement1"<?php if ($c == 1) e ...

Inserting a new row into a particular table

I am working on a project where I have a table that displays different exercises. My goal is to allow users to add a new row for each exercise individually. Currently, the snippet below shows how I have implemented this: <!DOC ...

New configuration for NextJS: Redefining redirects in a separate file

Transitioning from my old WordPress site to a fresh, sleek Next.js platform has been an exciting journey. One challenge I've encountered is dealing with the numerous redirects that need to be set up. I prefer keeping things organized and clutter-free, ...

Toggle the visibility of one div while hiding another by checking a checkbox

When checkbox1 is checked, I want to hide div1 and show div2. I've attempted the code below, but it didn't work as expected. <script type="text/javascript"> function valueChanged() { if ($('.checkbox1').is(":checked" ...

The JavaScript exec() RegExp method retrieves a single item

Possible Duplicate: Question about regex exec returning only the first match "x1y2z3".replace(/[0-9]/g,"a") This code snippet returns "xayaza" as expected. /[0-9]/g.exec("x1y2z3") However, it only returns an array containing one item: ["1"]. S ...

What distinguishes a WAV file recorded from a user's microphone versus a WAV file imported from a separate file? Identifying the unique characteristics that may be causing bugs

Currently, I have two methods available for sending a WAV file to the server. Users can either upload the file directly or record it using their microphone. After the files are sent, they undergo a similar processing workflow. The file is uploaded to S3 an ...

Using PHP and AJAX, populate a table based on the selection made from a dropdown

Hello, thank you for taking the time to review my issue. Let me outline the objective. I have successfully implemented two drop-down menus that are populated dynamically from a database. The query retrieves names and phone numbers (with plans to fetch mor ...

NPM is having trouble locating a shell script

An error is encountered when running npm run build: '.' is not recognized as an internal or external command, operable program or batch file. Here is the npm file that contains relevant scripts: "scripts": { "postinstall": "jspm instal ...

The latest issue encountered in @apollo/experimental-nextjs-app-support with Graphql Nextjs 13 has been identified

I am interested in utilizing mutation functions. apolloProvider.tsx "use client"; // ^ this file requires the "use client" pragma import { ApolloLink, HttpLink, SuspenseCache } from "@apollo/client"; import { ApolloNextApp ...

AJAX Showdown: Comparing jQuery's AJAX API to JavaScript's XHR

tl;dr: I have two different scripts that appear to be identical, but one works while the other does not. Why is this? Let me provide some context for this post. I am working on creating an image uploading form that utilizes AJAX requests to generate a dyn ...

Tips for querying Mongo using Node.js

Although this question may seem repetitive, please bear with me. My goal is to query MongoDB directly from the dom eventually, but for now, I'm working on querying from my routes module. Below is my query: var db = require('./config/db.js&apos ...

Hiding Certain Words on a Website

Is there a way to hide specific text strings on a website? For instance, suppose I want the string "hxxp://nullrefer.com/?" to be invisible whenever it appears on my page. If a URL like "hxxp://nullrefer.com/?hxxp://www.Amazon.com" is mentioned, I only w ...

Is there a way to dynamically change the helperText of a Material UI TextField using its current value through code?

I'm currently attempting to dynamically change the helperText of a Material UI TextField based on the value entered into the field. Below is my current implementation: const defaultScores = { STR: 10, DEX: 10, CON: 10, INT: 10, WIS: 10, CH ...

"Enhancing Your Tables: A Guide to Implementing Filters in jQuery.fancyTable or Similar Tools

Currently, I am utilizing the fancyTable plugin to showcase a table of Django results. I have successfully integrated a search bar and sortable columns (ascending/descending). Filters are also incorporated, but at present, they only update the search bar w ...

Only JSON objects with a boolean value of true will be returned

I am working on returning JSON objects in JavaScript/TypeScript that have a true boolean value for the "team" property. For example, the JSON data I am using is as follows: { "state": "Texas", "stateId": 1, "team": true }, { "state": "Cali ...