diff --git a/.vscode/settings.json b/.vscode/settings.json
index 896cb9470959cc24e9d343173561d9d728f3b206..d98ed346857ad58d2b4422a2764fcc38485c1fe3 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -22,6 +22,7 @@
     "eslint.options": {
         "configFile":"./.eslintrc"
     },
+    "prettier.configPath": "./client/.prettierrc",
     //git
     "git.ignoreLimitWarning": true,
     //language specific
diff --git a/client/.eslintrc b/client/.eslintrc
index 46369ae68df115758c772580e6f148f3956380a8..7e2cadb0f5dc6cbde1bcb39b5382f7f88f349dde 100644
--- a/client/.eslintrc
+++ b/client/.eslintrc
@@ -1,57 +1,26 @@
 {
-    "env": {
-        "browser": true,
-        "es6": true,
-        "node": true
-    },
-    "parser": "@typescript-eslint/parser",
-    "parserOptions": {
-        "ecmaFeatures": {
-            "jsx": true
-        },
-        "project": [
-            "tsconfig.json"
-        ],
-        "ecmaVersion": 2021,
-        "sourceType": "module"
-    },
-    "settings": {
-        "react": {
-            "version": "detect"
-        }
-    },
-    "extends": [
-        "airbnb-typescript",
-        "plugin:@typescript-eslint/recommended",
-        "plugin:react/recommended",
-        "prettier/@typescript-eslint",
-        "plugin:prettier/recommended"
-    ],
-    "rules": {
-        
-        "semi": "off",
-        "react/jsx-one-expression-per-line": "off",
-
-        "prettier/prettier": [
-            "error",
-            {
-                "endOfLine": "auto"
-            }
-        ],
-        "jsx-a11y/label-has-associated-control": [
-            2,
-            {
-                "labelComponents": [
-                    "CustomInputLabel"
-                ],
-                "labelAttributes": [
-                    "label"
-                ],
-                "controlComponents": [
-                    "CustomInput"
-                ],
-                "depth": 3
-            }
-        ]
+  "parser": "@typescript-eslint/parser",
+  "parserOptions": {
+      "sourceType": "module",
+      "project": [
+        "tsconfig.json"
+      ]
+  },
+  "ecmaFeatures": {
+    "jsx": true
+  },
+  "settings": {
+    "react": {
+      "version": "detect"
     }
+  },
+  "extends": [
+      "plugin:react/recommended",
+      "plugin:@typescript-eslint/recommended",
+      "prettier/@typescript-eslint",
+      "plugin:prettier/recommended"
+  ],
+  "rules": {
+    "prettier/prettier": ["warn"]
+  }
 }
\ No newline at end of file
diff --git a/client/.prettierrc b/client/.prettierrc
index 0cc6d643f022f337aea01cf93a3eb4d23b6cb136..4ff5f098aabbbd3a4fe56615df8a56dad7ef48bc 100644
--- a/client/.prettierrc
+++ b/client/.prettierrc
@@ -1,7 +1,8 @@
 {
-    "semi": false,
-    "trailingComma": "none",
-    "singleQuote": true,
-    "printWidth": 80,
-    "endOfLine": "lf"
-  }
\ No newline at end of file
+  "semi": false,
+  "trailingComma": "es5",
+  "singleQuote": true,
+  "printWidth": 120,
+  "tabWidth": 2,
+  "endOfLine": "lf"
+}
diff --git a/client/src/App.tsx b/client/src/App.tsx
index 1e8c051e2d67e0a74f4ef26ab737a7427cf23b52..c488843cc955c038ec74ccd1bf6b1c9e9def4a5f 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -1,15 +1,24 @@
+import { createMuiTheme, ThemeProvider } from '@material-ui/core'
 import React from 'react'
 import './App.css'
 import Main from './Main'
 
+const theme = createMuiTheme({
+  palette: {
+    primary: {
+      // Purple and green play nicely together.
+      main: '#6200EE',
+    },
+  },
+})
+
 const App: React.FC = () => {
   return (
     <div className="wrapper">
-      <link
-        rel="stylesheet"
-        href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
-      />
-      <Main />
+      <ThemeProvider theme={theme}>
+        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
+        <Main />
+      </ThemeProvider>
     </div>
   )
 }
diff --git a/client/src/Main.tsx b/client/src/Main.tsx
index a44422fdc2886602b51f32c09c3a11c3fca3a8b7..5ad533a6203b5dc1399fa89381bb13d3a35180a6 100644
--- a/client/src/Main.tsx
+++ b/client/src/Main.tsx
@@ -1,14 +1,24 @@
 import React from 'react'
 import { BrowserRouter, Route, Switch } from 'react-router-dom'
