Hello World!
Now before you scoff and say, "What on Earth would you need a Harry Potter API for?" hear me out. We Potterheads love the intricate tapestry of spells, characters, houses, books, and movies. So, naturally, it got me thinking, "Wouldn't it be amazing to have an API that provides all this enchanting data?!"
3 days and almost 10 coffees later I have everything ready.
What we're building 🤔
Let's create an API that sends data about the following from the franchise:
- Characters
- Spells
- Houses
- Books
- Movies
At the end I'll also tell you why I had to bang my head on wall for a mistake 🤏 this big, that caused a bug on production.
Setting up the project
I used NextJS for this because that is my goto for every web development project.
Almost everyone knows how to setup a Nextjs project so I'm not explaining it however you can follow this if you don't know how to.
Next I stole open sourced data from KostaSav and Daniel. And put them inside a folder called db
inside project root.
Creating API Routes
In NextJS 13 the way API works has completely changed. In order to get APIs working follow the below steps:
- Inside the
app
dir create a folder calledapi
. Not necessarilyapi
you can also use your name for the folder and it will still work, unlike Next 12. But for simplicity we will useapi
. - Create a folder called
characters
and finally inside it create a file calledroute.ts
. Theroute.ts
will be the entry to the/api/characters
path. It is similar to whatindex.html
is (entry point). - Inside
characters
folder create another folder called[characters]
followed by anotherroute.ts
. This will catch all dynamic routes. e.g./api/characters/harry%20potter
- Repeat the above steps for
houses
,spells
,books
,movies
.
Next 13 APIs (Important)
For an API to work in Next 13 we need to follow this syntax:
// For GET requests
export async function GET() {
return new Response("Hello");
}
// For POST requests
export async function POST() {
return new Response("World");
}
// To get slug follow this
export async function GET(
{ params }: { params: { character: string } }
) {
const { character } = params;
return new Response(character);
}
Check out their documentation here.
Setting up the APIs
-
/api/characters
This route sends json containing data about characters from the Franchise. So we need to read the data from db/characters.json
, convert into a JSON string and send it.
import characters from "@/db/characters.json";
export async function GET() {
return new Response(JSON.stringify(characters), {
headers: { "content-type": "application/json" },
});
}
-
/api/characters/[character]
This is a bit complicated.
Dynamic Route which will send data about an individual character.
For this we need to get the slug from URL.
So if your folder is named [character]
, inside the GET
method you need to pass the following parameter:
import characters from "@/db/characters.json";
export async function GET(
{ params }: { params: { character: string } }
// I totally understand this line I swear
const { character } = params; // Ah finally the slug
)
Next we need to find the character from the slug in our JOSN file.
if (character) {
const characterString = characters.find(
(c) => c.name.toLowerCase() === character.toLowerCase()
);
if (characterString) {
return new Response(JSON.stringify(characterString), {
headers: { "content-type": "application/json" },
});
}
}
Finally if no such character exists in the database, return a message saying the same.
return new Response(`No character with name ${character}`);
So at the end your code will look somewhat like this:
import characters from "@/db/characters.json";
export async function GET(
request: Request,
{ params }: { params: { character: string } }
) {
const { character } = params;
if (character) {
const characterString = characters.find(
(c) => c.name.toLowerCase() === character.toLowerCase()
);
if (characterString) {
return new Response(JSON.stringify(characterString), {
headers: { "content-type": "application/json" },
});
}
}
return new Response(`No character with name ${character}`);
}
- Repeat the above steps for
houses
,spells
,books
,movies
.
The Error
And about the error I talked about in the first part...
So I used TailwindCSS for the frontend and for some reason it just wasn't working when pushed on Vercel. So I had to spend a good part of my day just to find out that my tailwind config had a misconfiguration. So basically I wrote components
instead of Components
😑.
Just 1 letter caused me so much trouble.
Finally...
This is just a quick rundown of a 4 days journey and around 10 cups coffee.
Please checkout the Live Demo and here is the Github Repo
If you enjoyed the API please give a 💖 and 🌟 the Github repo.
Top comments (10)
Seems like a classic 404 Not Found error. You can specify a status code for
Response
objects like this:If you don't specify a status code, it defaults to 200 OK, so consumers of your API won't be able to determine whether the request actually succeeded without parsing the response body (or worse, they'll have no way of determining success at all, in the case of a HEAD request).
Thanks for your input. I was in a hurry to just complete this project so I missed on these small details 😅.
I will update it for sure! Thanks!
hey you have done such a great work i am die heart fan of harry potter me and my dog with a cup of tea enjoyed this master piece alote.
glad to know! 😄
Thanks for building this and sharing👍🏾
Thanks for giving it a read 😀
This is awesome. This caught my eye as I really enjoy Harry Potter. Just 10 coffees though?!? Impressive haha
Haha thanks for giving it a read 💖
Thanks for the outline. Also, I've once also faced the same error.
Npm doesn't allow uppercase as naming convention.
Now I'm of to make an API for naruto.
Datte-byo!
Best of luck!