diff --git a/typescript/lunargame/client/package-lock.json b/typescript/lunargame/client/package-lock.json
index f8b6c64..75e6a1e 100644
--- a/typescript/lunargame/client/package-lock.json
+++ b/typescript/lunargame/client/package-lock.json
@@ -7546,6 +7546,28 @@
         }
       }
     },
+    "react": {
+      "version": "16.8.6",
+      "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz",
+      "integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==",
+      "requires": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "prop-types": "^15.6.2",
+        "scheduler": "^0.13.6"
+      }
+    },
+    "react-dom": {
+      "version": "16.8.6",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz",
+      "integrity": "sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==",
+      "requires": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "prop-types": "^15.6.2",
+        "scheduler": "^0.13.6"
+      }
+    },
     "react-event-listener": {
       "version": "0.6.6",
       "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.6.6.tgz",
@@ -7988,6 +8010,22 @@
         "aproba": "^1.1.1"
       }
     },
+    "rxjs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
+      "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "rxjs-hooks": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/rxjs-hooks/-/rxjs-hooks-0.5.1.tgz",
+      "integrity": "sha512-UVF2PH6PdzGr1FPgRljzNtOxu8Yt3J5S2cM2KCv6ZRs3E/XaRI7/qiQySZlp9YIMpFVOuYeJDHgePkSLatY22g==",
+      "requires": {
+        "tslib": "^1.9.3"
+      }
+    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -8154,6 +8192,15 @@
       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
       "dev": true
     },
+    "scheduler": {
+      "version": "0.13.6",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
+      "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
+      "requires": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1"
+      }
+    },
     "schema-utils": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -9234,8 +9281,7 @@
     "tslib": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-      "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
-      "dev": true
+      "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
     },
     "tty-browserify": {
       "version": "0.0.0",
diff --git a/typescript/lunargame/client/package.json b/typescript/lunargame/client/package.json
index 6e9fa65..814ca68 100644
--- a/typescript/lunargame/client/package.json
+++ b/typescript/lunargame/client/package.json
@@ -38,6 +38,10 @@
     "@material-ui/core": "^4.1.3",
     "@material-ui/icons": "^4.2.1",
     "@material-ui/styles": "^4.2.0",
-    "react-router-dom": "^5.0.1"
+    "react": "^16.8.6",
+    "react-dom": "^16.8.6",
+    "react-router-dom": "^5.0.1",
+    "rxjs": "^6.5.2",
+    "rxjs-hooks": "^0.5.1"
   }
 }
diff --git a/typescript/lunargame/client/src/common/dom/classes/InfiniteList.ts b/typescript/lunargame/client/src/common/dom/classes/InfiniteList.ts
new file mode 100644
index 0000000..0cb0729
--- /dev/null
+++ b/typescript/lunargame/client/src/common/dom/classes/InfiniteList.ts
@@ -0,0 +1,65 @@
+import { cacheInstances } from '../../lang/objects/decorators/cacheInstances'
+import { BehaviorSubject } from 'rxjs'
+import { BaseServer } from '../../../modules/network/classes/BaseServer'
+
+export interface InfiniteListConfig {
+    urls: {
+        chunk: string
+        count: string
+    }
+    pageSize: number
+    initialLoads?: number
+}
+
+@cacheInstances(1)
+export class InfiniteList<T> {
+    private static server = new BaseServer()
+
+    private count = 0
+    private page = 0
+
+    public elements = new Set<T>()
+    public refresh = new BehaviorSubject(0)
+    public ready = new BehaviorSubject(false)
+
+    constructor(public name: string, private config: InfiniteListConfig) {}
+
+    async init() {
+        this.count = await InfiniteList.server.request(this.config.urls.count)
+
+        this.ready.next(true)
+        this.update()
+
+        for (let index = 0; index < this.config.initialLoads; index++) {
+            this.loadChunk()
+        }
+    }
+
+    async loadChunk() {
+        if (this.elements.size >= this.count) return
+
+        const chunk = await InfiniteList.server.request<T[]>(
+            this.config.urls.chunk,
+            'GET',
+            {},
+            {
+                page: this.page++,
+                pageSize: this.config.pageSize
+            }
+        )
+
+        for (const element of chunk) {
+            this.elements.add(element)
+        }
+
+        this.update()
+    }
+
+    private update() {
+        this.refresh.next(this.refresh.value + 1)
+    }
+
+    get data() {
+        return Array.from(this.elements.values())
+    }
+}
diff --git a/typescript/lunargame/client/src/common/dom/forms/helpers/createFormModal.tsx b/typescript/lunargame/client/src/common/dom/forms/helpers/createFormModal.tsx
index 42b2189..c8b727d 100644
--- a/typescript/lunargame/client/src/common/dom/forms/helpers/createFormModal.tsx
+++ b/typescript/lunargame/client/src/common/dom/forms/helpers/createFormModal.tsx
@@ -22,19 +22,35 @@ export interface ModalProps {
     onClose: Function
 }
 
