Pollito Dev
November 26, 2024

Pollito's Opinion on Spring Boot Development 10: Next.js?

Posted on November 26, 2024  •  5 minutes  • 964 words  • Other languages:  Español

Some context

This is the tenth part of the Spring Boot Development blog series.

Let’s start!

I do know some frontend

I am not a frontend developer, I do not engage in frontend developer activities in my day to day.

Having said that, I do know some frontend:

But my biggest teachers in frontend (specially React) are: Theo , Josh , and Midudev .

How did I approach this challenge?

Because my taste and knowledge on UI/UX is not that great, I choose pre-made solutions out there.

But the most important library I used was Orval RESTful client generator

Design by Contract principles in a Next.js application

In Orval Overview page you can find the following:

Orval is able to generate client with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification

And in the OpenAPI Generator Overview , the tool we used in our Java Spring Boot microservice to create an API following Design by Contract principles , you can find the following:

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (both 2.0 and 3.0 are supported)

It seems that is possible to implement Design by Contract principles in a Next.js app. Let’s check how it was made.

1. Orval configuration

In orval.config.ts :

import { defineConfig } from "orval";

export default defineConfig({
  users: {
    output: {
      mode: "split",
      target: "src/__generated__/api/users/usersApi.ts",
      schemas: "src/__generated__/api/users/model",
      client: "react-query",
    },
    input: {
      target: "src/openapi/userManagerBackend.yaml",
    },
  },
});

2. prebuild script in package.json

"prebuild": "npm run orval-build",

3. Use example

In the OpenAPI Specification , we have an operation named findById.

/users/{id}:
  get:
    tags:
      - User
    summary: Get user by identifier
    operationId: findById
    parameters:
      - description: User identifier
        in: path
        name: id
        required: true
        schema:
          format: int64
          type: integer
    responses:
      '200':
        description: A user
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      default:
        description: Error
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Error'

On pre-build, Orval generated a function useFindById. Here’s an example on how to use it:

src/app/users/[id]/page.tsx

"use client";
import { useParams } from "next/navigation";
import { getId } from "./_utils/params-utils";
import Loading from "@/components/v0/loading";
import AxiosErrorAlert from "@/components/v0/axios-error-alert";
import UserCard from "./_components/user-card";
import RedirectButton from "@/components/v0/redirect-button";
import { useFindById } from "@/__generated__/api/users/usersApi";

const UserDetails = () => {
  const id = getId(useParams<{ id: string }>());
  const {
    isPending,
    isError,
    data: response,
    error,
  } = useFindById(id, {
    axios: { baseURL: process.env.NEXT_PUBLIC_API_USERS_BASE_URL },
  });

  if (isPending) {
    return <Loading />;
  }

  if (isError) {
    return <AxiosErrorAlert axiosError={error} />;
  }

  return (
    <div className="flex flex-col items-center pt-4">
      <div className="flex flex-col items-center gap-4 w-full max-w-md">
        <UserCard user={response.data} />
        <div className="w-full flex justify-end">
          <RedirectButton href="/users" label="See Users" />
        </div>
      </div>
    </div>
  );
};

export default UserDetails;

Deployment

Don’t overcomplicate, and just deploy in a Vercel free plan. Don’t forget to add the ENV secrets to point to the backend, and the pagination size (personal preference to have it as a global thing).

.env.example

NEXT_PUBLIC_API_USERS_BASE_URL=https://user-manager-backend-den3.onrender.com
NEXT_PUBLIC_API_USERS_PAGE_SIZE=5

That’s all

It was a long journey, that started all the way back in December 2023 with old blogs (now deleted), treating the same concepts I did in this series, Design by Contract Principles.

Screenshot2024-11-26195802

There are some minor rough edges to fix here and there:

Nonetheless, I’m happy with the result as it is right now.

I invite you to check other stuff in my blog, as my passion for web development will keep me writing blogs for sure.

Cheers! Pollito <🐤/>.

Hey, check me out!

You can find me here