NextJS has built-in support for backend code and wow
CodeWithSwiz is a twice-a-week live show. Like a podcast with video and fun hacking. Focused on experiments. Join live Wednesdays and Sundays
In this episode of CodeWithSwiz, we tried NextJS's support for /api routes – code running on the backend.
Got that working, then my internet died. Couldn't finish the full objective of using an /api route to publish code to GitHub. 💩
Why NextJS /api routes are great
NextJS uses a special /pages/api
folder for routes running on the server. Both at compile-time and run-time. Always server side code.
Same file-based routing as your frontend code 👉 put a file there and it's available at <domain>/api/filename
. Export a default function from this file and that's your API controller.
// pages/api/publishArticle.js
export default async (req, res) => {
res.status(200).json({ success: true })
}
req
is the request object, res
is the response object. You read inputs from req
and return outputs by modifying res
.
You'll be familiar with this pattern, if you've used Express before. The most popular JavaScript backend framework, I believe.
Looks compatible with existing Express middlewares 🤘
Locally these routes work with your development server. Deploy to Vercel and they become cloud functions. AWS Lambdas (I assume) running on each API call. Haven't tried with Netlify.
In short, you get serverless without the pain 😍
How you can use /api to get things done
Unlike the traditional Express approach, NextJS forces you to use these routes as an API. They're meant to return data, not pages.
You want to have this discipline in your project as early as possible. Transitioning later when your team grows hurts. Been working on that transition at dayjob.exe and oof, hella gotchas 😅
On the stream, we created a React Query mutation running off a button click. It sends a POST request to our /api
route with the full article.
// components/ShipIt.js
export const ShipIt = ({ article }) => {
const [shipArticle, { status, isLoading }] = useMutation(async () => {
// makes a POST request to the server
return fetch("/api/publishArticle", {
method: "POST",
headers: {
// enables automatic body parsing
"Content-Type": "application/json",
},
body: JSON.stringify(article),
})
})
if (isLoading) {
return <Spinner></Spinner>
} else {
return <Button onClick={shipArticle}>Ship It</Button>
}
}
We set up a mutation, show a spinner when it's loading, and a button with a click handler otherwise. Click the button, call the shipArticle
method returned from useMutation
, execute the fetch()
call.
Setting the content-type header tells NextJS to parse POST body as a JSON string. Makes it easier to access values :)
// pages/api/publishArticle.js
export default async (req, res) => {
// req.body.title == article title
// req.body.description == article description
// etc
res.status(200).json({ success: true })
}
Tanner says we can share queries and mutations between frontend and backend. Gonna try that next time ✌️
Yes you can. https://t.co/4LTsY4B4gw
— Tanner Linsley (@tannerlinsley) September 13, 2020
Using GitHub's REST API to commit files
Original goal was to use an /api
route to publish an article. Since they're markdown files in a repo, that means using the GitHub API to make a commit.
We use the @octokit/rest library for that.
Runs in Node.js, which means it works with our NextJS server routes. But it's super complex and hard to figure out.
After much spelunking through the docs, we got an authenticated request working. It required a personal GitHub acces token added to .env.local
.
// pages/api/publishArticle.js
import { Octokit } from "@octokit/rest"
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
})
export default async (req, res) => {
const { data } = await octokit.request("/user")
// prints user info
console.log(data)
// ...
}
Instantiates Octokit with your token and requests /user
data. Makes the project hardcoded to you, but works. We'd have to add a full authentication system to let anyone else use this.
We figured out how to add files to repositories juuuuust as my internet died.
await octokit.repos.createOrUpdateFileContents
Join me Wednesday evening and we'll figure out the rest 🤞
Cheers,
~Swizec
PS: since this article was published, Gatsby added /api routes too 🥳
Continue reading about Why NextJS /api routes are fab – CodeWithSwiz 6
Semantically similar articles hand-picked by GPT-4
- Using JavaScript to commit to Github – CodeWithSwiz 7
- Your first NextJS app – CodeWithSwiz
- Building a small CMS with NextJS, pt2 – CodeWithSwiz
- Exploring NextJS with a headless CMS, pt4 – CodeWithSwiz
- Build simple backends with Gatsby Serverless Functions
Learned something new? Want to become a React expert?
Learning from tutorials is easy. You follow some steps, learn a smol lesson, and feel like you got dis 💪
Then comes the interview, a real world problem, or a question from the boss. Your mind goes blank. Shit, how does this work again ...
Happens to everyone. Building is harder than recognizing and the real world is a mess! Nothing fits in neat little boxes you learned about in tutorials.
That's where my emails come in – lessons from experience. Building production software :)
Leave your email and get the React email Series - a series of curated essays on building with React. Borne from experience, seasoned with over 12+ years of hands-on practice building the engineering side of growing SaaS companies.
Get Curated React Essays
Get a series of curated essays on React. Lessons and insights from building software for production. No bullshit.
Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.
Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.
Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.
Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev
Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization
Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections
Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog
Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com
By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️