+export interface FormModalOptions {
+    title: string
+    description: string
+    url: string
+    fields: TextFieldData[]
+    onSubmit: (data: unknown) => void
+}
+
+export const defaultFormModalOptions: FormModalOptions = {
+    title: 'Mymodal',
+    description: 'This is a modal',
+    url: '',
+    fields: [],
+    onSubmit: () => {}
+}
+
 const useStyles = makeStyles((theme: Theme) => ({
     field: {
         marginTop: theme.spacing(2)
     }
 }))
 
-export const createFormModal = (
-    title: string,
-    description: string,
-    url: string,
-    fields: TextFieldData[],
-    onSubmit?: (data: unknown) => void
-) => {
+export const createFormModal = (options: Partial<FormModalOptions> = {}) => {
+    // This merges all options
+    const { fields, title, description, onSubmit, url } = {
+        ...defaultFormModalOptions,
+        ...options
+    }
+
     const formFields = fields.map(
         field =>
             new FormField(
@@ -54,7 +70,7 @@ export const createFormModal = (
             props.onClose(event)
         }
 
-        const classes = useStyles()
+        const classes = useStyles(props)
 
         const textFields = fields.map((field, index) => {
             const fieldObject = formFields[index]
diff --git a/typescript/lunargame/client/src/modules/account/components/LoginModal.ts b/typescript/lunargame/client/src/modules/account/components/LoginModal.ts
index 33cf9d1..cd66637 100644
--- a/typescript/lunargame/client/src/modules/account/components/LoginModal.ts
+++ b/typescript/lunargame/client/src/modules/account/components/LoginModal.ts
@@ -6,11 +6,11 @@ import {
 import { Account } from '../../network/types/Account'
 import { updateAccount } from '../../helpers/updateAccount'
 
-export const LoginModal = createFormModal(
-    'Login',
-    `To subscribe to this website, please enter you r email address here. We will send updates occasionally.`,
-    'auth/login',
-    [
+export const LoginModal = createFormModal({
+    title: 'Login',
+    description: `To subscribe to this website, please enter you r email address here. We will send updates occasionally.`,
+    url: 'auth/login',
+    fields: [
         {
             name: 'email',
             type: 'email',
@@ -22,5 +22,5 @@ export const LoginModal = createFormModal(
             validators: passwordValidatorList()
         }
     ],
-    updateAccount
-)
+    onSubmit: updateAccount
+})
diff --git a/typescript/lunargame/client/src/modules/account/components/SignupModal.ts b/typescript/lunargame/client/src/modules/account/components/SignupModal.ts
index 3041a0b..cf150b8 100644
--- a/typescript/lunargame/client/src/modules/account/components/SignupModal.ts
+++ b/typescript/lunargame/client/src/modules/account/components/SignupModal.ts
@@ -10,11 +10,11 @@ import { DialogManager } from '../../../common/dom/dialogs/classes/DialogManager
 
 const dialogManager = new DialogManager()
 
-export const SignupModal = createFormModal(
-    'Signup',
-    `To create an account you need to provide an username, email and a password.`,
-    'auth/create',
-    [
+export const SignupModal = createFormModal({
+    title: 'Signup',
+    description: `To create an account you need to provide an username, email and a password.`,
+    url: 'auth/create',
+    fields: [
         {
             name: 'name',
             type: 'text',
@@ -31,7 +31,7 @@ export const SignupModal = createFormModal(
             validators: passwordValidatorList()
         }
     ],
-    (data: Account) => {
+    onSubmit: (data: Account) => {
         updateAccount(data)
         dialogManager.add({
             title: 'Email verification',
@@ -41,4 +41,4 @@ export const SignupModal = createFormModal(
             onClose: () => {}
         })
     }
-)
+})
diff --git a/typescript/lunargame/client/src/modules/core/components/Body.tsx b/typescript/lunargame/client/src/modules/core/components/Body.tsx
index 890b5b6..99fcaea 100644
--- a/typescript/lunargame/client/src/modules/core/components/Body.tsx
+++ b/typescript/lunargame/client/src/modules/core/components/Body.tsx
@@ -5,7 +5,8 @@ import { Route } from 'react-router-dom'
 
 const useStyles = makeStyles({
     root: {
-        padding: '5%'
+        height: '90vh',
+        display: 'block'
     }
 })
 
diff --git a/typescript/lunargame/client/src/modules/core/components/SidebarRouteData.tsx b/typescript/lunargame/client/src/modules/core/components/SidebarRouteData.tsx
index 4393b30..5b20048 100644
--- a/typescript/lunargame/client/src/modules/core/components/SidebarRouteData.tsx
+++ b/typescript/lunargame/client/src/modules/core/components/SidebarRouteData.tsx
@@ -1,7 +1,9 @@
 import React from 'react'
 import HomeIcon from '@material-ui/icons/Home'
+import GamesIcon from '@material-ui/icons/Games'
 import { Route } from '../types/Route'
 import { Home } from './Home'
+import { Games } from '../../games/components/GamePage'
 
 export const routes: Route[] = [
     {
@@ -11,13 +13,9 @@ export const routes: Route[] = [
         icon: <HomeIcon />
     },
     {
-        name: 'about',
-        url: '/about',
-        content: () => (
-            <>
-                <h1>This is the about component</h1>
-            </>
-        ),
-        icon: <HomeIcon />
+        name: 'games',
+        url: '/games',
+        content: Games,
+        icon: <GamesIcon />
     }
 ]
diff --git a/typescript/lunargame/client/src/modules/core/styles/mixins/maxSize.scss b/typescript/lunargame/client/src/modules/core/styles/mixins/maxSize.scss
new file mode 100644
index 0000000..6f1e10f
--- /dev/null
+++ b/typescript/lunargame/client/src/modules/core/styles/mixins/maxSize.scss
@@ -0,0 +1,5 @@
+@mixin maxSize {
+    width: 100%;
+    height: 100%;
+    display: block;
+}
diff --git a/typescript/lunargame/client/src/modules/core/styles/reset.scss b/typescript/lunargame/client/src/modules/core/styles/reset.scss
index 829396f..f1f84c7 100644
--- a/typescript/lunargame/client/src/modules/core/styles/reset.scss
+++ b/typescript/lunargame/client/src/modules/core/styles/reset.scss
@@ -449,3 +449,8 @@ a {
     text-decoration: none;
     color: inherit;
 }
+
+html,
+body {
+    overflow: hidden;
+}
diff --git a/typescript/lunargame/client/src/modules/core/types/Route.ts b/typescript/lunargame/client/src/modules/core/types/Route.ts
index 568bff8..67a36a9 100644
--- a/typescript/lunargame/client/src/modules/core/types/Route.ts
+++ b/typescript/lunargame/client/src/modules/core/types/Route.ts
@@ -1,10 +1,8 @@
 import React, { Component } from 'react'
 
-export type acceptedContent = React.ComponentElement<unknown, Component>
-
 export interface Route {
     name: string
     url: string
-    content: () => acceptedContent
-    icon: acceptedContent
+    content: (props: unknown) => JSX.Element
+    icon: JSX.Element
 }
diff --git a/typescript/lunargame/client/src/modules/games/components/GameListItem.scss b/typescript/lunargame/client/src/modules/games/components/GameListItem.scss
new file mode 100644
index 0000000..34b64bd
--- /dev/null
+++ b/typescript/lunargame/client/src/modules/games/components/GameListItem.scss
@@ -0,0 +1,16 @@
+@import '../../core/styles/mixins/maxSize.scss';
+
+.gameListItemContainer {
+    padding: 2%;
+}
+
+.gameListItem {
+    background-position: center;
+    background-size: cover;
+    background-repeat: no-repeat;
+}
+
+.gameListItem,
+.gameListItemContainer {
+    @include maxSize();
+}
diff --git a/typescript/lunargame/client/src/modules/games/components/GameListItem.tsx b/typescript/lunargame/client/src/modules/games/components/GameListItem.tsx
new file mode 100644
index 0000000..106e1fc
--- /dev/null
+++ b/typescript/lunargame/client/src/modules/games/components/GameListItem.tsx
@@ -0,0 +1,15 @@
+import React, { CSSProperties } from 'react'
+import './GameListItem.scss'
+import { GameChunkElementData } from '../../network/types/GameChunkElementData'
+
+export const GameListItem = (props: { game: GameChunkElementData }) => {
+    const styles: CSSProperties = {
+        backgroundImage: `url(${props.game.thumbail})`
+    }
+
+    return (
+        <div className="gameListItemContainer">
+            <div className="gameListItem" style={styles} />
+        </div>
+    )
+}
diff --git a/typescript/lunargame/client/src/modules/games/components/GamePage.scss b/typescript/lunargame/client/src/modules/games/components/GamePage.scss
new file mode 100644
index 0000000..6005f76
--- /dev/null
+++ b/typescript/lunargame/client/src/modules/games/components/GamePage.scss
@@ -0,0 +1,25 @@
+.gameListContainer {
+    overflow-y: scroll;
+    height: 100%;
+    display: block;
+    padding: 5vw;
+}
+
+.gameListContainer > .gameListGrid {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
+    grid-auto-rows: 1fr;
+}
+
+.gameListGrid::before {
+    content: '';
+    width: 0;
+    padding-bottom: 100%;
+    grid-row: 1 / 1;
+    grid-column: 1 / 1;
+}
+
+.gameListGrid > *:first-child {
+    grid-row: 1 / 1;
+    grid-column: 1 / 1;
+}
diff --git a/typescript/lunargame/client/src/modules/games/components/GamePage.tsx b/typescript/lunargame/client/src/modules/games/components/GamePage.tsx
new file mode 100644
index 0000000..4d86455
--- /dev/null
+++ b/typescript/lunargame/client/src/modules/games/components/GamePage.tsx
@@ -0,0 +1,37 @@
+import React, { UIEvent } from 'react'
+import './GamePage.scss'
+import { useObservable } from 'rxjs-hooks'
+import { GameInfiniteList } from '../constants'
+import { GameListItem } from './GameListItem'
+
+export const Games = () => {
+    useObservable(() => GameInfiniteList.refresh)
+
+    const ready = useObservable(() => GameInfiniteList.ready)
+
+    if (!ready) {
+        return <h1>Loading...</h1>
+    }
+
+    const handleScroll = (e: UIEvent<HTMLDivElement>) => {
+        const element = e.target as HTMLDivElement
+
+        if (
+            element.scrollHeight - element.scrollTop <
+            element.clientHeight + 50
+        ) {
+            GameInfiniteList.loadChunk()
+            e.preventDefault()
+        }
+    }
+
+    return (
+        <div onScroll={handleScroll} className="gameListContainer">
+            <div className="gameListGrid">
+                {GameInfiniteList.data.map(game => (
+                    <GameListItem key={game.id} game={game} />
+                ))}
+            </div>
+        </div>
+    )
+}
diff --git a/typescript/lunargame/client/src/modules/games/constants.ts b/typescript/lunargame/client/src/modules/games/constants.ts
new file mode 100644
index 0000000..acc22ad
--- /dev/null
+++ b/typescript/lunargame/client/src/modules/games/constants.ts
@@ -0,0 +1,14 @@
+import { InfiniteList } from '../../common/dom/classes/InfiniteList'
+import { GameChunkElementData } from '../network/types/GameChunkElementData'
+
+export const GameInfiniteList = new InfiniteList<GameChunkElementData>(
+    'gameList',
+    {
+        pageSize: 5,
+        urls: {
+            chunk: 'game/chunk',
+            count: 'game/count'
+        },
+        initialLoads: 6
+    }
+)
diff --git a/typescript/lunargame/client/src/modules/network/classes/BaseServer.ts b/typescript/lunargame/client/src/modules/network/classes/BaseServer.ts
index b9c4844..ee72452 100644
--- a/typescript/lunargame/client/src/modules/network/classes/BaseServer.ts
+++ b/typescript/lunargame/client/src/modules/network/classes/BaseServer.ts
@@ -26,14 +26,22 @@ export class BaseServer {
     public async request<T>(
         url: string,
         method = 'GET',
-        body = {}
+        body = {},
+        queryParams: Record<string, string | number> = {}
     ): Promise<T> {
         const noBody = ['GET', 'DELETE']
+        const useBody = noBody.indexOf(method) === -1
 
-        const response = await fetch(`${this.path}/${url}`, {
-            ...(noBody.indexOf(method) === -1
-                ? { body: JSON.stringify(body) }
-                : {}),
+        const params = Object.keys(queryParams).map(
+            key => `${key}=${queryParams[key]}`
+        )
+
+        const finalUrl = `${this.path}/${url}${
+            params.length ? '?' : ''
+        }${params.join('&')}`
+
+        const response = await fetch(finalUrl, {
+            ...(useBody ? { body: JSON.stringify(body) } : {}),
             headers: {
                 Accept: 'application/json',
                 'Content-Type': 'application/json',
@@ -42,6 +50,7 @@ export class BaseServer {
             method,
             credentials: 'include'
         })
+
         const parsed: Response<T> = await response.json()
         const status = response.status
 
diff --git a/typescript/lunargame/client/src/modules/network/types/GameChunkElementData.ts b/typescript/lunargame/client/src/modules/network/types/GameChunkElementData.ts
new file mode 100644
index 0000000..7c5a83c
--- /dev/null
+++ b/typescript/lunargame/client/src/modules/network/types/GameChunkElementData.ts
@@ -0,0 +1,5 @@
+export interface GameChunkElementData {
+    id: string
+    thumbail: string
+    avatar: string
+}