-import AdminView from './components/AdminView'
-import LoginForm from './components/Login'
+import AdminPage from './pages/admin/AdminPage'
+import LoginPage from './pages/login/LoginPage'
+import PresentationEditorPage from './pages/presentationEditor/PresentationEditorPage'
+import AudienceViewPage from './pages/views/AudienceViewPage'
+import JudgeViewPage from './pages/views/JudgeViewPage'
+import ParticipantViewPage from './pages/views/ParticipantViewPage'
+import ViewSelectPage from './pages/views/ViewSelectPage'
 
 const Main = () => {
   return (
     <BrowserRouter>
       <Switch>
-        <Route exact path="/" component={LoginForm} />
-        <Route path="/admin" component={AdminView} />
+        <Route exact path="/" component={LoginPage} />
+        <Route path="/admin" component={AdminPage} />
+        <Route path="/competition-id=:id" component={PresentationEditorPage} />
+        <Route exact path="/view" component={ViewSelectPage} />
+        <Route exact path="/view/participant" component={ParticipantViewPage} />
+        <Route exact path="/view/judge" component={JudgeViewPage} />
+        <Route exact path="/view/audience" component={AudienceViewPage} />
       </Switch>
     </BrowserRouter>
   )
diff --git a/client/src/components/CompetitionManager.tsx b/client/src/components/CompetitionManager.tsx
deleted file mode 100644
index 2d140fa35968cb8b227e5802b426fea7ce4bb144..0000000000000000000000000000000000000000
--- a/client/src/components/CompetitionManager.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Typography } from '@material-ui/core'
-import React from 'react'
-
-const CompetitionManager: React.FC = (props) => {
-  return (
-    <Typography variant="h1" noWrap>
-      Tävlingshanterare
-    </Typography>
-  )
-}
-
-export default CompetitionManager
diff --git a/client/src/components/Login.tsx b/client/src/components/Login.tsx
deleted file mode 100644
index 91af9b78d06d4bdde2d1b42939bad82fe0f1c968..0000000000000000000000000000000000000000
--- a/client/src/components/Login.tsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import { Button, TextField } from '@material-ui/core'
-import { withStyles } from '@material-ui/core/styles'
-import { Alert, AlertTitle } from '@material-ui/lab'
-import axios from 'axios'
-import { Formik, FormikHelpers } from 'formik'
-import React, { useState } from 'react'
-import * as Yup from 'yup'
-import { LoginModel } from '../interfaces/models'
-import './Login.css'
-
-const styles = {}
-
-interface LoginState {
-  status: number
-  message: string
-}
-
-interface LoginFormModel {
-  model: LoginModel
-  error?: string
-}
-
-interface ServerResponse {
-  code: number
-  message: string
-}
-
-const schema: Yup.SchemaOf<LoginFormModel> = Yup.object({
-  model: Yup.object()
-    .shape({
-      email: Yup.string().email('Email inte giltig').required('Email krävs'),
-      password: Yup.string()
-        .required('Lösenord krävs')
-        .min(6, 'Lösenord måste vara minst 6 karaktärer')
-    })
-    .required(),
-  error: Yup.string().optional()
-})
-
-const handleSubmit = async (
-  values: LoginFormModel,
-  actions: FormikHelpers<LoginFormModel>
-) => {
-  await axios
-    .post<ServerResponse>(`users/login`, values.model)
-    .then((res) => {
-      actions.resetForm()
-    })
-    .catch(({ response }) => {
-      actions.setFieldError('error', response.data.message)
-    })
-    .finally(() => {
-      actions.setSubmitting(false)
-    })
-}
-
-const LoginForm: React.FC = (props) => {
-  const [serverState, setServerState] = useState<LoginFormModel>()
-  const initialValues: LoginFormModel = { model: { email: '', password: '' } }
-  return (
-    <div className="login-page">
-      <Formik
-        initialValues={initialValues}
-        validationSchema={schema}
-        onSubmit={handleSubmit}
-      >
-        {(formik) => (
-          <form onSubmit={formik.handleSubmit} className="login-form">
-            <TextField
-              label="Email Adress"
-              name="model.email"
-              helperText={
-                formik.touched.model?.email ? formik.errors.model?.email : ''
-              }
-              error={Boolean(formik.errors.model?.email)}
-              onChange={formik.handleChange}
-              onBlur={formik.handleBlur}
-              margin="normal"
-            />
-            <TextField
-              label="Lösenord"
-              name="model.password"
-              type="password"
-              helperText={
-                formik.touched.model?.password
-                  ? formik.errors.model?.password
-                  : ''
-              }
-              error={Boolean(formik.errors.model?.password)}
-              onChange={formik.handleChange}
-              onBlur={formik.handleBlur}
-              margin="normal"
-            />
-            <Button
-              type="submit"
-              fullWidth
-              variant="contained"
-              color="primary"
-              disabled={!formik.isValid}
-            >
-              Submit
-            </Button>
-            {formik.errors.error ? (
-              <Alert severity="error">
-                <AlertTitle>Error</AlertTitle>
-                {formik.errors.error}
-              </Alert>
-            ) : (
-              <div />
-            )}
-          </form>
-        )}
-      </Formik>
-    </div>
-  )
-}
-
-export default withStyles(styles)(LoginForm)
diff --git a/client/src/index.css b/client/src/index.css
index ec2585e8c0bb8188184ed1e0703c4c8f2a8419b0..7323ae85c542d8da74f197f1395de258e8a4c673 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -1,13 +1,11 @@
 body {
   margin: 0;
-  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
-    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
-    sans-serif;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
+    'Droid Sans', 'Helvetica Neue', sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
 }
 
 code {
-  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
-    monospace;
+  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
 }
