Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1f24600
chore: clean the repo
DNR500 Jun 19, 2025
7281b11
chore: establish project
DNR500 Jun 21, 2025
77729b8
feat: add api endpoints
DNR500 Jun 22, 2025
b5f1ce8
feat: create base pages and a simple layout
DNR500 Jun 22, 2025
6e6bf34
feat: seach page set up and working
DNR500 Jun 25, 2025
8a70a29
feat: wire up the movei details page
DNR500 Jun 25, 2025
364397b
feat: component appearance and adaption
DNR500 Jun 25, 2025
650481a
test: adding some tests around the HomeSearchSection page
DNR500 Jun 26, 2025
79e2c16
fix: scroll jumping
DNR500 Jun 26, 2025
cd0e94e
refactor: endpoints using common code
DNR500 Jun 26, 2025
348d5ab
docs: update README
DNR500 Jun 26, 2025
2070e51
feat: introduce browser history and some fixes
DNR500 Jun 26, 2025
b1a2ed6
feat: use react page title and cache server pages
DNR500 Jun 29, 2025
e579454
refactor: simlify Movie Details page
DNR500 Jul 1, 2025
7fe74cc
feat: accessiblity improvements
DNR500 Jul 1, 2025
d1f172e
feat: add storybook
DNR500 Jul 2, 2025
8e658bf
chore: add storybook and test pagination
DNR500 Jul 3, 2025
be32126
feat: README update, slug improvement
DNR500 Jul 3, 2025
0ab0fdb
feat: image url changes to the search and movie details endpoints
DNR500 Jul 4, 2025
d6feae7
feat: create picture elements for image data
DNR500 Jul 4, 2025
afaf74b
refactor: responsive image files
DNR500 Jul 5, 2025
f3ff198
feat: updates to layout
DNR500 Jul 5, 2025
4b6d464
feat: layout improvements
DNR500 Jul 6, 2025
05cfab2
feat: improve screen reader experience
DNR500 Jul 7, 2025
fecdfdc
doc: add more storybook files and tests
DNR500 Jul 12, 2025
aa15444
feat: add return to page position to search
DNR500 Jul 13, 2025
683172e
chore: minor improvements
DNR500 Jul 13, 2025
c24f5bb
docs: docs updates and some testing changes
DNR500 Jul 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 44 additions & 23 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,23 +1,44 @@
!.gitkeep
!.gitignore
!*.dll
[Oo]bj
[Bb]in
*.user
*.suo
*.[Cc]ache
*.bak
*.ncb
*.DS_Store
*.userprefs
*.iml
*.ncrunch*
.*crunch*.local.xml
.idea
[Tt]humbs.db
*.tgz
*.sublime-*

node_modules
bower_components
npm-debug.log
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

*storybook.log
storybook-static
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
Binary file added .storybook/assets/default-w185.webp
Binary file not shown.
Binary file added .storybook/assets/default.webp
Binary file not shown.
Binary file added .storybook/assets/lg-w500.webp
Binary file not shown.
Binary file added .storybook/assets/md.webp
Binary file not shown.
Binary file added .storybook/assets/sm-w342.webp
Binary file not shown.
Binary file added .storybook/assets/sm.webp
Binary file not shown.
12 changes: 12 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/nextjs-vite';

const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: ['@storybook/addon-docs', '@storybook/addon-a11y', '@storybook/addon-viewport'],
framework: {
name: '@storybook/nextjs-vite',
options: {},
},
staticDirs: ['../public'],
};
export default config;
25 changes: 25 additions & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { Preview } from '@storybook/nextjs-vite';
import '../src/app/globals.css';
import { viewports } from './viewports';

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},

a11y: {
test: 'todo',
},

viewport: {
options: viewports,
defaultViewport: 'responsive',
},
},
};

export default preview;
50 changes: 50 additions & 0 deletions .storybook/viewports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { MINIMAL_VIEWPORTS } from 'storybook/viewport';

