Rails and Next.js: the perfect combination for modern web development (Final part)

Raphael Almeida Araújo
4 min readAug 9, 2023

Updates:

November 11th, 2023: I created a gem to help us generate the scaffold for the Rails API and the NextJS app using a single command. Now, we can use dynamic routes. Get more information at https://github.com/raphox/next_rails_scaffold.

As promised in the previous post, it’s time to technically detail the process of creating a Ruby on Rails application that renders web pages using React components generated by Next.js.

As I shared in the previous post, I made a commit for each step of the process:

https://github.com/raphox/rails-next/commits/main

The creation of the project was divided into four stages:

  1. Create the Ruby on Rails project.
  2. Create API endpoints for document management.
  3. Create the Next.js project and configure it so that the HTML and Javascript code generation script sends the files to the Rails project’s public folder.
  4. Change the Next.js default page to consume API data from the Ruby on Rails project.

Considering what it takes to integrate Rails with Next.js, let’s now break down each process step.

Create the Ruby on Rails project

Excellent and detailed documentation on the process of creating a Ruby on Rails application can be found here https://guides.rubyonrails.org/getting_started.html#creating-a-new-rails-project.

But if you already have all the necessary dependencies, you will basically need to run the following command:

rails new my_api --api

With just this command, you will have generated all the code to complete the first step.

The --api option used in the project generation command will discard the entire View layer of the Ruby on Rails project. This is necessary since we are going to use Next.js instead of the View layer.

Create API Endpoints for Document Management

Now that we have the base code for the Ruby on Rails application let’s make the endpoints available that will be consumed by the React interface.

rails g scaffold Document title:string description:string link:string

And that’s it. We already have the database structure and endpoints for the following:

  • List the documents
  • View data for a specific document
  • Create a new document
  • Update data for a specific document
  • Remove a specific document

Don’t forget to run the rails db:migrate command to create the database structure.

Create the Next.js project

To add the Next project, just initialize the project inside the Rails application directory:

npx create-next-app@latest

Creation options:

What is your project named? frontend
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias? No / Yes

When you finish creating the project, you only need to change two files:

// frontend/package.json#L7
+ "build": "next build && next export -o ../public",
// frontend/next.config.js#L4-L6
+ images: {
+ unoptimized: true,
+ },

From there you can use the npm run build command to convert your Next application into a SPA within your Rails application’s public public directory.

Tip: You have the option to create the Procfile.local file to work together with the https://github.com/ddollar/foreman gem. That way you don’t have to start the two applications every time you start the project.

# Procfile.local
api: bin/rails server -p 8080
frontend: sh -c 'cd ./frontend && npm run dev'

For more detailed information on installing, building, and configuring Next.js, visit https://nextjs.org/docs.

Consume API data through SPA

To focus on consuming the API and not worry so much about the other features, the generated code example is based on the default page of a Next.js project.

As you can see in the image below, a list of links to the official Next.js documentation is at the bottom of the page. Let’s change this part of the code to list the links based on the data collected from the API.

To consume the API, a hook called useDocuments was created:

Using useDocuments inside the main page, we will have access to the API data so that we can print the links:

export default function Home() {
const { documents, isLoading } = useDocuments();
// ...
{isLoading ? (
<p>Loading...</p>
) : (
documents?.map((document) => (
<a
key={document.id}
href={document.link}
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
{`${document.title} `}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
{document.description}
</p>
</a>
))
)}
// ...

And this is the end of our series of posts.

I hope that I have contributed so that fewer people have a headache integrating React with Rails and that we can build well-structured projects in Rails, taking advantage of everything that React has provided and provided us in recent years.

--

--