In this test you will have to consume from https://swapi.dev https://swapi.info, a free API related to a beloved entertainment franchise, in order to show two views:
- A planets view where you list the planet name and the names of the Star Wars films where they appear.
- Single planet view where you show all the information of a given planet.
These are the steps I took:
- I used the boilerplate setup from React Router to get started quickly
- I added linting and prettier early, to make sure the code style is consistent
- I focused on the basic routing and functionality first, without styling
- I added tests early: Cypress tests for user interaction and Storybook for components
- I used Tailwind to style the app. A full component library, like ChakraUI, would have also been a good option
- I added React Query (the lastest version is called TanStack Query) so I could improve the way planets and films are fetched
- I noticed the app was getting bigger, so I renamed and reorganised some files
- I added a loader skeleton with Reacts Suspense, because I wanted to try that out :)
- I implemented a general approach for displaying the resource url values (films and people)
I have used React and eslint often before, but my previous projects were not on the latest verion. This project gave me the opportunity to try out some new features, like Suspense. React Router has also changed quite a bit since I last used it. I have learned the new way to set up the routes and some new possibilities, like clientLoader.
React Query was new to me; I'm quite happy with what it offers. It makes sure that e.g. the films on the planet overview page are not fetched a zilion times, each is fetched just once.
For smaller apps, Storybook doesn't add that much value initially. If components are only used one way in your application, you can also test them in your application. However, in a larger app, Storybook gives you an overview of what is already present in your app. When visual regression tests and/or snapshot tests are set up, it can ensure that the component don't change accidentally when you are working on something else. Adding stories after the fact is less effective, so I have already added a few of them now, even though the app is still quite small.
Tests are awesome when you run them. I ran mine locally, often enough, but it would be better to have an automated test flow so you don't forget. Same for linting and prettier.
Set up visual regression tests or snapshot tests in Storybook.
Showing a list of 60 items is not ideal. This could be improved by
- pagination
- filter and sorting options
- a fun extra: a button to explore a random planet
Some more base components could probably be extracted for reuse. However, I feel this becomes more useful when you have at least one other place where you would like to use that component.
The UrlItem component doesn't quite feel like a component, maybe it needs to be a hook? But it also returns jsx, so I'm not quite sure where it belongs.
Install the dependencies:
npm install
Start the development server with HMR:
npm run dev
Your application will be available at http://localhost:5173
.
Make sure you have the application up and running on port 5173
Then start Cypress UI like this
npm run cypress
Or, alternatively, you can run it headless. This is faster, but you cannot follow along
npm run test:cypress
You can open Storybook and see all stories by running
npm run storybook
Run the automatic accessibility tests by running
npm run test:storybook
Create a production build:
npm run build
To build and run using Docker:
docker build -t my-app .
# Run the container
docker run -p 3000:3000 my-app
The containerized application can be deployed to any platform that supports Docker, including:
- AWS ECS
- Google Cloud Run
- Azure Container Apps
- Digital Ocean App Platform
- Fly.io
- Railway
If you're familiar with deploying Node applications, the built-in app server is production-ready.
Make sure to deploy the output of npm run build
├── package.json
├── package-lock.json (or pnpm-lock.yaml, or bun.lockb)
├── build/
│ ├── client/ # Static assets
│ └── server/ # Server-side code
Built with ❤️ using React Router. (Leia icons created by pocike - Flaticon)[https://www.flaticon.com/free-icons/leia]