diff --git a/client/src/interfaces/models.ts b/client/src/interfaces/models.ts
index 292554f4ac8c62b8525f679c3d127accea65752e..f2bc0b12cf3151d9fde320d2a981a88859f664b1 100644
--- a/client/src/interfaces/models.ts
+++ b/client/src/interfaces/models.ts
@@ -1,4 +1,8 @@
-export interface LoginModel {
+export interface AccountLoginModel {
   email: string
   password: string
 }
+
+export interface CompetitionLoginModel {
+  code: string
+}
diff --git a/client/src/components/AdminView.css b/client/src/pages/admin/AdminPage.css
similarity index 56%
rename from client/src/components/AdminView.css
rename to client/src/pages/admin/AdminPage.css
index 1ad0b7ee6dd4647d7f8f7d07b6853ed5ceac4026..471dc7d3d7a3b865f32c4e0d99b9bba73df2c5cb 100644
--- a/client/src/components/AdminView.css
+++ b/client/src/pages/admin/AdminPage.css
@@ -1,10 +1,9 @@
 .background {
-  background: linear-gradient(to top, #efd5ff 0%, #3d55b3 100%);
   height: 100%;
 }
 
 .top-bar {
-  display:flex;
+  display: flex;
   justify-content: space-between;
   align-items: flex-start;
-}
\ No newline at end of file
+}
diff --git a/client/src/components/AdminView.test.tsx b/client/src/pages/admin/AdminPage.test.tsx
similarity index 79%
rename from client/src/components/AdminView.test.tsx
rename to client/src/pages/admin/AdminPage.test.tsx
index cdc460499c777bd4ee6a456b93d751272e98ebeb..b29b78f82bb88d7489a9a09ef071693acbfde654 100644
--- a/client/src/components/AdminView.test.tsx
+++ b/client/src/pages/admin/AdminPage.test.tsx
@@ -1,12 +1,12 @@
 import { render } from '@testing-library/react'
 import React from 'react'
 import { BrowserRouter } from 'react-router-dom'
-import AdminView from './AdminView'
+import AdminPage from './AdminPage'
 
 it('renders admin view', () => {
   render(
     <BrowserRouter>
-      <AdminView />
+      <AdminPage />
     </BrowserRouter>
   )
 })
diff --git a/client/src/components/AdminView.tsx b/client/src/pages/admin/AdminPage.tsx
similarity index 79%
rename from client/src/components/AdminView.tsx
rename to client/src/pages/admin/AdminPage.tsx
index 54551b640789e676461065c686d424bafa290efd..a95bf04ee0c8c50e298c859e345a153d93ce6d8a 100644
--- a/client/src/components/AdminView.tsx
+++ b/client/src/pages/admin/AdminPage.tsx
@@ -9,16 +9,16 @@ import {
   ListItemIcon,
   ListItemText,
   Toolbar,
-  Typography
+  Typography,
 } from '@material-ui/core'
 import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
 import DashboardIcon from '@material-ui/icons/Dashboard'
 import MailIcon from '@material-ui/icons/Mail'
 import React from 'react'
 import { Link, Route, Switch, useRouteMatch } from 'react-router-dom'
-import './AdminView.css'
-import CompetitionManager from './CompetitionManager'
-import Regions from './Regions'
+import './AdminPage.css'
+import CompetitionManager from './components/CompetitionManager'
+import Regions from './components/Regions'
 
 const drawerWidth = 240
 const menuItems = ['Startsida', 'Regioner', 'Användare', 'Tävlingshanterare']
@@ -26,36 +26,34 @@ const menuItems = ['Startsida', 'Regioner', 'Användare', 'Tävlingshanterare']
 const useStyles = makeStyles((theme: Theme) =>
   createStyles({
     root: {
-      display: 'flex'
+      display: 'flex',
     },
     appBar: {
       width: `calc(100% - ${drawerWidth}px)`,
-      marginLeft: drawerWidth
+      marginLeft: drawerWidth,
     },
     drawer: {
       width: drawerWidth,
       flexShrink: 0,
-      marginRight: drawerWidth
+      marginRight: drawerWidth,
     },
     drawerPaper: {
-      width: drawerWidth
+      width: drawerWidth,
     },
     // necessary for content to be below app bar
     toolbar: theme.mixins.toolbar,
     content: {
       flexGrow: 1,
       backgroundColor: theme.palette.background.default,
-      paddingLeft: theme.spacing(30)
-    }
+      paddingLeft: theme.spacing(30),
+    },
   })
 )
 
 const AdminView: React.FC = (props) => {
   const classes = useStyles()
   const [openIndex, setOpenIndex] = React.useState(0)
-  const match = useRouteMatch()
-  console.log(match)
-  const { path, url } = match
+  const { path, url } = useRouteMatch()
   return (
     <div className={classes.root}>
       <CssBaseline />
@@ -70,7 +68,7 @@ const AdminView: React.FC = (props) => {
         className={(classes.drawer, 'background')}
         variant="permanent"
         classes={{
-          paper: classes.drawerPaper
+          paper: classes.drawerPaper,
         }}
         anchor="left"
       >
@@ -87,9 +85,7 @@ const AdminView: React.FC = (props) => {
                 selected={index === openIndex}
                 onClick={() => setOpenIndex(index)}
               >
-                <ListItemIcon>
-                  {text === 'Dashboard' ? <DashboardIcon /> : <MailIcon />}
-                </ListItemIcon>
+                <ListItemIcon>{index === 0 ? <DashboardIcon /> : <MailIcon />}</ListItemIcon>
                 <ListItemText primary={text} />
               </ListItem>
             ))}
@@ -97,14 +93,7 @@ const AdminView: React.FC = (props) => {
           <Divider />
           <List>
             <ListItem>
-              <Button
-                component={Link}
-                to="/"
-                type="submit"
-                fullWidth
-                variant="contained"
-                color="primary"
-              >
+              <Button component={Link} to="/" type="submit" fullWidth variant="contained" color="primary">
                 Logga ut
               </Button>
             </ListItem>
diff --git a/client/src/pages/admin/components/CompetitionManager.css b/client/src/pages/admin/components/CompetitionManager.css
new file mode 100644
index 0000000000000000000000000000000000000000..716dde28317c6d6da62f3ddcb72021cec5d31ed8
--- /dev/null
+++ b/client/src/pages/admin/components/CompetitionManager.css
@@ -0,0 +1,13 @@
+.top-bar {
+  display: flex;
+  justify-content: space-between;
+  align-items:flex-end;
+}
+
+.new-competition-button {
+  margin-bottom: 8px !important;
+}
+
+.remove-competition {
+  color:red !important;
+}
\ No newline at end of file
diff --git a/client/src/components/CompetitionManager.test.tsx b/client/src/pages/admin/components/CompetitionManager.test.tsx
similarity index 56%
rename from client/src/components/CompetitionManager.test.tsx
rename to client/src/pages/admin/components/CompetitionManager.test.tsx
index b7156f680329a98c468dfa3a751448191a8b088b..2a92138fe288429a93c9a2d015af2d08cf93f58f 100644
--- a/client/src/components/CompetitionManager.test.tsx
+++ b/client/src/pages/admin/components/CompetitionManager.test.tsx
@@ -1,7 +1,12 @@
 import { render } from '@testing-library/react'
 import React from 'react'
+import { BrowserRouter } from 'react-router-dom'
 import CompetitionManager from './CompetitionManager'
 
 it('renders competition manager', () => {
-  render(<CompetitionManager />)
+  render(
+    <BrowserRouter>
+      <CompetitionManager />
+    </BrowserRouter>
+  )
 })
diff --git a/client/src/pages/admin/components/CompetitionManager.tsx b/client/src/pages/admin/components/CompetitionManager.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b2a717e30fe5b0595f6ebb3143387988a9476d7b
--- /dev/null
+++ b/client/src/pages/admin/components/CompetitionManager.tsx
@@ -0,0 +1,206 @@
+import { Button, Menu } from '@material-ui/core'
+import FormControl from '@material-ui/core/FormControl'
+import InputBase from '@material-ui/core/InputBase'
+import InputLabel from '@material-ui/core/InputLabel'
+import MenuItem from '@material-ui/core/MenuItem'
+import Paper from '@material-ui/core/Paper'
+import Select from '@material-ui/core/Select'
+import { createStyles, makeStyles, Theme, withStyles } from '@material-ui/core/styles'
+import Table from '@material-ui/core/Table'
+import TableBody from '@material-ui/core/TableBody'
+import TableCell from '@material-ui/core/TableCell'
+import TableContainer from '@material-ui/core/TableContainer'
+import TableHead from '@material-ui/core/TableHead'
+import TableRow from '@material-ui/core/TableRow'
+import MoreHorizIcon from '@material-ui/icons/MoreHoriz'
+import React from 'react'
+import { Link } from 'react-router-dom'
+import './CompetitionManager.css'
+
+const BootstrapInput = withStyles((theme: Theme) =>
+  createStyles({
+    root: {
+      'label + &': {
+        marginTop: theme.spacing(3),
+      },
+    },
+    input: {
+      borderRadius: 4,
+      position: 'relative',
+      backgroundColor: theme.palette.background.paper,
+      border: '1px solid #ced4da',
+      fontSize: 16,
+      padding: '10px 26px 10px 12px',
+      transition: theme.transitions.create(['border-color', 'box-shadow']),
+      '&:focus': {
+        borderRadius: 4,
+        borderColor: '#80bdff',
+        boxShadow: '0 0 0 0.2rem rgba(0,123,255,.25)',
+      },
+    },
+  })
+)(InputBase)
+
+function createCompetition(name: string, region: string, year: number, id: number) {
+  return { name, region, year, id }
+}
+
+const competitions = [
+  createCompetition('Tävling 1', 'Stockholm', 2021, 1),
+  createCompetition('Tävling 2', 'Stockholm', 2020, 2),
+  createCompetition('Tävling 3', 'Sala', 2020, 3),
+  createCompetition('Tävling 4', 'Sundsvall', 2020, 4),
+  createCompetition('Tävling 5', 'Linköping', 2020, 5),
+  createCompetition('Tävling 6', 'Linköping', 2020, 6),
+  createCompetition('Tävling 7', 'Sala', 2019, 7),
+  createCompetition('Tävling 8', 'Stockholm', 2019, 8),
+  createCompetition('Tävling 9', 'Stockholm', 2019, 9),
+  createCompetition('Tävling 10', 'Lidköping', 2019, 10),
+  createCompetition('Tävling 11', 'Stockholm', 2019, 11),
+  createCompetition('Tävling 12', 'Sala', 2018, 12),
+  createCompetition('Tävling 13', 'Tornby', 2018, 13),
+]
+
+const regions = competitions
+  .map((competition) => competition.region)
+  .filter((competition, index, self) => self.indexOf(competition) === index)
+
+const years = competitions
+  .map((competition) => competition.year)
+  .filter((competition, index, self) => self.indexOf(competition) === index)
+
+const useStyles = makeStyles((theme: Theme) =>
+  createStyles({
+    table: {
+      width: 1500, // TODO: Shrink table when smaller screen
+    },
+    margin: {
+      margin: theme.spacing(1),
+    },
+  })
+)
+
+const CompetitionManager: React.FC = (props) => {
+  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
+  const classes = useStyles()
+  const yearInitialValue = 0
+  const regionInitialValue = ''
+  const noFilterText = 'Alla'
+  const [searchInput, setSearchInput] = React.useState('')
+  const [year, setYear] = React.useState(yearInitialValue)
+  const [region, setRegion] = React.useState(regionInitialValue)
+  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
+    setAnchorEl(event.currentTarget)
+  }
+
+  const handleClose = () => {
+    setAnchorEl(null)
+  }
+
+  const onSearchChange = (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
+    setSearchInput(event.target.value)
+  }
+
+  return (
+    <div>
+      <div className="top-bar">
+        <div>
+          <FormControl className={classes.margin}>
+            <InputLabel shrink id="demo-customized-textbox">
+              Sök
+            </InputLabel>
+            <BootstrapInput id="demo-customized-textbox" onChange={onSearchChange} />
+          </FormControl>
+          <FormControl className={classes.margin}>
+            <InputLabel shrink id="demo-customized-select-native">
+              Region
+            </InputLabel>
+            <Select
+              labelId="demo-customized-select-label"
+              id="demo-customized-select"
+              value={region === regionInitialValue ? noFilterText : region}
+              input={<BootstrapInput />}
+            >
+              <MenuItem value={noFilterText} onClick={() => setRegion(regionInitialValue)}>
+                {noFilterText}
+              </MenuItem>
+              {regions.map((text, index) => (
+                <MenuItem key={text} value={text} onClick={() => setRegion(text)}>
+                  {text}
+                </MenuItem>
+              ))}
+            </Select>
+          </FormControl>
+          <FormControl className={classes.margin}>
+            <InputLabel shrink id="demo-customized-select-label">
+              År
+            </InputLabel>
+            <Select
+              id="demo-customized-select"
+              value={year === yearInitialValue ? noFilterText : year}
+              input={<BootstrapInput />}
+            >
+              <MenuItem value={noFilterText} onClick={() => setYear(yearInitialValue)}>
+                {noFilterText}
+              </MenuItem>
+              {years.map((year, index) => (
+                <MenuItem key={year} value={year} onClick={() => setYear(year)}>
+                  {year}
+                </MenuItem>
+              ))}
+            </Select>
+          </FormControl>
+        </div>
+        <Button color="secondary" variant="contained" className="new-competition-button">
+          Ny Tävling
+        </Button>
+      </div>
+      <TableContainer component={Paper}>
+        <Table className={classes.table} aria-label="simple table">
+          <TableHead>
+            <TableRow>
+              <TableCell>Namn</TableCell>
+              <TableCell align="right">Region</TableCell>
+              <TableCell align="right">År</TableCell>
+              <TableCell align="right"></TableCell>
+            </TableRow>
+          </TableHead>
+          <TableBody>
+            {competitions
+              .filter((row) => {
+                const nameOkay = row.name.match(RegExp(searchInput, 'i')) //Makes sure name matches search input case insensitively
+                const yearOkay = year == yearInitialValue || row.year == year
+                const regionOkay = region == regionInitialValue || row.region == region
+                return yearOkay && regionOkay && nameOkay
+              })
+              .map((row) => (
+                <TableRow key={row.name}>
+                  <TableCell scope="row">
+                    <Button color="primary" component={Link} to={`/competition-id=${row.id}`}>
+                      {row.name}
+                    </Button>
+                  </TableCell>
+                  <TableCell align="right">{row.region}</TableCell>
+                  <TableCell align="right">{row.year}</TableCell>
+                  <TableCell align="right">
+                    <Button onClick={handleClick}>
+                      <MoreHorizIcon />
+                    </Button>
+                  </TableCell>
+                </TableRow>
+              ))}
+          </TableBody>
+        </Table>
+      </TableContainer>
+      <Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}>
+        <MenuItem onClick={handleClose}>Starta</MenuItem>
+        <MenuItem onClick={handleClose}>Duplicera</MenuItem>
+        <MenuItem className="remove-competition" onClick={handleClose}>
+          Ta bort
+        </MenuItem>
+      </Menu>
+    </div>
+  )
+}
+
+export default CompetitionManager
diff --git a/client/src/components/Regions.test.tsx b/client/src/pages/admin/components/Regions.test.tsx
similarity index 100%
rename from client/src/components/Regions.test.tsx
rename to client/src/pages/admin/components/Regions.test.tsx
diff --git a/client/src/components/Regions.tsx b/client/src/pages/admin/components/Regions.tsx
similarity index 100%
rename from client/src/components/Regions.tsx
rename to client/src/pages/admin/components/Regions.tsx
diff --git a/client/src/components/Login.css b/client/src/pages/login/LoginPage.css
similarity index 75%
rename from client/src/components/Login.css
rename to client/src/pages/login/LoginPage.css
index 5a01047d29ff819bb1581e3434f2509620ab6aed..abefd48f971cdf9fdf2f072a552aaaf6a7b18713 100644
--- a/client/src/components/Login.css
+++ b/client/src/pages/login/LoginPage.css
@@ -1,10 +1,11 @@
 .login-page {
   display: flex;
+  height: 100%;
   justify-content: center;
+  align-items: center;
 }
 
 .login-form {
   display: flex;
   flex-direction: column;
-  width: 250px;
 }