export const viewports = {
...MINIMAL_VIEWPORTS,
xs: {
name: 'xs (360px)',
styles: { width: '360px', height: '100%' },
type: 'mobile',
},
xsLargest: {
name: 'xs (639px)',
styles: { width: '639px', height: '100%' },
type: 'mobile',
},
sm: {
name: 'sm (640px)',
styles: { width: '640px', height: '100%' },
type: 'mobile',
},
smLargest: {
name: 'sm (767px)',
styles: { width: '767px', height: '100%' },
type: 'mobile',
},
md: {
name: 'md (768px)',
styles: { width: '768px', height: '100%' },
type: 'tablet',
},
mdLargest: {
name: 'md (1023px)',
styles: { width: '1023px', height: '100%' },
type: 'tablet',
},
lg: {
name: 'lg (1024px)',
styles: { width: '1024px', height: '100%' },
type: 'desktop',
},
xl: {
name: 'xl (1280px)',
styles: { width: '1280px', height: '100%' },
type: 'desktop',
},
'2xl': {
name: '2xl (1536px)',
styles: { width: '1536px', height: '100%' },
type: 'desktop',
},
};
7 changes: 7 additions & 0 deletions .storybook/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
import { setProjectAnnotations } from '@storybook/nextjs-vite';
import * as projectAnnotations from './preview';

// This is an important step to apply the right configuration when testing your stories.
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);
142 changes: 142 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Movie App Next.js

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

### Setup your env file

You will need to obtain an access token from TMDB - https://www.themoviedb.org/settings/api.

You can sign up and create an account if you don't already have one.

You will need your API Read Access Token. Then create a file in the root folder of this project called `.env.local`.

It should look like the following. Add your token

```bash
# api code
MOVIE_DB_ACCESS_TOKEN=YOUR-TOKEN-HERE
MOVIES_SEARCH_REVALIDATE=300
MOVIES_DETAIL_REVALIDATE=3600
MOVIES_CONFIGURATION_REVALIDATE=7200

# server side page component code
SEARCH_REVALIDATE_TIME=300
MOVIE_REVALIDATE_TIME=3600

# client side code
NEXT_PUBLIC_CLIENT_SIDE_SEARCH_REVALIDATE_TIME=300
NEXT_PUBLIC_CLIENT_SIDE_MOVIE_REVALIDATE_TIME=3600

# current domain
NEXT_PUBLIC_SITE_URL=http://localhost:3000
```

The project uses npm. Run the follow to get set up.

```
npm i
```

### Production build of the app

To see the app running optimally you can do a production build of the app and see that working locally.

```bash
npm run build
npm run start
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

I would advise testing with the production build and using an incognito browser window.

### Local development run

To benefit from hot reloading while working on the app you can run..

```bash
npm run dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

There is also a Storybook set up

```bash
npm run storybook
```

It will run on http://localhost:6006/

This will allow you to look at and work on specific components in isolation

### Dev scripts

See the scripts section of the package.json for scripts

```bash
npm run lint
npm run test
npm run typecheck
```
### Code formating
The project uses eslint and prettier to manage code format

## Technical Decisions

### General approach

The basic idea here was to first build a working skeleton for the whole app and then be able to drill in to
parts of the code later to make improvements and enhance and improve the experience. I have been very constrained
in terms of time available to work on this so I aimed to get something that I could demo. There are lots of improvements
that I would make and certainly in terms of process I would probably work a bit differently if I was doing this for my day job.


### Why use Next.js

I prefer to keep API keys and Access Tokens server side where possible.

This is more secure and prevents malicious usage and also where services might be rate limited helps to protect our usage of external systems like TMDB.

Next.js has the ability to set up backend api endpoints easily and also gives you the benefit of Next.js caching to optimise performance.

So it made sense to establish BFF for the frontend app.

### Site structure and caching strategy

You can find information about this on the [Site Structure Overview document](../docs/site-structure-and-caching.md)


### SSR Hydration Pattern with Tanstack Query

For the search page we are using the SSR Hydration Pattern with Tanstack Query - you can read more about this in the
[SSR Hydration Pattern with Tanstack Query document](../docs/hydration-pattern-with-tanstack-query.md)

### Styling

I have used frameworks like styled components and emotion on projects before but know from experience that these
frameworks don't always work so nicely with Next.js and the App router. I decided to use Tailwind Css as I have worked a little
with that before and it works well with App router in Next. Also Tailwind Css comes with a pre-made theme that gives some nice options for color palettes
and spacing tokens that are very useful.

### General Tests

Most of the components and pages currently have unit tests, some tests would still be good for some of the utils in our lib folder

### Future improvements

- Additional error handling on the home page
- Add husky to get checks running on push
- Set up a pipeline using github actions and establish a live environment
- Functional tests

### What I would have done differently

I haven't actually worked much with Tanstack Query hydration in the past. I would probably
want to do a spike of that before committing to doing it with production code. Because I'm doing this in my free time
I thought that try this new approach would make the challenge a bit more interesting for myself.

I've focused on creating a small subset of components to show that I can work with basic HTML and think about semantic markup, but I would
normally consider adopting a component library such as shadcn/ui for some of the basic components.
Loading