Resource routes help organize API endpoints by grouping related actions for data in one place. This makes your API easier to understand and maintain.
Resource routes for APIs in Remix
export const loader = async ({ params }) => { /* handle GET request */ }; export const action = async ({ request, params }) => { /* handle POST, PUT, DELETE */ }; // File path example: app/routes/api/posts.ts
Resource routes in Remix use loader for GET requests and action for other HTTP methods.
File names and folder structure define the API route paths automatically.
loader handles GET requests to list all items in a resource.export const loader = async () => { return new Response(JSON.stringify({ message: 'List all items' }), { status: 200 }); };
action handles POST and DELETE requests for creating and deleting items.export const action = async ({ request }) => { if (request.method === 'POST') { // create new item return new Response('Created', { status: 201 }); } if (request.method === 'DELETE') { // delete item return new Response('Deleted', { status: 200 }); } };
// File structure example: // app/routes/api/posts.ts // handles /api/posts route with GET and POST // app/routes/api/posts/$postId.ts // handles /api/posts/:postId route with GET, PUT, DELETE
This example shows a simple resource route for posts. The loader returns all posts on GET requests. The action handles POST requests to add a new post.
import { json } from '@remix-run/node'; // app/routes/api/posts.ts let posts = [ { id: '1', title: 'First Post' }, { id: '2', title: 'Second Post' } ]; export const loader = async () => { return json(posts); }; export const action = async ({ request }) => { if (request.method === 'POST') { const formData = await request.formData(); const title = formData.get('title'); if (typeof title !== 'string' || !title) { return json({ error: 'Title is required' }, { status: 400 }); } const newPost = { id: String(posts.length + 1), title }; posts.push(newPost); return json(newPost, { status: 201 }); } return json({ error: 'Method not allowed' }, { status: 405 }); };
Remember to handle different HTTP methods inside the action function.
Use Remix's json helper to return JSON responses easily.
File and folder names define your API paths, so organize them clearly.
Resource routes group related API actions in one file using loader and action.
Remix uses file structure to map URLs to resource routes automatically.
This pattern keeps your API clean, consistent, and easy to maintain.
Practice
Solution
Step 1: Understand resource routes concept
Resource routes group related API actions such asloaderandactionin one file for better organization.Step 2: Eliminate incorrect options
Options describing only GET requests, separate files per endpoint, or client-side routes do not match the grouping feature.Final Answer:
To group related API actions likeloaderandactionin one file -> Option AQuick Check:
Resource routes group API actions like loader/action [OK]
- Thinking resource routes create separate files per endpoint
- Assuming resource routes handle only GET requests
- Confusing resource routes with client-side routing
Solution
Step 1: Identify Remix resource route file location
Remix maps resource routes insideapp/routesfolder, soapp/routes/api/posts.tsis correct.Step 2: Check for proper exports
Resource routes export bothloaderandactionto handle GET and POST (or other) requests in one file.Final Answer:
app/routes/api/posts.ts withloaderandactionexports -> Option BQuick Check:
Resource route file in app/routes with loader and action [OK]
- Placing API files outside app/routes folder
- Using separate files per HTTP method instead of one resource file
- Confusing client-side route files with API resource routes
app/routes/api/user.ts with these exports:export async function loader() { return new Response('User data') }
export async function action() { return new Response('User updated') }What response will a POST request to
/api/user return?Solution
Step 1: Identify HTTP method handling
Theloaderhandles GET requests, andactionhandles POST requests in Remix resource routes.Step 2: Match POST request to action response
A POST request to/api/usertriggers theactionfunction, which returns "User updated".Final Answer:
"User updated" -> Option DQuick Check:
POST request triggers action = "User updated" [OK]
- Confusing loader with action for POST requests
- Expecting 404 if action exists
- Thinking action is optional for POST
app/routes/api/item.ts with only a loader export. When you send a POST request to /api/item, what will happen?Solution
Step 1: Understand HTTP method handling in resource routes
In Remix,loaderhandles GET requests only. POST requests require anactionexport.Step 2: Check behavior when action is missing
Ifactionis missing, Remix responds with 405 Method Not Allowed for POST requests.Final Answer:
The server will respond with 405 Method Not Allowed -> Option AQuick Check:
Missing action for POST = 405 error [OK]
- Assuming POST calls loader
- Expecting 404 instead of 405
- Thinking server crashes without action
/api/products that supports GET, POST, and DELETE methods. How should you structure your Remix resource route file to handle all three methods correctly?Solution
Step 1: Understand Remix resource route method handling
Remix usesloaderfor GET requests andactionfor other HTTP methods like POST and DELETE.Step 2: Handle multiple methods in action
Insideaction, checkrequest.methodto differentiate POST and DELETE logic.Final Answer:
Export aloaderfor GET, anactionthat checksrequest.methodto handle POST and DELETE -> Option CQuick Check:
loader for GET, action handles POST/DELETE by method check [OK]
- Trying to create separate files per HTTP method
- Not checking request.method inside action
- Ignoring loader for GET requests
Ready to prove it?
Pass the test and this pattern moves unknown
