Backend Time – Building a Simple Node.js API for Your Flutter App
Now that we’ve set up a slick-looking Flutter frontend, it’s time to power it with a backend. In this tutorial, we’ll be diving into the world of Node.js to create a simple API that your Flutter app can interact with. Don’t worry—it’s simpler than you think. By the end of this, you’ll have a basic REST API up and running, able to handle requests and communicate with a database (we’ll be using MongoDB).
REST API: The Menu for Your App
Before we dive into code, let’s talk about what a REST API is and why you need one. Imagine a restaurant. You (the customer) ask the waiter (the API) for a dish from the menu (the data). The waiter runs back to the kitchen (Node.js), grabs the dish, and brings it to your table (your Flutter app). Simple, right?
That’s basically what a REST API does—it allows your app to request specific data (like a menu item), and the backend delivers it. It works with standard HTTP methods (GET, POST, PUT, DELETE) that correspond to the four main things you might want to do with data:
- GET: Retrieve data (like ordering a dish from the menu).
- POST: Send data (like leaving a review for the dish you just ate).
- PUT: Update data (like changing the toppings on a pizza).
- DELETE: Remove data (like canceling your order).
Now that we know what REST is, let’s start building our own API using Node.js and Express.
Setting Up a Node.js Project with Express
Step 1: Install Node.js and Create a New Project
If you haven’t already installed Node.js, follow these steps:
-
Download and install Node.js from https://nodejs.org/. Make sure you’re downloading the LTS version (Long Term Support). You’ll also get npm (Node Package Manager) installed with it, which is what we’ll use to manage packages in our project.
-
Once installed, open your terminal or command prompt. Navigate to the directory where you want to create your project and run the following command to initialize a new Node.js project:
mkdir flutter-node-backend cd flutter-node-backend npm init -y
This command will create a new directory and initialize a
package.json
file, which keeps track of your project’s dependencies and scripts.
Step 2: Install Express
Now, let’s install Express, a minimal and flexible Node.js framework that’s going to make building our API a breeze. If Node.js is the foundation of our app, Express is the speedy construction team that gets everything up and running quickly.
Run this command to install Express:
npm install express
Step 3: Create the Server
Now, let’s get our server up and running. Create a new file called server.js
in your project’s root directory. Open the file and add this code:
const express = require('express');
const app = express();
const PORT = 3000;
app.use(express.json());
// Basic route
app.get('/', (req, res) => {
res.send('Hello, Flutter!');
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Here’s what this does:
express()
: This is our Express app, which handles all the incoming requests.app.use(express.json())
: This line tells Express to automatically parse incoming JSON requests so we can access the data inreq.body
.app.get('/')
: This is a simple route that sends back a message, "Hello, Flutter!", when you visit the root URL.app.listen(PORT, () => {...})
: This starts the server on port 3000 and logs a message to the console when the server is running.
Step 4: Run the Server
In your terminal, run this command to start the server:
node server.js
Now, open your browser and go to http://localhost:3000. You should see the message “Hello, Flutter!” on the screen.
Congratulations, you just created your first Node.js server! But this is just the beginning—let’s move on to creating some more useful routes.
Creating Routes for the API
In a real-world app, your API will have multiple routes to handle different types of requests (GET, POST, PUT, DELETE). Let’s build out these routes in our server.js
file.
Step 1: Create a GET Route
Let’s start with a simple GET route to fetch some data. Add this code under your root route (app.get('/')
):
let users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
// Get all users
app.get('/users', (req, res) => {
res.json(users);
});
This route will return a list of users in JSON format when you visit /users
. It’s like asking the kitchen for the full menu, and it delivers the list of dishes (users).
Step 2: Create a POST Route
Next, let’s create a POST route to add a new user. This is where you’ll send data to the server (like adding a new dish to the menu).
// Add a new user
app.post('/users', (req, res) => {
const newUser = {
id: users.length + 1,
name: req.body.name,
};
users.push(newUser);
res.status(201).json(newUser);
});
In this route, we’re adding a new user to the users
array. We’re also using res.status(201)
to indicate that the request was successful and a new resource was created.
Step 3: Create a PUT Route
The PUT method is used to update an existing resource. Let’s add a route that lets us update a user’s name.
// Update a user's name
app.put('/users/:id', (req, res) => {
const userId = parseInt(req.params.id);
const user = users.find(u => u.id === userId);
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
user.name = req.body.name;
res.json(user);
});
This route takes an id
parameter from the URL (using req.params.id
), finds the corresponding user, and updates their name.
Step 4: Create a DELETE Route
Finally, let’s create a DELETE route to remove a user from the array.
// Delete a user
app.delete('/users/:id', (req, res) => {
const userId = parseInt(req.params.id);
users = users.filter(u => u.id !== userId);
res.status(204).send(); // No content, just confirms deletion
});
This route finds the user by their id
and removes them from the users
array. The res.status(204)
sends a “No Content” response, which is a standard way to confirm that something was successfully deleted without returning any data.
Connecting to a Database (MongoDB)
Right now, we’re storing users in a simple array, which works for small-scale stuff. But in a real app, you’ll need a more reliable way to store data. Enter MongoDB, a NoSQL database that stores data in flexible, JSON-like documents.
Step 1: Install MongoDB and Mongoose
To use MongoDB in our app, we need to install a library called Mongoose, which makes it easier to interact with MongoDB. First, install the necessary packages:
npm install mongoose
Step 2: Connect to MongoDB
Next, let’s connect our app to a MongoDB database. Add this code at the top of your server.js
file:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/flutter-node-db', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('Connected to MongoDB');
});
This code connects your app to a local MongoDB database called flutter-node-db
. If you’re using MongoDB Atlas (the cloud version), you’ll replace localhost
with your connection string.
Step 3: Create a Mongoose Model
Let’s define a User model using Mongoose. A model is a way to define the structure of your data. Create a new file called models/User.js
and add this code:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
});
module.exports = mongoose.model('User', userSchema);
This schema defines a user with just one field, name
, which is a required string.
Step 4: Update Routes to Use MongoDB
Now, let’s update our routes to interact with MongoDB instead of the users
array. Replace your GET
and POST
routes in server.js
with this:
const User = require('./models/User');
// Get all users
app.get('/users', async (req, res) => {
const users = await User.find();
res.json(users);
});
// Add a new user
app.post('/users', async (req, res) => {
const newUser = new User({ name: req.body.name });
await newUser.save();
res.status(201).json(newUser);
});
We’ve swapped out the array for MongoDB. Now, when you add a user, it’s saved to the database, and when you fetch users, you get them from the database instead of the array.
Testing the API
Before we wrap up, it’s important to test the API to make sure everything works as expected. You can use Postman or curl for this.
Here’s how to test the GET route with curl
:
curl http://localhost:3000/users
For the POST route:
curl -X POST -H "Content-Type: application/json" -d '{"name": "Dave"}' http://localhost:3000/users
You should see your new user added to the database!
By now, you should have a fully functioning Node.js backend with a simple API that your Flutter app can communicate with.