This tutorial is part of an upcoming series exploring caching mechanisms in Next.js 15. Stay tuned for the next installment!
Project Overview
In this tutorial, we’ll build a REST API for managing a directory of coffee shops. This backend will later serve as the foundation for a Next.js 15 frontend application, which we’ll cover in the next article of this series.Setting Up Your Development Environment
We can start by installing our requirements:php, composer, laravel CLI and the upsun CLI. We are using brew for MacOS here but I’m sure you will be able to translate this to other systems!
Bootstrapping Laravel
First, we’ll create a new Laravel project using the Laravel CLI. Then we’ll add Laravel Sail, which provides a Docker-based development environment with PHP, PostgreSQL, Redis, and other services pre-configured. This gives us a consistent and isolated development environment that mimics production (without being exactly the same).
And yes I made a typo on the video. Spelling coffee wrong. Shame. We will be using the correct spelling everywhere else!
Setting up local development
Update your.env file with your preferred settings and add the following hostnames to your /etc/hosts file for local development:
Let’s start everything!
Let’s start our Docker containers using Laravel Sail. This will spin up our development environment with PHP, PostgreSQL and other required services:Customizing our editor with rules
Before diving into the code, let’s configure our editor to follow Laravel best practices and coding standards. Create a new file called.cursorrules in your project root. This file will contain AI prompts that help Cursor understand Laravel conventions and provide better code suggestions.
You can find the recommended Laravel rules at cursorrule.com/posts/laravel-php-cursor-rules. Copy the content from there and paste it into your .cursorrules file.
These rules will ensure consistent code style, proper Laravel patterns, and helpful autocompletions as we build our API.
Creating our application
The Laravel API configuration
Let’s configure our application for API development. The following command will:- Install Laravel Sanctum for API authentication
- Set up API routing under the
/apiprefix - Configure the
routes/api.phpfile for our API endpoints - Add other API-related packages and configurations
Adding the model
Shop model by adding fields to the migration file. We’ll also specify which fields can be mass-assigned by adding them to the model’s $fillable property.
Let’s seed our database for testing
Let’s update ourDatabaseSeeder.php to generate some sample shop data using Laravel’s factory system:
HasFactory trait. Add this line at the top of your Shop model file:
Shop model. We’ll create a new ShopFactory class by extending Laravel’s base factory class and defining how to generate each field:
Let’s work on our controller
Now let’s update ourShopController to add the index and show methods that will handle our API endpoints:
paginate().
Creating the routes
Let’s define our API routes by adding the following code toroutes/api.php. These routes will handle GET requests for listing all shops and retrieving individual shop details:
Route::apiResource() helper instead, which would automatically define all RESTful routes (index, show, store, update, destroy) in a single line:
Let’s test
Let’s test our newly created API endpoints by making requests to both the collection endpoint/shops and the individual shop endpoint /shops/{id}. This will verify that our routes, controller methods, and resource transformations are working correctly:
Let’s deploy it!
Now that our REST API is fully functional with working endpoints, it’s time to deploy it to production on Upsun. Upsun will provide us with a scalable, managed hosting environment with built-in PostgreSQL and Redis support.First let’s create our Upsun project.
coffee-api folder, we’ll remove that first to avoid nested repositories.
[project id] with the ID from the previous step (project:create):
Creating the configuration
Before pushing our code to Upsun, we need to create a configuration file that defines our application’s infrastructure and deployment settings. This configuration will specify our PHP version, database requirements, and build/deploy processes. Create a new file called.upsun/config.yaml with the following configuration (explained below).
Because we are using PostgreSQL in our project, it is important to add
pdo and pdo_pgsql to our PHP extensions!.environment file in your project root with these essential configuration mappings:
Let’s push!
With our configuration files in place and environment variables set up, we can now deploy our Laravel application to Upsun. The platform will automatically build our application, install dependencies, and set up the required services:Let’s copy our data
If we test our API endpoint now, it will work but return empty results since database seeders don’t automatically run in production environments. We’ll need to populate our database with some initial data.shops table data or do a full database dump - both approaches will work. Let’s use our database GUI tool to export the data.
- Run
upsun db:sqlfor direct database access - Create local SSH tunnels to access both the database and cache services
- Host:
127.0.0.1 - Port:
30000 - Database:
main - Username:
main - Password:
main
INSERT queries to populate the remote database with our coffee shop data. After executing the queries, our remote API will have all the coffee shops available!
You can verify the data was copied successfully by checking the API response below:
Adding a domain
Now that our API is deployed and working, let’s make it accessible via a custom domain. This will give us a branded URL instead of the default Upsun hostname.upsun environment:info edge_hostname -p PROJECT_ID -e PRODUCTION_ENVIRONMENT:
Note: While Cloudflare supports CNAME flattening which allows using a CNAME for the root domain (
@), many DNS providers require using A records instead. Check your provider’s documentation for their specific requirements regarding root domain configuration.Final test!
Once your DNS changes propagate (which can take anywhere from a few minutes to 48 hours depending on your provider), Upsun will automatically provision and configure TLS certificates for your domain. If you’re using Cloudflare, you should be able to test the API endpoints immediately while waiting for DNS propagation:Summary
In this tutorial, we’ve accomplished several key objectives:- Set up a complete local development environment with PHP, Composer, and Laravel Sail
- Created a new Laravel REST API project from scratch
- Implemented API endpoints for managing coffee shop data
- Configured and deployed the application to Upsun
- Added a custom domain with SSL/TLS support
What’s Next?
This REST API serves as the foundation for our coffee shop directory application. In the next article of this series, we’ll build a modern frontend using Next.js 15 that consumes this API. We’ll explore:- Setting up a Next.js 15 project
- Implementing API integration
- Leveraging Next.js’s powerful caching mechanisms
- Deploying the frontend application