diff --git a/client/src/components/Login.test.tsx b/client/src/pages/login/LoginPage.test.tsx
similarity index 64%
rename from client/src/components/Login.test.tsx
rename to client/src/pages/login/LoginPage.test.tsx
index 12a6c79c133e96598a6e583ddcbd555e1799df97..ae41ba025840c938774f018789438941ba368cdc 100644
--- a/client/src/components/Login.test.tsx
+++ b/client/src/pages/login/LoginPage.test.tsx
@@ -1,7 +1,7 @@
 import { render } from '@testing-library/react'
 import React from 'react'
-import LoginForm from './Login'
+import LoginPage from './LoginPage'
 
 it('renders login form', () => {
-  render(<LoginForm />)
+  render(<LoginPage />)
 })
diff --git a/client/src/pages/login/LoginPage.tsx b/client/src/pages/login/LoginPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..776e64b1b9582ddbd000470d63089994144d8777
--- /dev/null
+++ b/client/src/pages/login/LoginPage.tsx
@@ -0,0 +1,44 @@
+import { AppBar, Tab, Tabs } from '@material-ui/core'
+import { makeStyles, Theme } from '@material-ui/core/styles'
+import React from 'react'
+import AdminLogin from './components/AdminLogin'
+import CompetitionLogin from './components/CompetitionLogin'
+import './LoginPage.css'
+
+interface TabPanelProps {
+  activeTab: number
+}
+
+function LoginContent(props: TabPanelProps) {
+  const { activeTab } = props
+  if (activeTab === 0) {
+    return <AdminLogin />
+  }
+  return <CompetitionLogin />
+}
+
+const useStyles = makeStyles((theme: Theme) => ({
+  root: {
+    backgroundColor: theme.palette.background.paper,
+  },
+}))
+
+const LoginPage: React.FC = (props) => {
+  const classes = useStyles()
+  const [loginTab, setLoginTab] = React.useState(0)
+  return (
+    <div className="login-page">
+      <div className={classes.root}>
+        <AppBar position="static">
+          <Tabs value={loginTab} onChange={(event, selectedTab) => setLoginTab(selectedTab)}>
+            <Tab label="Konto" id="simple-tab-0" />
+            <Tab label="Tävling" id="simple-tab-1" />
+          </Tabs>
+        </AppBar>
+        <LoginContent activeTab={loginTab} />
+      </div>
+    </div>
+  )
+}
+
+export default LoginPage
diff --git a/client/src/pages/login/components/AdminLogin.test.tsx b/client/src/pages/login/components/AdminLogin.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4e966c895cd9deee7b738b6eaee9e979e60ddf0d
--- /dev/null
+++ b/client/src/pages/login/components/AdminLogin.test.tsx
@@ -0,0 +1,7 @@
+import { render } from '@testing-library/react'
+import React from 'react'
+import AdminLogin from './AdminLogin'
+
+it('renders admin login', () => {
+  render(<AdminLogin />)
+})
diff --git a/client/src/pages/login/components/AdminLogin.tsx b/client/src/pages/login/components/AdminLogin.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..77dc2a4ccd1d500221cb4c5a3ce0f3a2972dbb7d
--- /dev/null
+++ b/client/src/pages/login/components/AdminLogin.tsx
@@ -0,0 +1,94 @@
+import { Button, TextField } from '@material-ui/core'
+import { Alert, AlertTitle } from '@material-ui/lab'
+import axios from 'axios'
+import { Formik, FormikHelpers } from 'formik'
+import React from 'react'
+import * as Yup from 'yup'
+import { AccountLoginModel } from '../../../interfaces/models'
+
+interface AccountLoginFormModel {
+  model: AccountLoginModel
+  error?: string
+}
+
+interface ServerResponse {
+  code: number
+  message: string
+}
+
+const accountSchema: Yup.SchemaOf<AccountLoginFormModel> = Yup.object({
+  model: Yup.object()
+    .shape({
+      email: Yup.string().email('Email inte giltig').required('Email krävs'),
+      password: Yup.string().required('Lösenord krävs').min(6, 'Lösenord måste vara minst 6 tecken'),
+    })
+    .required(),
+  error: Yup.string().optional(),
+})
+
+const handleAccountSubmit = async (values: AccountLoginFormModel, actions: FormikHelpers<AccountLoginFormModel>) => {
+  await axios
+    .post<ServerResponse>(`users/login`, values.model)
+    .then((res) => {
+      actions.resetForm()
+    })
+    .catch(({ response }) => {
+      console.log(response.data.message)
+      actions.setFieldError('error', response.data.message)
+    })
+    .finally(() => {
+      actions.setSubmitting(false)
+    })
+}
+
+const AdminLogin: React.FC = (props) => {
+  const accountInitialValues: AccountLoginFormModel = {
+    model: { email: '', password: '' },
+  }
+  return (
+    <Formik initialValues={accountInitialValues} validationSchema={accountSchema} onSubmit={handleAccountSubmit}>
+      {(formik) => (
+        <form onSubmit={formik.handleSubmit} className="login-form">
+          <TextField
+            label="Email Adress"
+            name="model.email"
+            helperText={formik.touched.model?.email ? formik.errors.model?.email : ''}
+            error={Boolean(formik.touched.model?.email && formik.errors.model?.email)}
+            onChange={formik.handleChange}
+            onBlur={formik.handleBlur}
+            margin="normal"
+          />
+          <TextField
+            label="Lösenord"
+            name="model.password"
+            type="password"
+            helperText={formik.touched.model?.password ? formik.errors.model?.password : ''}
+            error={Boolean(formik.touched.model?.password && formik.errors.model?.password)}
+            onChange={formik.handleChange}
+            onBlur={formik.handleBlur}
+            margin="normal"
+          />
+          <Button
+            type="submit"
+            fullWidth
+            variant="contained"
+            color="primary"
+            disabled={!formik.isValid || !formik.touched.model?.email || !formik.touched.model?.email}
+          >
+            Logga in
+          </Button>
+          {formik.errors.error ? (
+            <Alert severity="error">
+              <AlertTitle>Error</AlertTitle>
+              {formik.errors.error}
+            </Alert>
+          ) : (
+            <div />
+          )}
+        </form>
+      )}
+    </Formik>
+  )
+}
+
+export default AdminLogin
diff --git a/client/src/pages/login/components/CompetitionLogin.test.tsx b/client/src/pages/login/components/CompetitionLogin.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..29213c943578afb01b27199d0a3fcb5f2db44092
--- /dev/null
+++ b/client/src/pages/login/components/CompetitionLogin.test.tsx
@@ -0,0 +1,7 @@
+import { render } from '@testing-library/react'
+import React from 'react'
+import CompetitionLogin from './CompetitionLogin'
+
+it('renders competition login', () => {
+  render(<CompetitionLogin />)
+})
diff --git a/client/src/pages/login/components/CompetitionLogin.tsx b/client/src/pages/login/components/CompetitionLogin.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2450196d0cf5166a4d295417c69ef3654196552f
--- /dev/null
+++ b/client/src/pages/login/components/CompetitionLogin.tsx
@@ -0,0 +1,85 @@
+import { Button, TextField } from '@material-ui/core'
+import { Alert, AlertTitle } from '@material-ui/lab'
+import axios from 'axios'
+import { Formik, FormikHelpers } from 'formik'
+import React from 'react'
+import * as Yup from 'yup'
+import { CompetitionLoginModel } from '../../../interfaces/models'
+
+interface CompetitionLoginFormModel {
+  model: CompetitionLoginModel
+  error?: string
+}
+
+interface ServerResponse {
+  code: number
+  message: string
+}
+
+const competitionSchema: Yup.SchemaOf<CompetitionLoginFormModel> = Yup.object({
+  model: Yup.object()
+    .shape({
+      code: Yup.string().required('Mata in kod').min(6, 'Koden måste vara minst 6 tecken'),
+    })
+    .required(),
+  error: Yup.string().optional(),
+})
+
+const handleCompetitionSubmit = async (
+  values: CompetitionLoginFormModel,
+  actions: FormikHelpers<CompetitionLoginFormModel>
+) => {
+  console.log(values.model)
+  await axios
+    .post<ServerResponse>(`users/login`, { code: values.model.code })
+    .then((res) => {
+      actions.resetForm()
+    })
+    .catch(({ response }) => {
+      console.log(response.data.message)
+      actions.setFieldError('error', response.data.message)
+    })
+    .finally(() => {
+      actions.setSubmitting(false)
+    })
+}
+
+const CompetitionLogin: React.FC = (props) => {
+  const competitionInitialValues: CompetitionLoginFormModel = {
+    model: { code: '' },
+  }
+  return (
+    <Formik
+      initialValues={competitionInitialValues}
+      validationSchema={competitionSchema}
+      onSubmit={handleCompetitionSubmit}
+    >
+      {(formik) => (
+        <form onSubmit={formik.handleSubmit} className="login-form">
+          <TextField
+            label="Tävlingskod"
+            name="model.code"
+            helperText={formik.touched.model?.code && formik.touched.model?.code ? formik.errors.model?.code : ''}
+            error={Boolean(formik.touched.model?.code && formik.errors.model?.code)}
+            onChange={formik.handleChange}
+            onBlur={formik.handleBlur}
+            margin="normal"
+          />
+          <Button type="submit" fullWidth variant="contained" color="primary" disabled={!formik.isValid}>
+            Anslut till tävling
+          </Button>
+          {formik.errors.error ? (
+            <Alert severity="error">
+              <AlertTitle>Error</AlertTitle>
+              {formik.errors.error}
+            </Alert>
+          ) : (
+            <div />
+          )}
+        </form>
+      )}
+    </Formik>
+  )
+}
+
+export default CompetitionLogin
diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e5f1366ef74167317e53f52b8ed9b804ce6531f0
--- /dev/null
+++ b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
@@ -0,0 +1,14 @@
+import { Typography } from '@material-ui/core'
+import React from 'react'
+import { useParams } from 'react-router-dom'
+
+interface CompetitionParams {
+  id: string
+}
+
+const PresentationEditorPage: React.FC = (props) => {
+  const params: CompetitionParams = useParams()
+  return <Typography variant="h1">tävling: {params.id}</Typography>
+}
+
+export default PresentationEditorPage
diff --git a/client/src/pages/views/AudienceViewPage.tsx b/client/src/pages/views/AudienceViewPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f0cd70bc18d1132c0054ff3242ef04e4a35e4fb0
--- /dev/null
+++ b/client/src/pages/views/AudienceViewPage.tsx
@@ -0,0 +1,7 @@
+import React from 'react'
+
+const AudienceViewPage: React.FC = (props) => {
+  return <div>Publik</div>
+}
+
+export default AudienceViewPage
diff --git a/client/src/pages/views/JudgeViewPage.tsx b/client/src/pages/views/JudgeViewPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0051152b6327bd9df8257733b4e8628be21bd0c0
--- /dev/null
+++ b/client/src/pages/views/JudgeViewPage.tsx
@@ -0,0 +1,7 @@
+import React from 'react'
+
+const JudgeViewPage: React.FC = (props) => {
+  return <div>Judge</div>
+}
+
+export default JudgeViewPage
diff --git a/client/src/pages/views/ParticipantViewPage.tsx b/client/src/pages/views/ParticipantViewPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6a22cd4477e91a9a3d7f8d82bb36363c8c38a990
--- /dev/null
+++ b/client/src/pages/views/ParticipantViewPage.tsx
@@ -0,0 +1,7 @@
+import React from 'react'
+
+const ParticipantViewPage: React.FC = (props) => {
+  return <div>Deltagare</div>
+}
+
+export default ParticipantViewPage
diff --git a/client/src/pages/views/ViewSelectPage.css b/client/src/pages/views/ViewSelectPage.css
new file mode 100644
index 0000000000000000000000000000000000000000..920c6a342fa49a6a2ce9d205effa14e6e0d74a7c
--- /dev/null
+++ b/client/src/pages/views/ViewSelectPage.css
@@ -0,0 +1,20 @@
+.root {
+    display: flex;
+    justify-content: center;
+    margin-top: 12%;
+    height: 100%;
+}
+
+.button-group {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    width: max-content;
+    height: 140px;
+    margin-left: auto;
+    margin-right: auto;
+}
+
+.view-button {
+    width: 100%;
+}
diff --git a/client/src/pages/views/ViewSelectPage.tsx b/client/src/pages/views/ViewSelectPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..81decf7cdfb52b9d586edd2e92922eba7f3f58a9
--- /dev/null
+++ b/client/src/pages/views/ViewSelectPage.tsx
@@ -0,0 +1,25 @@
+import Button from '@material-ui/core/Button'
+import React from 'react'
+import { Link, useRouteMatch } from 'react-router-dom'
+import './ViewSelectPage.css'
+
+const ViewSelectPage: React.FC = (props) => {
+  const { path, url } = useRouteMatch()
+  return (
+    <div className="root">
+      <div className="button-group">
+        <Button className="view-button" color="primary" variant="contained" component={Link} to={`${url}/participant`}>
+          Deltagarvy
+        </Button>
+        <Button className="view-button" color="primary" variant="contained" component={Link} to={`${url}/audience`}>
+          Åskådarvy
+        </Button>
+        <Button className="view-button" color="primary" variant="contained" component={Link} to={`${url}/judge`}>
+          Domarvy
+        </Button>
+      </div>
+    </div>
+  )
+}
+
+export default ViewSelectPage
diff --git a/client/tsconfig.json b/client/tsconfig.json
index a273b0cfc0e965c35524e3cd0d3574cbe1ad2d0d..7f162ff3f6dbd3b8e60e6de8503fac0937d8f423 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -1,26 +1,31 @@
 {
   "compilerOptions": {
+    "rootDir": "./src",
+    "outDir": "./build",
+    "esModuleInterop": true,
+    "jsx": "react-jsx",
     "target": "es5",
     "lib": [
       "dom",
       "dom.iterable",
       "esnext"
     ],
-    "allowJs": true,
     "skipLibCheck": true,
-    "esModuleInterop": true,
     "allowSyntheticDefaultImports": true,
     "strict": true,
     "forceConsistentCasingInFileNames": true,
-    "noFallthroughCasesInSwitch": true,
     "module": "esnext",
     "moduleResolution": "node",
     "resolveJsonModule": true,
     "isolatedModules": true,
     "noEmit": true,
-    "jsx": "react-jsx"
+    "allowJs": true,
+    "noFallthroughCasesInSwitch": true
   },
   "include": [
-    "src"
+    "./src/**/*"
+  ],
+  "exclude": [
+    "build"
   ]
 }