Read and write SQL Database from a Next.js app
Render a Next.js page from SQL Database rows and add rows from a route handler, in an application that Azion deploys from GitHub.
You render a page of a Next.js App Router project from the rows of a SQL Database table, and add rows from a route handler, in an application that Azion builds from your GitHub repository. Both files run in the function the build deploys. To write rows from a function you write yourself, refer to Write rows to SQL Database from a function.
The page reads through a read replica, which refuses a statement that writes with attempt to write a readonly database. The route handler therefore writes through the Azion API, with the database identifier and a personal token it reads from environment variables.
Prerequisites
- SQL Database enabled on your account, and the Edit SQL Database permission. The product is in Preview, so request access through Technical Support.
- A database and a table for the app to read. The examples use a database named
portal-appwhoseprojectstable is created withCREATE TABLE IF NOT EXISTS projects (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL);and holds one row,Customer portal. To create them, refer to Create a database using the API, Create a table using the API, and Insert rows. - The database identifier and a personal token stored as the environment variables
PORTAL_DB_IDandPORTAL_SQL_TOKEN, as Store the database identifier and the token shows. A variable reaches the function only after the next deploy, so create both before the repository is imported. - A GitHub repository with a Next.js project at its root, on a version Azion supports, imported with the Next.js preset. For the versions, refer to Next.js versions. To import the repository, refer to Import a project from GitHub.
The examples use app.example.com for the application’s domain. Replace it, and the names above, with your own values.
Render a page from the database rows
The page and the route handler both export dynamic = 'force-dynamic', so Next.js renders them on each request instead of once at build time, when the database is out of reach.
Add the page as app/page.js. It reads the rows through a read replica, with the Database class of the Azion.Sql global:
Database.open takes the database name and no token. Once the file is deployed, the page lists the rows of projects on every request.
The Deploy full-stack applications globally use case uses the values of this example.
Add rows from a route handler
Add the route handler as app/api/projects/route.js. It sends the insert as Write rows to SQL Database from a function describes, with PORTAL_DB_ID and PORTAL_SQL_TOKEN, and answers 500 on a failed request or a failed statement:
Commit both files to the repository’s default branch. The page lists the projects of portal-app on every request, and POST /api/projects adds one.
The Deploy full-stack applications globally use case uses the values of this example.
Confirm the page reads and the route writes
Each check requests the application on its domain. A location that does not have the application yet answers a 404 page that reads There's nothing here yet; wait a few minutes and retry.
-
The page renders from the database. Request the home page:
The HTML carries the row the table holds, in the list the page renders:
-
Build assets come from the bucket. Copy a URL under
/_next/static/from the page’s HTML and request it:The response carries
200, without the request reaching the function. -
A route writes to the database. Create a project:
ShellThe response carries
201and the ID the database assigned:A
500means the write failed. Read the line the route logged, as Troubleshoot function execution and logs shows:Azion API answered 401points at thePORTAL_SQL_TOKENvalue, and a database error string points at the statement. -
The page shows the write. Request the home page again. The list carries both projects.
-
A push deploys. Change the
<h1>text, commit, and push to the default branch. Request the home page after the deploy propagates. The HTML carries the new heading.
The page reads the table through a read replica, and the route handler writes to it through the Azion API.
These checks confirm the Deploy full-stack applications globally use case.