diff --git a/TODO.md b/TODO.md
index 6adfd3b5e88fba73be20c8a7e15bdf06566a6578..f3367a02d7e259c788e517edd5b883cf2f814d2c 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,8 +1,4 @@
-- Finish Autentification and route protection with JWT
-- Implement detailed view of Participant information
-- Password reset after account creation
-- Client side field validation
-- Deployment
+- Fix Chef seeing CO and volunteer in same university
 
 - Traduction
 - Search functionality
diff --git a/client/src/binding/Claims.ts b/client/src/binding/Claims.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0f6a7dac48af8aae572eec430bd49be84f4ef8f6
--- /dev/null
+++ b/client/src/binding/Claims.ts
@@ -0,0 +1,10 @@
+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+import type { Role } from "./Role";
+import type { University } from "./University";
+
+export type Claims = {
+  id: string;
+  role: Role;
+  university: University;
+  exp: number;
+};
diff --git a/client/src/binding/EmailResetPayload.ts b/client/src/binding/EmailResetPayload.ts
new file mode 100644
index 0000000000000000000000000000000000000000..94648bda8e3fec53f32897d2058d1189eb757a71
--- /dev/null
+++ b/client/src/binding/EmailResetPayload.ts
@@ -0,0 +1,3 @@
+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+
+export type EmailResetPayload = { email: string };
diff --git a/client/src/binding/MinimalParticipant.ts b/client/src/binding/MinimalParticipant.ts
index bb2e0d2c0bb12c6e97e17560d468f826391c62d6..be03e0913a13f2898b20c7bb230da140e8104e26 100644
--- a/client/src/binding/MinimalParticipant.ts
+++ b/client/src/binding/MinimalParticipant.ts
@@ -1,11 +1,13 @@
 // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
 import type { Competition } from "./Competition";
 import type { Role } from "./Role";
+import type { University } from "./University";
 
 export type MinimalParticipant = {
   first_name: string;
   last_name: string;
   email: string;
   competition: Competition;
+  university: University;
   role: Role;
 };
diff --git a/client/src/binding/Participant.ts b/client/src/binding/ParticipantInfo.ts
similarity index 51%
rename from client/src/binding/Participant.ts
rename to client/src/binding/ParticipantInfo.ts
index cf21abe4dc7e422eb8dd867adcf3b2b2414c587a..4d2a8110be81fc7c8585173953df878e22b72901 100644
--- a/client/src/binding/Participant.ts
+++ b/client/src/binding/ParticipantInfo.ts
@@ -1,25 +1,19 @@
 // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
-import type { Competition } from "./Competition";
-import type { Role } from "./Role";
+import type { TshirtSize } from "./TshirtSize";
 
-export type Participant = {
-  id: string;
-  role: Role;
-  email: string;
-  first_name: string;
-  last_name: string;
-  university: string | null;
+export type ParticipantInfo = {
   medical_conditions: string | null;
   allergies: string | null;
   pronouns: string | null;
-  competition: Competition | null;
+  supper: string | null;
+  is_vegetarian: boolean | null;
   phone_number: string | null;
-  tshirt_size: string | null;
+  tshirt_size: TshirtSize | null;
   comments: string | null;
   emergency_contact: string | null;
   has_monthly_opus_card: boolean | null;
   reduced_mobility: string | null;
-  study_proof: string;
-  photo: string;
-  cv: string;
+  study_proof: File;
+  photo: File;
+  cv: File;
 };
diff --git a/client/src/binding/ParticipantPreview.ts b/client/src/binding/ParticipantPreview.ts
index d8d7738d9b566f82638bea7d1e46f0469d381305..cf23154e440e3e1104e52ff7dc6ade4bdc4d4374 100644
--- a/client/src/binding/ParticipantPreview.ts
+++ b/client/src/binding/ParticipantPreview.ts
@@ -1,6 +1,7 @@
 // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
 import type { Competition } from "./Competition";
 import type { Role } from "./Role";
+import type { University } from "./University";
 
 export type ParticipantPreview = {
   id: string;
@@ -9,5 +10,6 @@ export type ParticipantPreview = {
   email: string;
   role: Role;
   competition: Competition;
+  university: University;
   contain_cv: boolean;
 };
diff --git a/client/src/binding/TshirtSize.ts b/client/src/binding/TshirtSize.ts
new file mode 100644
index 0000000000000000000000000000000000000000..01256388734ff2489a96e02ae755006825445ff9
--- /dev/null
+++ b/client/src/binding/TshirtSize.ts
@@ -0,0 +1,3 @@
+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+
+export type TshirtSize = "xs" | "s" | "m" | "l" | "xl" | "xxl";
diff --git a/client/src/binding/University.ts b/client/src/binding/University.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f62004e94784db01e193ac3a53db8cab9d9d1619
--- /dev/null
+++ b/client/src/binding/University.ts
@@ -0,0 +1,17 @@
+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+
+export type University =
+  | "uqac"
+  | "uqar"
+  | "uqat"
+  | "uqo"
+  | "uqtr"
+  | "mcgill"
+  | "mcgill_macdonald"
+  | "concordia"
+  | "ets"
+  | "polymtl"
+  | "ulaval"
+  | "ulaval_agriculture"
+  | "uds"
+  | "none";
diff --git a/client/src/components/ProtectedRoute.tsx b/client/src/components/ProtectedRoute.tsx
index 95d5749adf74a532ae2cd06b073680389111aedc..dc07511d8692de9cdfedfa52f534683e3896254d 100644
--- a/client/src/components/ProtectedRoute.tsx
+++ b/client/src/components/ProtectedRoute.tsx
@@ -17,6 +17,9 @@ export function ProtectedRoute(props: ProtectedRouteProps) {
             localStorage.removeItem("token")
             navigate("/login")
         }
+        localStorage.setItem("id", response.id)
+        localStorage.setItem("role", response.role)
+        localStorage.setItem("university", response.university)
     })
 
     return <>{props.children}</>
diff --git a/client/src/components/forms-component/Checkbox.tsx b/client/src/components/forms-component/Checkbox.tsx
index fb9b1ab013172a67a7501315f99c6211e2fa2890..4da6bfbd327e4ac760f4ad30e977d37c38e34254 100644
--- a/client/src/components/forms-component/Checkbox.tsx
+++ b/client/src/components/forms-component/Checkbox.tsx
@@ -1,5 +1,6 @@
 import { JSX, splitProps } from "solid-js"
 import { InputError } from "./InputError"
+import clsx from "clsx"
 
 type CheckboxProps = {
     ref: (element: HTMLInputElement) => void
diff --git a/client/src/components/forms-component/FileInput.tsx b/client/src/components/forms-component/FileInput.tsx
index 41999eff69ff21e467fd3617bc54c8d82fd86661..b41f9ca33602b9493f2adf8815bb1f3f5ae598f9 100644
--- a/client/src/components/forms-component/FileInput.tsx
+++ b/client/src/components/forms-component/FileInput.tsx
@@ -42,7 +42,7 @@ export function FileInput(props: FileInputProps) {
     )
 
     return (
-        <div class={clsx("px-8 lg:px-10", props.class)}>
+        <div>
             <InputLabel
                 name={props.name}
                 label={props.label}
diff --git a/client/src/components/forms-component/SubmitSuccess.tsx b/client/src/components/forms-component/SubmitSuccess.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bcf7696c61a9b14fe1d24c1fcf1c59754a4aee09
--- /dev/null
+++ b/client/src/components/forms-component/SubmitSuccess.tsx
@@ -0,0 +1,15 @@
+import { Expandable } from "./Expandable"
+
+type Props = {
+    success: () => string | null
+}
+
+export function SubmitSuccess(props: Props) {
+    return (
+        <Expandable expanded={!!props.success()}>
+            <div class="pt-4 text-sm text-green-500 dark:text-green-400 md:text-base lg:pt-5 lg:text-lg">
+                {props.success()}
+            </div>
+        </Expandable>
+    )
+}
diff --git a/client/src/components/forms-component/TextInput.tsx b/client/src/components/forms-component/TextInput.tsx
index 006aca991f3f7ea1e1bcbc673303343fa2dc53c7..7afc9ab72526672eb783d702f0966aed0f7bb51a 100644
--- a/client/src/components/forms-component/TextInput.tsx
+++ b/client/src/components/forms-component/TextInput.tsx
@@ -45,7 +45,7 @@ export function TextInput(props: TextInputProps) {
     )
 
     return (
-        <div class={clsx(props.class)}>
+        <div class={clsx("w-full", props.class)}>
             <InputLabel
                 name={props.name}
                 label={props.label}
diff --git a/client/src/components/forms/AdditionnalInfoForm.tsx b/client/src/components/forms/AdditionnalInfoForm.tsx
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..77290903dd6dd523ac662563169cf4e24c74ee4d 100644
--- a/client/src/components/forms/AdditionnalInfoForm.tsx
+++ b/client/src/components/forms/AdditionnalInfoForm.tsx
@@ -0,0 +1,241 @@
+import { useNavigate } from "@solidjs/router"
+import { createForm, setValues, SubmitHandler } from "@modular-forms/solid"
+import { TextInput } from "../forms-component/TextInput"
+import { Checkbox } from "../forms-component/Checkbox"
+import { ParticipantInfo } from "../../binding/ParticipantInfo"
+import { Select } from "../forms-component/Select"
+import { FileInput } from "../forms-component/FileInput"
+import { getParticipant, patchParticipantInfo } from "../../request/routes"
+import { createEffect } from "solid-js"
+import { t } from "../../stores/locale"
+
+export function AdditionalInfoForm() {
+    const navigate = useNavigate()
+    const [loginForm, { Form, Field }] = createForm<ParticipantInfo>()
+
+    const handleSubmit: SubmitHandler<ParticipantInfo> = async (
+        values,
+        event,
+    ) => {
+        event.preventDefault()
+        const response = await patchParticipantInfo(values)
+        if (response && response.status == 201) {
+            navigate("/dashboard")
+        } else {
+            console.log(response)
+        }
+    }
+
+    createEffect(async () => {
+        const id = localStorage.getItem("id")
+        if (!id) return
+        const response = await getParticipant(id)
+        if (!response.error) {
+            const participant = response as ParticipantInfo
+            setValues(loginForm, participant)
+        }
+    })
+
+    return (
+        <Form
+            class="flex w-1/2 flex-col space-y-6"
+            action="#"
+            method="post"
+            onSubmit={handleSubmit}
+        >
+            <Field name="medical_conditions">
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value || ""}
+                        error={field.error}
+                        label={t("additionalInfo.medicalConditionsLabel")}
+                        type="text"
+                        placeholder={t("additionalInfo.medicalConditions")}
+                    />
+                )}
+            </Field>
+
+            <Field name="allergies">
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value || ""}
+                        error={field.error}
+                        label={t("additionalInfo.allergiesLabel")}
+                        type="text"
+                        placeholder={t("additionalInfo.allergies")}
+                    />
+                )}
+            </Field>
+
+            <Field name="pronouns">
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value || ""}
+                        error={field.error}
+                        label={t("additionalInfo.pronounsLabel")}
+                        type="text"
+                        placeholder={t("additionalInfo.pronouns")}
+                    />
+                )}
+            </Field>
+
+            <Field name="is_vegetarian" type="boolean">
+                {(field, props) => (
+                    <Checkbox
+                        {...props}
+                        checked={field.value || false}
+                        error={field.error}
+                        label={t("additionalInfo.vegetarianLabel")}
+                    />
+                )}
+            </Field>
+
+            <Field name="phone_number">
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value || ""}
+                        error={field.error}
+                        label={t("additionalInfo.phoneNumberLabel")}
+                        type="text"
+                        placeholder={t("additionalInfo.phoneNumber")}
+                    />
+                )}
+            </Field>
+
+            <Field name="tshirt_size">
+                {(field, props) => (
+                    <Select
+                        {...props}
+                        value={field.value || "m"}
+                        error={field.error}
+                        label={t("additionalInfo.tshirtSize")}
+                        options={[
+                            {
+                                label: "XS",
+                                value: "xs",
+                            },
+                            {
+                                label: "S",
+                                value: "s",
+                            },
+                            {
+                                label: "M",
+                                value: "m",
+                            },
+                            {
+                                label: "L",
+                                value: "l",
+                            },
+                            {
+                                label: "XL",
+                                value: "xl",
+                            },
+                            {
+                                label: "2XL",
+                                value: "xxl",
+                            },
+                        ]}
+                    />
+                )}
+            </Field>
+
+            <Field name="emergency_contact">
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value || ""}
+                        error={field.error}
+                        label={t("additionalInfo.emergencyContactLabel")}
+                        type="text"
+                        placeholder={t("additionalInfo.emergencyContact")}
+                    />
+                )}
+            </Field>
+
+            <Field name="has_monthly_opus_card" type="boolean">
+                {(field, props) => (
+                    <Checkbox
+                        {...props}
+                        error={field.error}
+                        label={t("additionalInfo.hasMonthlyOpusCard")}
+                    />
+                )}
+            </Field>
+
+            <Field name="reduced_mobility">
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value || ""}
+                        error={field.error}
+                        label={t("additionalInfo.reducedMobilityLabel")}
+                        type="text"
+                        placeholder={t("additionalInfo.reducedMobility")}
+                    />
+                )}
+            </Field>
+
+            <Field name="study_proof" type="File">
+                {(field, props) => (
+                    <FileInput
+                        {...props}
+                        value={field.value}
+                        error={field.error}
+                        label={t("additionalInfo.studyProofLabel")}
+                        accept="image/*,.pdf,.doc,.docx,.odt,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+                    />
+                )}
+            </Field>
+
+            <Field name="photo" type="File">
+                {(field, props) => (
+                    <FileInput
+                        {...props}
+                        value={field.value}
+                        error={field.error}
+                        label={t("additionalInfo.photoLabel")}
+                        accept="image/*"
+                    />
+                )}
+            </Field>
+
+            <Field name="cv" type="File">
+                {(field, props) => (
+                    <FileInput
+                        {...props}
+                        value={field.value}
+                        error={field.error}
+                        label={t("additionalInfo.cvLabel")}
+                        accept=".pdf,.doc,.docx,.odt,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+                    />
+                )}
+            </Field>
+
+            <Field name="comments">
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value || ""}
+                        error={field.error}
+                        label="Commentaires"
+                        type="text"
+                        placeholder="Commentaires"
+                    />
+                )}
+            </Field>
+
+            <div>
+                <button
+                    type="submit"
+                    class="flex w-full justify-center rounded-md bg-light-highlight px-5 py-4 text-xl font-semibold leading-6 text-white shadow-sm hover:bg-light-highlight focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-light-highlight"
+                >
+                    Mettre à jour les renseignements personnels
+                </button>
+            </div>
+        </Form>
+    )
+}
diff --git a/client/src/components/forms/EmailResetForm.tsx b/client/src/components/forms/EmailResetForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4248fe79e1e65bbd1cdf0bce0bb6d888e6cc619a
--- /dev/null
+++ b/client/src/components/forms/EmailResetForm.tsx
@@ -0,0 +1,68 @@
+import {
+    createForm,
+    email,
+    required,
+    SubmitHandler,
+} from "@modular-forms/solid"
+import { createSignal } from "solid-js"
+import { EmailResetPayload } from "../../binding/EmailResetPayload"
+import { resetEmail } from "../../request/routes"
+import { t } from "../../stores/locale"
+import { SubmitError } from "../forms-component/SubmitError"
+import { SubmitSuccess } from "../forms-component/SubmitSuccess"
+import { TextInput } from "../forms-component/TextInput"
+
+export function EmailResetForm() {
+    const [_loginForm, { Form, Field }] = createForm<EmailResetPayload>()
+
+    const [error, setError] = createSignal<string | null>(null)
+    const [success, setSuccess] = createSignal<string | null>(null)
+
+    const handleSubmit: SubmitHandler<EmailResetPayload> = async (
+        values,
+        event,
+    ) => {
+        event.preventDefault()
+        const request = await resetEmail(values)
+        if (request.status !== 200) {
+            setError(t("loginPage.badLogin"))
+            setSuccess(null)
+        } else {
+            setError(null)
+            setSuccess(t("loginPage.resetEmailSent"))
+        }
+    }
+    return (
+        <Form class="space-y-6" onSubmit={handleSubmit}>
+            <Field
+                name="email"
+                validate={[
+                    required(t("loginPage.requiredEmail")),
+                    email(t("loginPage.invalidEmail")),
+                ]}
+            >
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value}
+                        error={field.error}
+                        label={t("loginPage.email")}
+                        type="email"
+                        placeholder="exemple@courriel.com"
+                        required
+                    />
+                )}
+            </Field>
+            <div>
+                <button
+                    type="submit"
+                    class="flex w-full justify-center rounded-md bg-light-highlight py-3 font-semibold text-white shadow-sm"
+                >
+                    {t("loginPage.signIn")}
+                </button>
+                <SubmitSuccess success={success} />
+                <SubmitError error={error} />
+            </div>
+        </Form>
+    )
+}
diff --git a/client/src/components/forms/LoginForm.tsx b/client/src/components/forms/LoginForm.tsx
index 8e6198f0a8d3b2adf82dfdaabd1389cadde8099b..397c1b767eef343dffe69e19b6d9a68785cd08bd 100644
--- a/client/src/components/forms/LoginForm.tsx
+++ b/client/src/components/forms/LoginForm.tsx
@@ -12,6 +12,7 @@ import { TextInput } from "../forms-component/TextInput"
 import { SubmitError } from "../forms-component/SubmitError"
 import { createSignal } from "solid-js"
 import { t } from "../../stores/locale"
+import PrefetchLink from "../PrefetchLink"
 
 export default function LoginForm() {
     const [_loginForm, { Form, Field }] = createForm<AuthPayload>()
@@ -32,61 +33,67 @@ export default function LoginForm() {
     }
 
     return (
-        <div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
-            <Form class="space-y-6" onSubmit={handleSubmit}>
-                <Field
-                    name="email"
-                    validate={[
-                        required(t("loginPage.requiredEmail")),
-                        email(t("loginPage.invalidEmail")),
-                    ]}
-                >
-                    {(field, props) => (
-                        <TextInput
-                            {...props}
-                            value={field.value}
-                            error={field.error}
-                            label={t("loginPage.email")}
-                            type="email"
-                            placeholder="exemple@courriel.com"
-                            required
-                        />
-                    )}
-                </Field>
+        <Form class="space-y-6" onSubmit={handleSubmit}>
+            <Field
+                name="email"
+                validate={[
+                    required(t("loginPage.requiredEmail")),
+                    email(t("loginPage.invalidEmail")),
+                ]}
+            >
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value}
+                        error={field.error}
+                        label={t("loginPage.email")}
+                        type="email"
+                        placeholder="exemple@courriel.com"
+                        required
+                    />
+                )}
+            </Field>
 
-                <Field
-                    name="password"
-                    validate={[
-                        required(t("loginPage.requiredPassword")),
-                        minLength(
-                            8,
-                            "You password must have 8 characters or more.",
-                        ),
-                    ]}
+            <Field
+                name="password"
+                validate={[
+                    required(t("loginPage.requiredPassword")),
+                    minLength(
+                        8,
+                        "You password must have 8 characters or more.",
+                    ),
+                ]}
+            >
+                {(field, props) => (
+                    <TextInput
+                        {...props}
+                        value={field.value}
+                        error={field.error}
+                        type="password"
+                        label={t("loginPage.password")}
+                        placeholder="********"
+                        required
+                    />
+                )}
+            </Field>
+            <PrefetchLink
+                to="/forgotten-password"
+                file="ForgottenPassword"
+                class="block"
+            >
+                <span class="text-green-500">
+                    {t("loginPage.forgotPassword")}
+                </span>
+            </PrefetchLink>
+            <div>
+                <button
+                    type="submit"
+                    class="flex w-full justify-center rounded-md bg-light-highlight py-3 font-semibold text-white shadow-sm"
                 >
-                    {(field, props) => (
-                        <TextInput
-                            {...props}
-                            value={field.value}
-                            error={field.error}
-                            type="password"
-                            label={t("loginPage.password")}
-                            placeholder="********"
-                            required
-                        />
-                    )}
-                </Field>
-
-                <div>
-                    <button
-                        type="submit"
-                        class="flex w-full justify-center rounded-md bg-light-highlight py-3 font-semibold text-white shadow-sm"
-                    >
-                        {t("loginPage.signIn")}
-                    </button>
-                    <SubmitError error={error} />
-                </div>
-            </Form>
-        </div>
+                    {t("loginPage.signIn")}
+                </button>
+                <SubmitError error={error} />
+            </div>
+        </Form>
     )
 }
diff --git a/client/src/components/forms/NewPasswordForm.tsx b/client/src/components/forms/NewPasswordForm.tsx
index e38a66cbf5dfd6f24a8a16cde9487412ed5ca9e8..a3849abe648a85b46ec068e0710b587875e7594f 100644
--- a/client/src/components/forms/NewPasswordForm.tsx
+++ b/client/src/components/forms/NewPasswordForm.tsx
@@ -3,15 +3,19 @@ import { ChangePasswordPayload } from "../../binding/ChangePasswordPayload"
 import { changePassword } from "../../request/routes"
 import { TextInput } from "../forms-component/TextInput"
 import { SubmitError } from "../forms-component/SubmitError"
-import { createSignal } from "solid-js"
+import { createEffect, createSignal } from "solid-js"
 
 export function NewPassword() {
     const [_form, { Form, Field }] = createForm<ChangePasswordPayload>()
     const [error, setError] = createSignal<string | null>(null)
 
     const onSubmit = async (data: ChangePasswordPayload) => {
-        await changePassword(data)
+        const response = await changePassword(data)
+        if (response.error) {
+            setError("Erreur lors du changement de mot de passe")
+        }
     }
+    createEffect(async () => {})
     return (
         <Form onSubmit={onSubmit} class="flex flex-col gap-8">
             <Field name="new_password">
diff --git a/client/src/components/forms/ParticipantForm.tsx b/client/src/components/forms/ParticipantForm.tsx
index 7baa521aa99235cf945a9028ae533d0a585bed7c..8de21106d4001d6c078e1232b0e9b38ec31a8e5c 100644
--- a/client/src/components/forms/ParticipantForm.tsx
+++ b/client/src/components/forms/ParticipantForm.tsx
@@ -1,4 +1,4 @@
-import { Info, PlusCircle, Trash } from "phosphor-solid-js"
+import { PlusCircle, Trash } from "phosphor-solid-js"
 import { MinimalParticipant } from "../../binding/MinimalParticipant"
 import { createResource, For } from "solid-js"
 import { createForm } from "@modular-forms/solid"
@@ -29,20 +29,26 @@ function ParticipantRow(props: ParticipantRowProps) {
             <td class="p-2 text-center">{p.email}</td>
             <td class="p-2 text-center">{p.competition}</td>
             <td class="p-2 text-center">{p.role}</td>
+            {localStorage.getItem("role") === "organizer" && (
+                <td class="p-2 text-center">{p.university}</td>
+            )}
             <td class="flex flex-row gap-4 p-2 text-center">
-                <button
+                {/* <button
                     type="button"
                     class="rounded bg-blue-500 p-1 font-bold text-white hover:bg-blue-700"
                 >
                     <Info class="h-8 w-8"></Info>
-                </button>
-                <button
-                    type="button"
-                    class="rounded bg-red-500 p-1 font-bold text-white hover:bg-red-700"
-                    onClick={deleteParticipantOnClick}
-                >
-                    <Trash class="h-8 w-8"></Trash>
-                </button>
+                </button> */}
+
+                {localStorage.getItem("role") !== "volunteer" && (
+                    <button
+                        type="button"
+                        class="rounded bg-red-500 p-1 font-bold text-white hover:bg-red-700"
+                        onClick={deleteParticipantOnClick}
+                    >
+                        <Trash class="h-8 w-8"></Trash>
+                    </button>
+                )}
             </td>
         </tr>
     )
@@ -55,6 +61,43 @@ async function fetchWrapper() {
     return participants
 }
 
+function getGivableRole() {
+    const role = localStorage.getItem("role")
+    if (role == "organizer") {
+        return [
+            {
+                label: "CO/Directeur",
+                value: "organizer",
+            },
+            {
+                label: "Volontaire",
+                value: "volunteer",
+            },
+            {
+                label: "Chef",
+                value: "chef",
+            },
+            {
+                label: "Participant",
+                value: "participant",
+            },
+        ]
+    } else if (role == "chef") {
+        return [
+            {
+                label: "Chef",
+                value: "chef",
+            },
+            {
+                label: "Participant",
+                value: "participant",
+            },
+        ]
+    } else {
+        return []
+    }
+}
+
 export default function ParticipantForm() {
     const [user, { refetch }] = createResource(fetchWrapper)
     const [_form, { Form, Field }] = createForm<MinimalParticipant>()
@@ -84,6 +127,11 @@ export default function ParticipantForm() {
                         <th class="border-b border-gray-300 p-2 text-center">
                             Rôle
                         </th>
+                        {localStorage.getItem("role") === "organizer" && (
+                            <th class="border-b border-gray-300 p-2 text-center">
+                                Université
+                            </th>
+                        )}
                         <th class="border-b border-gray-300 p-2 text-center">
                             Actions
                         </th>
@@ -98,141 +146,198 @@ export default function ParticipantForm() {
                             />
                         )}
                     </For>
-                    <tr class="border-b border-gray-200">
-                        <td class="p-2">
-                            <Field name="first_name">
-                                {(field, props) => (
-                                    <TextInput
-                                        {...props}
-                                        value={field.value}
-                                        error={field.error}
-                                        class="w-52"
-                                        type="text"
-                                        placeholder="Prénom"
-                                        required
-                                    />
-                                )}
-                            </Field>
-                        </td>
-                        <td class="p-2">
-                            <Field name="last_name">
-                                {(field, props) => (
-                                    <TextInput
-                                        {...props}
-                                        value={field.value}
-                                        error={field.error}
-                                        class="w-52"
-                                        type="text"
-                                        placeholder="Nom"
-                                        required
-                                    />
-                                )}
-                            </Field>
-                        </td>
-                        <td class="p-2">
-                            <Field name="email">
-                                {(field, props) => (
-                                    <TextInput
-                                        {...props}
-                                        value={field.value}
-                                        error={field.error}
-                                        type="email"
-                                        placeholder="exemple@courriel.com"
-                                        required
-                                    />
-                                )}
-                            </Field>
-                        </td>
-                        <td class="p-2">
-                            <Field name="competition">
-                                {(field, props) => (
-                                    <Select
-                                        {...props}
-                                        value={field.value}
-                                        error={field.error}
-                                        options={[
-                                            {
-                                                label: "Aucune",
-                                                value: "none",
-                                            },
-                                            {
-                                                label: "Conception Senior",
-                                                value: "conception_senior",
-                                            },
-                                            {
-                                                label: "Conception Junior",
-                                                value: "conception_junior",
-                                            },
-                                            {
-                                                label: "Débats oratoires",
-                                                value: "debats_oratoires",
-                                            },
-                                            {
-                                                label: "Reingénierie",
-                                                value: "reingenierie",
-                                            },
-                                            {
-                                                label: "Génie Conseil",
-                                                value: "genie_conseil",
-                                            },
-                                            {
-                                                label: "Communication Scientifique",
-                                                value: "communication_scientifique",
-                                            },
-                                            {
-                                                label: "Programmation",
-                                                value: "programmation",
-                                            },
-                                            {
-                                                label: "Conception innovatrice",
-                                                value: "conception_innovatrice",
-                                            },
-                                            {
-                                                label: "Cycle supérieur",
-                                                value: "cycle_superieur",
-                                            },
-                                        ]}
-                                        required
-                                    />
-                                )}
-                            </Field>
-                        </td>
-                        <td class="p-2">
-                            <Field name="role">
-                                {(field, props) => (
-                                    <Select
-                                        {...props}
-                                        value={field.value}
-                                        error={field.error}
-                                        options={[
-                                            {
-                                                label: "CO/Directeur",
-                                                value: "organizer",
-                                            },
-                                            {
-                                                label: "Volontaire",
-                                                value: "volunteer",
-                                            },
-                                            {
-                                                label: "Chef",
-                                                value: "chef",
-                                            },
-                                            {
-                                                label: "Participant",
-                                                value: "participant",
-                                            },
-                                        ]}
-                                        required
-                                    />
-                                )}
-                            </Field>
-                        </td>
-                        <td class="p-2">
-                            <button class="rounded bg-green-500 p-1 font-bold text-white hover:bg-green-700">
-                                <PlusCircle class="h-8 w-8"></PlusCircle>
-                            </button>
-                        </td>
-                    </tr>
+                    {localStorage.getItem("role") !== "volunteer" && (
+                        <tr class="border-b border-gray-200">
+                            <td class="p-2">
+                                <Field name="first_name">
+                                    {(field, props) => (
+                                        <TextInput
+                                            {...props}
+                                            value={field.value}
+                                            error={field.error}
+                                            class="w-52"
+                                            type="text"
+                                            placeholder="Prénom"
+                                            required
+                                        />
+                                    )}
+                                </Field>
+                            </td>
+                            <td class="p-2">
+                                <Field name="last_name">
+                                    {(field, props) => (
+                                        <TextInput
+                                            {...props}
+                                            value={field.value}
+                                            error={field.error}
+                                            class="w-52"
+                                            type="text"
+                                            placeholder="Nom"
+                                            required
+                                        />
+                                    )}
+                                </Field>
+                            </td>
+                            <td class="p-2">
+                                <Field name="email">
+                                    {(field, props) => (
+                                        <TextInput
+                                            {...props}
+                                            value={field.value}
+                                            error={field.error}
+                                            type="email"
+                                            placeholder="exemple@courriel.com"
+                                            required
+                                        />
+                                    )}
+                                </Field>
+                            </td>
+                            <td class="p-2">
+                                <Field name="competition">
+                                    {(field, props) => (
+                                        <Select
+                                            {...props}
+                                            value={field.value}
+                                            error={field.error}
+                                            options={[
+                                                {
+                                                    label: "Aucune",
+                                                    value: "none",
+                                                },
+                                                {
+                                                    label: "Conception Senior",
+                                                    value: "conception_senior",
+                                                },
+                                                {
+                                                    label: "Conception Junior",
+                                                    value: "conception_junior",
+                                                },
+                                                {
+                                                    label: "Débats oratoires",
+                                                    value: "debats_oratoires",
+                                                },
+                                                {
+                                                    label: "Reingénierie",
+                                                    value: "reingenierie",
+                                                },
+                                                {
+                                                    label: "Génie Conseil",
+                                                    value: "genie_conseil",
+                                                },
+                                                {
+                                                    label: "Communication Scientifique",
+                                                    value: "communication_scientifique",
+                                                },
+                                                {
+                                                    label: "Programmation",
+                                                    value: "programmation",
+                                                },
+                                                {
+                                                    label: "Conception innovatrice",
+                                                    value: "conception_innovatrice",
+                                                },
+                                                {
+                                                    label: "Cycle supérieur",
+                                                    value: "cycle_superieur",
+                                                },
+                                            ]}
+                                            required
+                                        />
+                                    )}
+                                </Field>
+                            </td>
+                            <td class="p-2">
+                                <Field name="role">
+                                    {(field, props) => (
+                                        <Select
+                                            {...props}
+                                            value={field.value}
+                                            error={field.error}
+                                            options={getGivableRole()}
+                                            required
+                                        />
+                                    )}
+                                </Field>
+                            </td>
+                            {localStorage.getItem("role") === "organizer" && (
+                                <td class="p-2">
+                                    <Field name="university">
+                                        {(field, props) => (
+                                            <Select
+                                                {...props}
+                                                value="none"
+                                                error={field.error}
+                                                options={[
+                                                    {
+                                                        label: "UQAC",
+                                                        value: "uqac",
+                                                    },
+                                                    {
+                                                        label: "UQAR",
+                                                        value: "uqar",
+                                                    },
+                                                    {
+                                                        label: "UQAT",
+                                                        value: "uqat",
+                                                    },
+                                                    {
+                                                        label: "UQO",
+                                                        value: "uqo",
+                                                    },
+                                                    {
+                                                        label: "UQTR",
+                                                        value: "uqtr",
+                                                    },
+                                                    {
+                                                        label: "McGill",
+                                                        value: "mcgill",
+                                                    },
+                                                    {
+                                                        label: "McGill Macdonald",
+                                                        value: "mcgill_macdonald",
+                                                    },
+                                                    {
+                                                        label: "Concordia",
+                                                        value: "concordia",
+                                                    },
+                                                    {
+                                                        label: "ETS",
+                                                        value: "ets",
+                                                    },
+                                                    {
+                                                        label: "PolyMTL",
+                                                        value: "polymtl",
+                                                    },
+                                                    {
+                                                        label: "ULaval",
+                                                        value: "ulaval",
+                                                    },
+                                                    {
+                                                        label: "ULaval Agroalimentaire",
+                                                        value: "ulaval-agriculture",
+                                                    },
+                                                    {
+                                                        label: "UDS",
+                                                        value: "uds",
+                                                    },
+                                                    {
+                                                        label: "Aucune",
+                                                        value: "none",
+                                                    },
+                                                ]}
+                                                required
+                                            />
+                                        )}
+                                    </Field>
+                                </td>
+                            )}
+                            <td class="p-2">
+                                <button class="rounded bg-green-500 p-1 font-bold text-white hover:bg-green-700">
+                                    <PlusCircle class="h-8 w-8"></PlusCircle>
+                                </button>
+                            </td>
+                        </tr>
+                    )}
                 </tbody>
             </table>
         </Form>
diff --git a/client/src/i18n/en.ts b/client/src/i18n/en.ts
index 56780541709b39b90cea1246355346cb88b91035..3d63291de8436137e4ede6f4079a5462e80ef542 100644
--- a/client/src/i18n/en.ts
+++ b/client/src/i18n/en.ts
@@ -96,6 +96,30 @@ const loginPage = {
     email: "Email",
     password: "Password",
     signIn: "Sign in",
+    forgotPassword: "Forgot password?",
+    resetEmailSent: "An email has been sent to reset your password.",
+}
+
+const additionalInfo = {
+    medicalConditions: "Medical conditions",
+    medicalConditionsLabel:
+        "Please specify any medical conditions that we should be aware of.",
+    allergies: "Allergies",
+    allergiesLabel: "Please specify any allergies that we should be aware of.",
+    pronouns: "Pronouns",
+    pronounsLabel: "Please specify your pronouns.",
+    vegetarianLabel: "Are you vegetarian?",
+    phoneNumber: "Phone number",
+    phoneNumberLabel: "Please specify your phone number.",
+    tshirtSize: "T-shirt size",
+    emergencyContact: "Emergency contact",
+    emergencyContactLabel: "Please specify your emergency contact.",
+    hasMonthlyOpusCard: "Do you have a monthly OPUS card?",
+    reducedMobilityLabel: "Any acommodation for reduced mobility?",
+    reducedMobility: "What do you need?",
+    studyProofLabel: "Study proof",
+    photoLabel: "Photo",
+    cvLabel: "CV",
 }
 
 export const dict = {
@@ -109,5 +133,6 @@ export const dict = {
     documents: documents,
     login: "Login",
     loginPage: loginPage,
+    additionalInfo: additionalInfo,
     madeBy: "Made by",
 }
diff --git a/client/src/i18n/fr.ts b/client/src/i18n/fr.ts
index dff81fcfb3bbabdfa1071fa58f64d0a9a03e14ee..1195552625ac38c0e569a439ab33e2c06fa85df6 100644
--- a/client/src/i18n/fr.ts
+++ b/client/src/i18n/fr.ts
@@ -96,6 +96,31 @@ const loginPage = {
     email: "Courriel",
     password: "Mot de passe",
     signIn: "Se connecter",
+    forgotPassword: "Mot de passe oublié?",
+    resetEmailSent: "Courriel de réinitialisation envoyé",
+}
+
+const additionalInfo = {
+    medicalConditions: "Conditions médicales",
+    medicalConditionsLabel:
+        "Veuillez spécifier toute condition médicale dont nous devrions être informés.",
+    allergies: "Allergies",
+    allergiesLabel:
+        "Veuillez spécifier toute allergie dont nous devrions être informés.",
+    pronouns: "Pronoms",
+    pronounsLabel: "Veuillez spécifier vos pronoms.",
+    vegetarianLabel: "Êtes-vous végétarien?",
+    phoneNumber: "Numéro de téléphone",
+    phoneNumberLabel: "Veuillez spécifier votre numéro de téléphone.",
+    tshirtSize: "Taille de T-shirt",
+    emergencyContact: "Contact d'urgence",
+    emergencyContactLabel: "Veuillez spécifier votre contact d'urgence.",
+    hasMonthlyOpusCard: "Avez-vous une carte OPUS mensuelle?",
+    reducedMobilityLabel: "Besoin d'aménagement pour mobilité réduite?",
+    reducedMobility: "Qu'avez-vous besoin?",
+    studyProofLabel: "Preuve d'études",
+    photoLabel: "Photo",
+    cvLabel: "CV",
 }
 
 export const dict = {
@@ -110,4 +135,5 @@ export const dict = {
     login: "Connexion",
     madeBy: "Créé par",
     loginPage: loginPage,
+    additionalInfo: additionalInfo,
 }
diff --git a/client/src/index.tsx b/client/src/index.tsx
index 101035db7403a5db3a78704b71cd9d42bf2c98dc..1d662c9f3979cc58eb72419f42c14f81e210c216 100644
--- a/client/src/index.tsx
+++ b/client/src/index.tsx
@@ -27,6 +27,7 @@ const Dashboard = lazy(() => import("./routes/Dashboard"))
 const AdditionalForm = lazy(() => import("./routes/AdditionalForm"))
 const ListParticipant = lazy(() => import("./routes/ListParticipant"))
 const ChangePassword = lazy(() => import("./routes/ChangePassword"))
+const ForgottenPassword = lazy(() => import("./routes/ForgottenPassword"))
 
 const app = document.getElementById("app")
 if (app) {
@@ -47,6 +48,10 @@ if (app) {
                     path="/change-password/:token?"
                     component={ChangePassword}
                 />
+                <Route
+                    path="/forgotten-password"
+                    component={ForgottenPassword}
+                />
                 <Route path="*" component={NotFound} />
             </Router>
         ),
diff --git a/client/src/request/fetch_wrapper.ts b/client/src/request/fetch_wrapper.ts
index ed6e17c1d3b87349a07faa97d6ca2f8a83e5b76b..58a6e1df78e07df49218bdcc449c0f674153af89 100644
--- a/client/src/request/fetch_wrapper.ts
+++ b/client/src/request/fetch_wrapper.ts
@@ -72,6 +72,7 @@ export async function fetch_patch(url: string, body: any) {
     return await fetch(import.meta.env.VITE_API_URL + url, {
         method: "PATCH",
         headers: {
+            "Content-Type": "application/json",
             Authorization: "Bearer " + token,
         },
         body: JSON.stringify(body),
diff --git a/client/src/request/routes.ts b/client/src/request/routes.ts
index 581276fb45afea74b85227882109c75b07992097..0f9976d5d5967606cbbd5b06e9b61de81df467c8 100644
--- a/client/src/request/routes.ts
+++ b/client/src/request/routes.ts
@@ -1,10 +1,13 @@
 import { AuthPayload } from "../binding/AuthPayload"
 import { ChangePasswordPayload } from "../binding/ChangePasswordPayload"
+import { EmailResetPayload } from "../binding/EmailResetPayload"
 import { MinimalParticipant } from "../binding/MinimalParticipant"
+import { ParticipantInfo } from "../binding/ParticipantInfo"
 import { ParticipantPreview } from "../binding/ParticipantPreview"
 import {
     fetch_delete,
     fetch_get,
+    fetch_patch,
     fetch_post,
     fetch_post_no_token,
     fetch_put,
@@ -22,7 +25,11 @@ export async function fetchParticipants() {
 export async function submitMinimalParticipant(
     participant: MinimalParticipant,
 ) {
-    return await fetch_post("/participant", participant)
+    const payload: any = participant
+    if (localStorage.getItem("role") == "chef") {
+        payload.university = localStorage.getItem("university")
+    }
+    return await fetch_post("/participant", payload)
 }
 
 export async function deleteParticipant(p: ParticipantPreview) {
@@ -49,3 +56,60 @@ export async function testAuth() {
     }
     return await request.json()
 }
+
+export async function resetEmail(email: EmailResetPayload) {
+    return await fetch_post_no_token("/password", email)
+}
+
+function getBase64(file: File): Promise<string> {
+    return new Promise((resolve, reject) => {
+        const reader = new FileReader()
+
+        // Event listener when the file reading is completed
+        reader.onload = () => {
+            // `reader.result` contains the base64 string
+            const base64String = reader.result as string
+            const base64StringSplit = base64String.split(",")[1]
+            if (!base64StringSplit) {
+                reject(new Error("Failed to convert file to base64"))
+            }
+            resolve(base64StringSplit) // Removing the base64 prefix
+        }
+
+        // Event listener for any error
+        reader.onerror = () => {
+            reject(new Error("Failed to convert file to base64"))
+        }
+
+        // Reading the file as a data URL (which contains base64 encoded string)
+        reader.readAsDataURL(file)
+    })
+}
+
+export async function patchParticipantInfo(info: ParticipantInfo) {
+    const payload: any = info
+    if (info.study_proof) {
+        payload.study_proof = await getBase64(info.study_proof)
+    } else {
+        payload.study_proof = ""
+    }
+    if (info.photo) {
+        payload.photo = await getBase64(info.photo)
+    } else {
+        payload.photo = ""
+    }
+    if (info.cv) {
+        payload.cv = await getBase64(info.cv)
+    } else {
+        payload.cv = ""
+    }
+    return await fetch_patch("/participant", payload)
+}
+
+export async function getParticipant(id: string) {
+    const response = await fetch_get("/participant/" + id)
+    if (!response) {
+        return undefined
+    }
+    return await response.json()
+}
diff --git a/client/src/routes/AdditionalForm.tsx b/client/src/routes/AdditionalForm.tsx
index 16c04e3e0a80a063c509da0fc2978dc7c48a4eac..378b7fb6cb6bede2f7855b2acf7f1157a998f48c 100644
--- a/client/src/routes/AdditionalForm.tsx
+++ b/client/src/routes/AdditionalForm.tsx
@@ -1,113 +1,18 @@
-import { createForm, SubmitHandler } from "@modular-forms/solid"
 import FixedImage from "../components/FixedImage"
-import { useNavigate } from "@solidjs/router"
+import { AdditionalInfoForm } from "../components/forms/AdditionnalInfoForm"
 import { ProtectedRoute } from "../components/ProtectedRoute"
-import { Participant } from "../binding/Participant"
 
 export default function AdditionalForm() {
-    const navigate = useNavigate()
-    const [_loginForm, { Form, Field }] = createForm<Participant>()
-
-    const handleSubmit: SubmitHandler<Participant> = (values, event) => {
-        event.preventDefault()
-        console.log(values)
-        navigate("/leader")
-    }
-
-    interface Props {
-        id: any
-        name: string
-    }
-
-    function TextField(prop: Props) {
-        return (
-            <Field name={prop.id}>
-                {(_field, props) => (
-                    <div>
-                        <label
-                            for={prop.id}
-                            class="block text-sm font-medium leading-6 text-gray-900"
-                        >
-                            {prop.name}
-                        </label>
-                        <div class="mt-2">
-                            <input
-                                {...props}
-                                id={prop.id}
-                                name={prop.id}
-                                type="text"
-                                required
-                                class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-light-highlight sm:text-sm sm:leading-6"
-                            />
-                        </div>
-                    </div>
-                )}
-            </Field>
-        )
-    }
-
     return (
         <ProtectedRoute>
             <div class="flex w-full flex-col items-center justify-center">
                 <FixedImage url="/banners/documents.svg" height="32rem">
                     <h1 class="text-center font-futur text-6xl text-white">
-                        {"Tableau de bord des chefs"}
+                        {"Tableau de bord"}
                     </h1>
                 </FixedImage>
-                <div class="-mt-32 sm:mx-auto sm:w-full sm:max-w-sm">
-                    <Form
-                        class="space-y-6"
-                        action="#"
-                        method="post"
-                        onSubmit={handleSubmit}
-                    >
-                        <TextField
-                            id="medical_conditions"
-                            name="Conditions médicales"
-                        />
-                        <TextField id="allergies" name="Allergies" />
-                        <TextField id="pronouns" name="Pronoms" />
-                        <TextField
-                            id="phone_number"
-                            name="Numéro de téléphone"
-                        />
-                        <TextField id="tshirt_size" name="Taille de T-shirt" />
-                        <TextField id="comments" name="Commentaires" />
-                        <TextField
-                            id="emergency_contact"
-                            name="Contact d'urgence"
-                        />
-
-                        <Field name="has_monthly_opus_card">
-                            {(_field, props) => (
-                                <div class="flex items-center">
-                                    <input
-                                        {...props}
-                                        id="has_monthly_opus_card"
-                                        type="checkbox"
-                                        value=""
-                                        class="h-4 w-4 rounded border-gray-300 bg-gray-100 text-blue-600 focus:ring-2 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:ring-offset-gray-800 dark:focus:ring-blue-600"
-                                    />
-                                    <label
-                                        for="has_monthly_opus_card"
-                                        class="ms-2 text-sm font-medium text-gray-900 dark:text-gray-300"
-                                    >
-                                        Je possède un abonnement pour la carte
-                                        OPUS.
-                                    </label>
-                                </div>
-                            )}
-                        </Field>
-
-                        <div>
-                            <button
-                                type="submit"
-                                class="flex w-full justify-center rounded-md bg-light-highlight px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-light-highlight focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-light-highlight"
-                            >
-                                Envoyer les renseignements personnels
-                            </button>
-                        </div>
-                    </Form>
+                <div class="-mt-32 flex flex-col items-center">
+                    <AdditionalInfoForm />
                 </div>
             </div>
         </ProtectedRoute>
diff --git a/client/src/routes/Dashboard.tsx b/client/src/routes/Dashboard.tsx
index 0816014efd080148712d7338d6d8af461311ee6d..b404f89634669547a989f659fe79ab229c29fecc 100644
--- a/client/src/routes/Dashboard.tsx
+++ b/client/src/routes/Dashboard.tsx
@@ -37,9 +37,14 @@ export default function Dashboard() {
                     <PrefetchLink to="/additional-form" file="AdditionalForm">
                         <BigButton text="Changer mes renseignements personnels" />
                     </PrefetchLink>
-                    <PrefetchLink to="/list-participant" file="ListParticipant">
-                        <BigButton text="Liste des participants" />
-                    </PrefetchLink>
+                    {localStorage.getItem("role") !== "participant" && (
+                        <PrefetchLink
+                            to="/list-participant"
+                            file="ListParticipant"
+                        >
+                            <BigButton text="Liste des participants" />
+                        </PrefetchLink>
+                    )}
                     <PrefetchLink to="/change-password" file="ChangePassword">
                         <BigButton text="Changer le mot de passe" />
                     </PrefetchLink>
diff --git a/client/src/routes/ForgottenPassword.tsx b/client/src/routes/ForgottenPassword.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..fcc7e4d7e6ac738894025ca64cedca9ca5261dea
--- /dev/null
+++ b/client/src/routes/ForgottenPassword.tsx
@@ -0,0 +1,18 @@
+import FixedImage from "../components/FixedImage"
+import { EmailResetForm } from "../components/forms/EmailResetForm"
+import { t } from "../stores/locale"
+
+export default function ForgottenPassword() {
+    return (
+        <div class="flex w-full flex-col items-center justify-center">
+            <FixedImage url="/banners/documents.svg" height="32rem">
+                <h1 class="text-center font-futur text-6xl text-white">
+                    {t("loginPage.forgotPassword")}
+                </h1>
+            </FixedImage>
+            <div class="-mt-32 flex h-full w-full flex-row items-center justify-center gap-4 p-4 font-futur text-xl font-bold">
+                <EmailResetForm />
+            </div>
+        </div>
+    )
+}
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000000000000000000000000000000000000..b706e5ac9de007b3d16b6fabe4c5c4318e2150fc
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,61 @@
+{
+  "nodes": {
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1729413321,
+        "narHash": "sha256-I4tuhRpZFa6Fu6dcH9Dlo5LlH17peT79vx1y1SpeKt0=",
+        "owner": "nixos",
+        "repo": "nixpkgs",
+        "rev": "1997e4aa514312c1af7e2bda7fad1644e778ff26",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nixos",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "nixpkgs": "nixpkgs",
+        "utils": "utils"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "utils": {
+      "inputs": {
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1726560853,
+        "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
index 5a30df4c0efa90d091118e19c56433fddc628653..c93f588a8c1b0def16ac2c56ccc98340554ee3c0 100644
--- a/flake.nix
+++ b/flake.nix
@@ -29,12 +29,12 @@
           packages = with pkgs; [
             bun
           ];
-          DB_USER="postgres";
-          DB_PASSWORD="password";
-          DB_NAME="dev";
-          DB_PORT="5432";
-          DB_HOST="localhost";
-          DATABASE_URL="postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}";
+          POSTGRES_USER="postgres";
+          POSTGRES_PASSWORD="password";
+          POSTGRES_NAME="dev";
+          POSTGRES_PORT="5432";
+          POSTGRES_HOST="localhost";
+          DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_NAME}";
 
           TS_RS_EXPORT_DIR = "../client/src/binding";
           LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ pkgs.openssl ];
diff --git a/server/.sqlx/query-01bd25a5698e76cdec3ae0eb1a638059914202a09aa606af11f38d7848f37c67.json b/server/.sqlx/query-01bd25a5698e76cdec3ae0eb1a638059914202a09aa606af11f38d7848f37c67.json
deleted file mode 100644
index 4f74f8d77594a8f983649021ed0c37be7bdfbeb5..0000000000000000000000000000000000000000
--- a/server/.sqlx/query-01bd25a5698e76cdec3ae0eb1a638059914202a09aa606af11f38d7848f37c67.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "db_name": "PostgreSQL",
-  "query": "UPDATE participants SET (medical_conditions, allergies, supper, pronouns, competition, phone_number, tshirt_size, comments, emergency_contact, has_monthly_opus_card, reduced_mobility, study_proof, photo, cv)\n                = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) WHERE id = $15",
-  "describe": {
-    "columns": [],
-    "parameters": {
-      "Left": [
-        "Text",
-        "Text",
-        "Text",
-        "Text",
-        {
-          "Custom": {
-            "name": "competition",
-            "kind": {
-              "Enum": [
-                "none",
-                "conception_senior",
-                "conception_junior",
-                "debats_oratoires",
-                "reingenierie",
-                "genie_conseil",
-                "communication_scientifique",
-                "programmation",
-                "conception_innovatrice",
-                "cycle_superieur"
-              ]
-            }
-          }
-        },
-        "Text",
-        "Text",
-        "Text",
-        "Text",
-        "Bool",
-        "Text",
-        "Bytea",
-        "Bytea",
-        "Bytea",
-        "Uuid"
-      ]
-    },
-    "nullable": []
-  },
-  "hash": "01bd25a5698e76cdec3ae0eb1a638059914202a09aa606af11f38d7848f37c67"
-}
diff --git a/server/.sqlx/query-11746d3bbe0047f2995a6366ba00cfd84d0dbc1c83bef77cfc83af19e69d5b94.json b/server/.sqlx/query-11746d3bbe0047f2995a6366ba00cfd84d0dbc1c83bef77cfc83af19e69d5b94.json
index 769fa9905f54a907d716ccb1585bf552ecd22650..2cd25e169e027ed22cf1ec5cfa5ac5786afccb0b 100644
--- a/server/.sqlx/query-11746d3bbe0047f2995a6366ba00cfd84d0dbc1c83bef77cfc83af19e69d5b94.json
+++ b/server/.sqlx/query-11746d3bbe0047f2995a6366ba00cfd84d0dbc1c83bef77cfc83af19e69d5b94.json
@@ -42,7 +42,29 @@
             }
           }
         },
-        "Text"
+        {
+          "Custom": {
+            "name": "university",
+            "kind": {
+              "Enum": [
+                "uqac",
+                "uqar",
+                "uqat",
+                "uqo",
+                "uqtr",
+                "mcgill",
+                "mcgill_macdonald",
+                "concordia",
+                "ets",
+                "polymtl",
+                "ulaval",
+                "ulaval-agriculture",
+                "uds",
+                "none"
+              ]
+            }
+          }
+        }
       ]
     },
     "nullable": []
diff --git a/server/.sqlx/query-668d7e49b4dae36348dbddca35bd8292cb59f2c0f8c20f4d0ac5faf058b183ac.json b/server/.sqlx/query-668d7e49b4dae36348dbddca35bd8292cb59f2c0f8c20f4d0ac5faf058b183ac.json
index e8d8cfab73ac0d12780207ac5dfe3f93188d66d0..db0e348f87eeaa1e60014bcdaa9c2e1efcee4ccc 100644
--- a/server/.sqlx/query-668d7e49b4dae36348dbddca35bd8292cb59f2c0f8c20f4d0ac5faf058b183ac.json
+++ b/server/.sqlx/query-668d7e49b4dae36348dbddca35bd8292cb59f2c0f8c20f4d0ac5faf058b183ac.json
@@ -6,7 +6,29 @@
     "parameters": {
       "Left": [
         "Uuid",
-        "Text"
+        {
+          "Custom": {
+            "name": "university",
+            "kind": {
+              "Enum": [
+                "uqac",
+                "uqar",
+                "uqat",
+                "uqo",
+                "uqtr",
+                "mcgill",
+                "mcgill_macdonald",
+                "concordia",
+                "ets",
+                "polymtl",
+                "ulaval",
+                "ulaval-agriculture",
+                "uds",
+                "none"
+              ]
+            }
+          }
+        }
       ]
     },
     "nullable": []
diff --git a/server/.sqlx/query-8e6f6c7229ba7d13f4690c70229bac29698bbccae3adfb0f2cdcdff1daa9fe15.json b/server/.sqlx/query-8e6f6c7229ba7d13f4690c70229bac29698bbccae3adfb0f2cdcdff1daa9fe15.json
new file mode 100644
index 0000000000000000000000000000000000000000..34f167eaf2146e1ca99811d668eac3bd1041698a
--- /dev/null
+++ b/server/.sqlx/query-8e6f6c7229ba7d13f4690c70229bac29698bbccae3adfb0f2cdcdff1daa9fe15.json
@@ -0,0 +1,68 @@
+{
+  "db_name": "PostgreSQL",
+  "query": "SELECT id, role AS \"role: Role\", university AS \"university: University\" FROM participants WHERE email = $1",
+  "describe": {
+    "columns": [
+      {
+        "ordinal": 0,
+        "name": "id",
+        "type_info": "Uuid"
+      },
+      {
+        "ordinal": 1,
+        "name": "role: Role",
+        "type_info": {
+          "Custom": {
+            "name": "role",
+            "kind": {
+              "Enum": [
+                "participant",
+                "organizer",
+                "volunteer",
+                "chef"
+              ]
+            }
+          }
+        }
+      },
+      {
+        "ordinal": 2,
+        "name": "university: University",
+        "type_info": {
+          "Custom": {
+            "name": "university",
+            "kind": {
+              "Enum": [
+                "uqac",
+                "uqar",
+                "uqat",
+                "uqo",
+                "uqtr",
+                "mcgill",
+                "mcgill_macdonald",
+                "concordia",
+                "ets",
+                "polymtl",
+                "ulaval",
+                "ulaval-agriculture",
+                "uds",
+                "none"
+              ]
+            }
+          }
+        }
+      }
+    ],
+    "parameters": {
+      "Left": [
+        "Text"
+      ]
+    },
+    "nullable": [
+      false,
+      false,
+      false
+    ]
+  },
+  "hash": "8e6f6c7229ba7d13f4690c70229bac29698bbccae3adfb0f2cdcdff1daa9fe15"
+}
diff --git a/server/.sqlx/query-4ba558a81017dfe3d22e15a97f7e57e8a5404d9910102f7bd87eb9b887e97fcb.json b/server/.sqlx/query-a902b8930ff8374bde666f05bbab23a168364c617c4de636fe799cf00f8bc16b.json
similarity index 53%
rename from server/.sqlx/query-4ba558a81017dfe3d22e15a97f7e57e8a5404d9910102f7bd87eb9b887e97fcb.json
rename to server/.sqlx/query-a902b8930ff8374bde666f05bbab23a168364c617c4de636fe799cf00f8bc16b.json
index 9c528615386e95f606d73bf734a1aa0963a53f9c..5ef37548fba369ddac240234ce3b4e192708889c 100644
--- a/server/.sqlx/query-4ba558a81017dfe3d22e15a97f7e57e8a5404d9910102f7bd87eb9b887e97fcb.json
+++ b/server/.sqlx/query-a902b8930ff8374bde666f05bbab23a168364c617c4de636fe799cf00f8bc16b.json
@@ -1,6 +1,6 @@
 {
   "db_name": "PostgreSQL",
-  "query": "SELECT id, role AS \"role: Role\", password_hash, university FROM participants WHERE email = $1",
+  "query": "SELECT id, role AS \"role: Role\", password_hash, university AS \"university: University\" FROM participants WHERE email = $1",
   "describe": {
     "columns": [
       {
@@ -32,8 +32,30 @@
       },
       {
         "ordinal": 3,
-        "name": "university",
-        "type_info": "Text"
+        "name": "university: University",
+        "type_info": {
+          "Custom": {
+            "name": "university",
+            "kind": {
+              "Enum": [
+                "uqac",
+                "uqar",
+                "uqat",
+                "uqo",
+                "uqtr",
+                "mcgill",
+                "mcgill_macdonald",
+                "concordia",
+                "ets",
+                "polymtl",
+                "ulaval",
+                "ulaval-agriculture",
+                "uds",
+                "none"
+              ]
+            }
+          }
+        }
       }
     ],
     "parameters": {
@@ -48,5 +70,5 @@
       false
     ]
   },
-  "hash": "4ba558a81017dfe3d22e15a97f7e57e8a5404d9910102f7bd87eb9b887e97fcb"
+  "hash": "a902b8930ff8374bde666f05bbab23a168364c617c4de636fe799cf00f8bc16b"
 }
diff --git a/server/.sqlx/query-b2cf8ace57c4a960f64b49060612f3c4918a7eb20626e5827dd2ebd0b5c65294.json b/server/.sqlx/query-b2cf8ace57c4a960f64b49060612f3c4918a7eb20626e5827dd2ebd0b5c65294.json
new file mode 100644
index 0000000000000000000000000000000000000000..746f3d3cd9ed62f5f2696605234d9c9d493fac42
--- /dev/null
+++ b/server/.sqlx/query-b2cf8ace57c4a960f64b49060612f3c4918a7eb20626e5827dd2ebd0b5c65294.json
@@ -0,0 +1,41 @@
+{
+  "db_name": "PostgreSQL",
+  "query": "UPDATE participants SET (medical_conditions, allergies, is_vegetarian, pronouns, phone_number, tshirt_size, comments, emergency_contact, has_monthly_opus_card, reduced_mobility, study_proof, photo, cv)\n                = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) WHERE id = $14",
+  "describe": {
+    "columns": [],
+    "parameters": {
+      "Left": [
+        "Text",
+        "Text",
+        "Bool",
+        "Text",
+        "Text",
+        {
+          "Custom": {
+            "name": "tshirt_size",
+            "kind": {
+              "Enum": [
+                "xs",
+                "s",
+                "m",
+                "l",
+                "xl",
+                "xxl"
+              ]
+            }
+          }
+        },
+        "Text",
+        "Text",
+        "Bool",
+        "Text",
+        "Bytea",
+        "Bytea",
+        "Bytea",
+        "Uuid"
+      ]
+    },
+    "nullable": []
+  },
+  "hash": "b2cf8ace57c4a960f64b49060612f3c4918a7eb20626e5827dd2ebd0b5c65294"
+}
diff --git a/server/.sqlx/query-e08b705c8f710fe9496a9b72c258fed4cd4c7952a9c5cb2a6f8e5564758c3fce.json b/server/.sqlx/query-e08b705c8f710fe9496a9b72c258fed4cd4c7952a9c5cb2a6f8e5564758c3fce.json
deleted file mode 100644
index 59756034a61f8b1062a8ec64744fad4586f8cb26..0000000000000000000000000000000000000000
--- a/server/.sqlx/query-e08b705c8f710fe9496a9b72c258fed4cd4c7952a9c5cb2a6f8e5564758c3fce.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "db_name": "PostgreSQL",
-  "query": "SELECT id, role AS \"role: Role\", university FROM participants WHERE email = $1",
-  "describe": {
-    "columns": [
-      {
-        "ordinal": 0,
-        "name": "id",
-        "type_info": "Uuid"
-      },
-      {
-        "ordinal": 1,
-        "name": "role: Role",
-        "type_info": {
-          "Custom": {
-            "name": "role",
-            "kind": {
-              "Enum": [
-                "participant",
-                "organizer",
-                "volunteer",
-                "chef"
-              ]
-            }
-          }
-        }
-      },
-      {
-        "ordinal": 2,
-        "name": "university",
-        "type_info": "Text"
-      }
-    ],
-    "parameters": {
-      "Left": [
-        "Text"
-      ]
-    },
-    "nullable": [
-      false,
-      false,
-      false
-    ]
-  },
-  "hash": "e08b705c8f710fe9496a9b72c258fed4cd4c7952a9c5cb2a6f8e5564758c3fce"
-}
diff --git a/server/launch_db.sh b/server/launch_db.sh
index 82ab1660e23fa88ce54eb34844d0b467536181fb..3743a2e2a213b3efd0d28544a8b5e3d7b77a7361 100755
--- a/server/launch_db.sh
+++ b/server/launch_db.sh
@@ -14,17 +14,17 @@ set -x
 set -eo pipefail
 
 docker run \
-    -e POSTGRES_USER=${DB_USER} \
-    -e POSTGRES_PASSWORD=${DB_PASSWORD} \
-    -p "${DB_PORT}":5432 \
+    -e POSTGRES_USER=${POSTGRES_USER} \
+    -e POSTGRES_PASSWORD=${POSTGRES_PASSWORD} \
+    -p "${POSTGRES_PORT}":5432 \
     -d postgres
 
-export PGPASSWORD=${DB_PASSWORD}
+export PGPASSWORD=${POSTGRES_PASSWORD}
 until psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -p "${POSTGRES_PORT}" -d "postgres" -c '\q'; do
   >&2 echo "Postgres is unavailable - sleeping"
   sleep 1
 done
 
->&2 echo "Postgres is up and running on port ${DB_PORT}"
+>&2 echo "Postgres is up and running on port ${POSTGRES_PORT}"
 
 bash configure_db.sh
diff --git a/server/migrations/20241015182258_create_participants_table.sql b/server/migrations/20241015182258_create_participants_table.sql
index 3c404ab8d14c6b99d50e370c123fba965eb4a737..e9eefbaccd8bfdd80644e28dd0b0bbf147520e50 100644
--- a/server/migrations/20241015182258_create_participants_table.sql
+++ b/server/migrations/20241015182258_create_participants_table.sql
@@ -2,6 +2,10 @@ CREATE TYPE ROLE AS ENUM ('participant', 'organizer', 'volunteer', 'chef');
 
 CREATE TYPE COMPETITION AS ENUM ('none', 'conception_senior', 'conception_junior', 'debats_oratoires', 'reingenierie', 'genie_conseil', 'communication_scientifique', 'programmation', 'conception_innovatrice', 'cycle_superieur');
 
+CREATE TYPE UNIVERSITY AS ENUM ('uqac', 'uqar', 'uqat', 'uqo', 'uqtr', 'mcgill', 'mcgill_macdonald', 'concordia', 'ets', 'polymtl', 'ulaval', 'ulaval-agriculture', 'uds', 'none');
+
+CREATE TYPE TSHIRT_SIZE AS ENUM ('xs', 's', 'm', 'l', 'xl', 'xxl');
+
 CREATE TABLE participants (
     id UUID PRIMARY KEY,
     role ROLE NOT NULL,
@@ -10,13 +14,14 @@ CREATE TABLE participants (
     first_name TEXT NOT NULL,
     last_name TEXT NOT NULL,
     competition COMPETITION NOT NULL,
-    university TEXT NOT NULL,
+    university UNIVERSITY NOT NULL,
     medical_conditions TEXT,
     allergies TEXT,
     supper TEXT,
+    is_vegetarian BOOLEAN,
     pronouns TEXT,
     phone_number TEXT,
-    tshirt_size TEXT,
+    tshirt_size TSHIRT_SIZE,
     comments TEXT,
     emergency_contact TEXT,
     has_monthly_opus_card BOOLEAN,
diff --git a/server/src/auth/claims.rs b/server/src/auth/claims.rs
index d6cd920974a67872a7d653ca0aba957f6f0a1e0d..72dc09125baddfa83930d35cf5f00bd1ccd9fb63 100644
--- a/server/src/auth/claims.rs
+++ b/server/src/auth/claims.rs
@@ -1,4 +1,4 @@
-use crate::model::role::Role;
+use crate::model::{role::Role, university::University};
 use argon2::{password_hash::PasswordVerifier, Argon2, PasswordHash};
 use axum::{async_trait, extract::FromRequestParts, http::request::Parts, RequestPartsExt};
 use axum_extra::{
@@ -9,17 +9,19 @@ use chrono::Utc;
 use jsonwebtoken::{decode, Validation};
 use serde::{Deserialize, Serialize};
 use sqlx::PgPool;
+use ts_rs::TS;
 use uuid::Uuid;
 
 use crate::KEYS;
 
 use super::auth_error::AuthError;
 
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, TS)]
+#[ts(export)]
 pub struct Claims {
     pub id: Uuid,
     pub role: Role,
-    pub university: String,
+    pub university: University,
     pub exp: usize,
 }
 
@@ -33,7 +35,7 @@ impl Claims {
             .and_utc()
             .timestamp() as usize;
         let info = sqlx::query!(
-            r#"SELECT id, role AS "role: Role", university FROM participants WHERE email = $1"#,
+            r#"SELECT id, role AS "role: Role", university AS "university: University" FROM participants WHERE email = $1"#,
             email
         )
         .fetch_one(db)
@@ -51,7 +53,7 @@ impl Claims {
     }
     pub async fn new(email: String, password: String, db: &PgPool) -> Option<Self> {
         let user = sqlx::query!(
-            r#"SELECT id, role AS "role: Role", password_hash, university FROM participants WHERE email = $1"#,
+            r#"SELECT id, role AS "role: Role", password_hash, university AS "university: University" FROM participants WHERE email = $1"#,
             email
         )
         .fetch_one(db)
diff --git a/server/src/bin/create_admin.rs b/server/src/bin/create_admin.rs
index a878bf8e48a40deac20992a31bb85ed8e5b97241..e421db26b1c67c0d4cf1faa9feda94ececdaff18 100644
--- a/server/src/bin/create_admin.rs
+++ b/server/src/bin/create_admin.rs
@@ -1,5 +1,8 @@
 use backend_cqi::{
-    model::{competition::Competition, minimal_participant::MinimalParticipant, role::Role},
+    model::{
+        competition::Competition, minimal_participant::MinimalParticipant, role::Role,
+        university::University,
+    },
     Result,
 };
 use rand::distributions::{Alphanumeric, DistString};
@@ -18,10 +21,9 @@ async fn main() -> Result<()> {
         email: "mamanningham@cqi-qec.qc.ca".to_string(),
         competition: Competition::None,
         role: Role::Organizer,
+        university: University::Polymtl,
     };
-    participant
-        .write_to_database(&password, &db, "".to_string())
-        .await?;
+    participant.write_to_database(&password, &db).await?;
     println!("Password: {}", password);
     Ok(())
 }
diff --git a/server/src/model/minimal_participant.rs b/server/src/model/minimal_participant.rs
index 1461713243f9c38fed1e34d15bf73f1a2d2e9e81..e96af409caa681df131a24849a68ecfc3282560a 100644
--- a/server/src/model/minimal_participant.rs
+++ b/server/src/model/minimal_participant.rs
@@ -5,7 +5,7 @@ use sqlx::PgPool;
 use ts_rs::TS;
 use uuid::Uuid;
 
-use super::{competition::Competition, role::Role};
+use super::{competition::Competition, role::Role, university::University};
 
 #[derive(Debug, Serialize, Deserialize, TS, sqlx::FromRow)]
 #[ts(export)]
@@ -14,6 +14,7 @@ pub struct MinimalParticipant {
     pub last_name: String,
     pub email: String,
     pub competition: Competition,
+    pub university: University,
     pub role: Role,
 }
 
@@ -24,12 +25,7 @@ impl MinimalParticipant {
             .await
     }
 
-    pub async fn write_to_database(
-        &self,
-        password: &str,
-        db: &PgPool,
-        university: String,
-    ) -> Result<(), sqlx::Error> {
+    pub async fn write_to_database(&self, password: &str, db: &PgPool) -> Result<(), sqlx::Error> {
         let id = Uuid::new_v4();
         tracing::info!("Generated password: {}", password); // TODO: remove this debug line
         let salt = SaltString::generate(&mut OsRng);
@@ -48,7 +44,7 @@ impl MinimalParticipant {
             self.first_name,
             self.last_name,
             self.competition as Competition,
-            university
+            self.university as University
         )
         .execute(db)
         .await?;
diff --git a/server/src/model/mod.rs b/server/src/model/mod.rs
index 5c6b6a99f7e0dfb3a41eaee04b8496911f0d0882..babe45612533fbd96c9c0f86bbd7cec63502ae2e 100644
--- a/server/src/model/mod.rs
+++ b/server/src/model/mod.rs
@@ -1,6 +1,7 @@
 pub mod competition;
 pub mod minimal_participant;
-pub mod participant;
+pub mod participant_info;
 pub mod preview_participant;
 pub mod role;
-pub mod staff;
+pub mod tshirt_size;
+pub mod university;
diff --git a/server/src/model/participant.rs b/server/src/model/participant_info.rs
similarity index 69%
rename from server/src/model/participant.rs
rename to server/src/model/participant_info.rs
index c6d9aa834ed359dfad1ab4a157b494371392364a..834ee49439d84d1680931ed901ad80b9df6b9dfb 100644
--- a/server/src/model/participant.rs
+++ b/server/src/model/participant_info.rs
@@ -5,25 +5,20 @@ use sqlx::PgPool;
 use ts_rs::TS;
 use uuid::Uuid;
 
-use super::{competition::Competition, role::Role};
 use crate::utility::{deserialize_base64, serialize_base64};
 
+use super::{tshirt_size::TshirtSize, university::University};
+
 #[derive(Debug, Serialize, Deserialize, sqlx::FromRow, TS)]
 #[ts(export)]
-pub struct Participant {
-    pub id: Uuid,
-    pub role: Role,
-    pub email: String,
-    pub first_name: String,
-    pub last_name: String,
-    pub university: String,
+pub struct ParticipantInfo {
     pub medical_conditions: Option<String>,
     pub allergies: Option<String>,
     pub pronouns: Option<String>,
     pub supper: Option<String>,
-    pub competition: Option<Competition>,
+    pub is_vegetarian: Option<bool>,
     pub phone_number: Option<String>,
-    pub tshirt_size: Option<String>,
+    pub tshirt_size: Option<TshirtSize>,
     pub comments: Option<String>,
     pub emergency_contact: Option<String>,
     pub has_monthly_opus_card: Option<bool>,
@@ -32,41 +27,52 @@ pub struct Participant {
         serialize_with = "serialize_base64",
         deserialize_with = "deserialize_base64"
     )]
-    #[ts(type = "string")]
+    #[ts(type = "File")]
     pub study_proof: Option<Vec<u8>>,
     #[serde(
         serialize_with = "serialize_base64",
         deserialize_with = "deserialize_base64"
     )]
-    #[ts(type = "string")]
+    #[ts(type = "File")]
     pub photo: Option<Vec<u8>>,
     #[serde(
         serialize_with = "serialize_base64",
         deserialize_with = "deserialize_base64"
     )]
-    #[ts(type = "string")]
+    #[ts(type = "File")]
     pub cv: Option<Vec<u8>>,
 }
 
-impl Participant {
-    pub async fn get_participant(db: &PgPool) -> Result<Self, sqlx::Error> {
+impl ParticipantInfo {
+    pub async fn get_participant(id: Uuid, db: &PgPool) -> Result<Self, sqlx::Error> {
         sqlx::query_as("SELECT * FROM participants WHERE id = $1")
-            .bind(Uuid::new_v4())
+            .bind(id)
+            .fetch_one(db)
+            .await
+    }
+
+    pub async fn get_participant_with_university(
+        id: Uuid,
+        university: University,
+        db: &PgPool,
+    ) -> Result<Self, sqlx::Error> {
+        sqlx::query_as("SELECT * FROM participants WHERE id = $1 AND university = $2")
+            .bind(id)
+            .bind(university)
             .fetch_one(db)
             .await
     }
 
-    pub async fn write_to_database(&self, db: &PgPool) -> Result<(), sqlx::Error> {
+    pub async fn write_to_database(&self, id: Uuid, db: &PgPool) -> Result<(), sqlx::Error> {
         sqlx::query!(
-                r#"UPDATE participants SET (medical_conditions, allergies, supper, pronouns, competition, phone_number, tshirt_size, comments, emergency_contact, has_monthly_opus_card, reduced_mobility, study_proof, photo, cv)
-                = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) WHERE id = $15"#,
+                r#"UPDATE participants SET (medical_conditions, allergies, is_vegetarian, pronouns, phone_number, tshirt_size, comments, emergency_contact, has_monthly_opus_card, reduced_mobility, study_proof, photo, cv)
+                = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) WHERE id = $14"#,
                 self.medical_conditions,
                 self.allergies,
-                self.supper,
+                self.is_vegetarian,
                 self.pronouns,
-                self.competition as Option<Competition>,
                 self.phone_number,
-                self.tshirt_size,
+                self.tshirt_size as Option<TshirtSize>,
                 self.comments,
                 self.emergency_contact,
                 self.has_monthly_opus_card,
@@ -74,7 +80,7 @@ impl Participant {
                 self.study_proof,
                 self.photo,
                 self.cv,
-                self.id
+                id
             )
             .execute(db)
             .await?;
@@ -88,15 +94,15 @@ impl Participant {
         Ok(())
     }
 
-    pub async fn delete_from_database_university(
+    pub async fn delete_from_database_with_university(
         id: Uuid,
-        university: String,
+        university: University,
         db: &PgPool,
     ) -> Result<(), sqlx::Error> {
         sqlx::query!(
             r#"DELETE FROM participants WHERE id = $1 AND university = $2"#,
             id,
-            university
+            university as University
         )
         .execute(db)
         .await?;
diff --git a/server/src/model/preview_participant.rs b/server/src/model/preview_participant.rs
index c4f67ddbba4009d81eee6a21328a19d69900f213..79f7d2770d98ae0bf900a43b2b90d67f43069f80 100644
--- a/server/src/model/preview_participant.rs
+++ b/server/src/model/preview_participant.rs
@@ -3,7 +3,7 @@ use sqlx::PgPool;
 use ts_rs::TS;
 use uuid::Uuid;
 
-use super::{competition::Competition, role::Role};
+use super::{competition::Competition, role::Role, university::University};
 
 #[derive(Debug, Serialize, Deserialize, TS, sqlx::FromRow)]
 #[ts(export)]
@@ -14,13 +14,14 @@ pub struct ParticipantPreview {
     pub email: String,
     pub role: Role,
     pub competition: Competition,
+    pub university: University,
     pub contain_cv: bool,
 }
 
 impl ParticipantPreview {
     pub async fn get_participants(db: &PgPool) -> Result<Vec<Self>, sqlx::Error> {
         sqlx::query_as::<_, Self>(
-            r#"SELECT id, first_name, last_name, email, role, competition, cv IS NOT NULL as contain_cv FROM participants"#
+            r#"SELECT id, first_name, last_name, email, role, competition, university, cv IS NOT NULL as contain_cv FROM participants"#
         )
         .fetch_all(db)
         .await
@@ -28,9 +29,9 @@ impl ParticipantPreview {
 
     pub async fn get_participants_from_university(
         db: &PgPool,
-        university: &str,
+        university: University,
     ) -> Result<Vec<Self>, sqlx::Error> {
-        sqlx::query_as("SELECT * FROM participants WHERE university_name = $1")
+        sqlx::query_as("SELECT id, first_name, last_name, email, role, competition, university, cv IS NOT NULL as contain_cv FROM participants WHERE university = $1 AND (role = 'participant' OR role = 'chef')")
             .bind(university)
             .fetch_all(db)
             .await
diff --git a/server/src/model/role.rs b/server/src/model/role.rs
index af2ee8ae026a4ed7a0e90999beed7c2e82764ac9..5c49f9faee4d6c95b99feb644de49dc5927da9c8 100644
--- a/server/src/model/role.rs
+++ b/server/src/model/role.rs
@@ -1,7 +1,7 @@
 use serde::{Deserialize, Serialize};
 use ts_rs::TS;
 
-#[derive(Copy, Clone, Debug, Serialize, Deserialize, sqlx::Type, TS)]
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, sqlx::Type, TS)]
 #[serde(rename_all = "snake_case")]
 #[sqlx(rename_all = "snake_case", type_name = "ROLE")]
 #[ts(export)]
diff --git a/server/src/model/staff.rs b/server/src/model/staff.rs
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/server/src/model/tshirt_size.rs b/server/src/model/tshirt_size.rs
new file mode 100644
index 0000000000000000000000000000000000000000..4aa1ec98125b39db1b6ab4621f2a517df2d0b4c1
--- /dev/null
+++ b/server/src/model/tshirt_size.rs
@@ -0,0 +1,15 @@
+use serde::{Deserialize, Serialize};
+use ts_rs::TS;
+
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, sqlx::Type, TS)]
+#[serde(rename_all = "snake_case")]
+#[sqlx(rename_all = "snake_case", type_name = "TSHIRT_SIZE")]
+#[ts(export)]
+pub enum TshirtSize {
+    Xs,
+    S,
+    M,
+    L,
+    Xl,
+    Xxl,
+}
diff --git a/server/src/model/university.rs b/server/src/model/university.rs
new file mode 100644
index 0000000000000000000000000000000000000000..882aaf173af8976210f2526b57bab09a92e69462
--- /dev/null
+++ b/server/src/model/university.rs
@@ -0,0 +1,23 @@
+use serde::{Deserialize, Serialize};
+use ts_rs::TS;
+
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, sqlx::Type, TS)]
+#[serde(rename_all = "snake_case")]
+#[sqlx(rename_all = "snake_case", type_name = "UNIVERSITY")]
+#[ts(export)]
+pub enum University {
+    Uqac,
+    Uqar,
+    Uqat,
+    Uqo,
+    Uqtr,
+    Mcgill,
+    McgillMacdonald,
+    Concordia,
+    Ets,
+    Polymtl,
+    Ulaval,
+    UlavalAgriculture,
+    Uds,
+    None,
+}
diff --git a/server/src/routes/change_password.rs b/server/src/routes/change_password.rs
index d51da8807a78359785c32bb5c94c54f7da2ac5dd..6997315e76d441e9c0ec4612a7670d1a1ae4b8a6 100644
--- a/server/src/routes/change_password.rs
+++ b/server/src/routes/change_password.rs
@@ -6,7 +6,7 @@ use serde::Deserialize;
 use ts_rs::TS;
 
 use crate::auth::claims::Claims;
-use crate::model::participant::Participant;
+use crate::model::participant_info::ParticipantInfo;
 use crate::SharedState;
 
 #[derive(Deserialize, TS)]
@@ -20,7 +20,7 @@ pub async fn change_password(
     State(state): State<SharedState>,
     Json(password): Json<ChangePasswordPayload>,
 ) -> impl IntoResponse {
-    match Participant::change_password(claims.id, password.new_password, &state.db).await {
+    match ParticipantInfo::change_password(claims.id, password.new_password, &state.db).await {
         Ok(_) => (StatusCode::OK, "Password changed".to_string()),
         Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
     }
diff --git a/server/src/routes/delete_participant.rs b/server/src/routes/delete_participant.rs
index d377925ea6de2fb662f9125acaef01f24abf053c..b9d325629c76fa2f7750a825ff3f6771b26a6869 100644
--- a/server/src/routes/delete_participant.rs
+++ b/server/src/routes/delete_participant.rs
@@ -7,7 +7,7 @@ use uuid::Uuid;
 
 use crate::{
     auth::claims::Claims,
-    model::{participant::Participant, role::Role},
+    model::{participant_info::ParticipantInfo, role::Role},
     SharedState,
 };
 
@@ -17,13 +17,17 @@ pub async fn delete_participant(
     Path(id): Path<Uuid>,
 ) -> impl IntoResponse {
     match claims.role {
-        Role::Organizer => match Participant::delete_from_database(id, &state.db).await {
+        Role::Organizer => match ParticipantInfo::delete_from_database(id, &state.db).await {
             Ok(_) => (StatusCode::CREATED, "Participant deleted".to_string()),
             Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
         },
         Role::Chef => {
-            match Participant::delete_from_database_university(id, claims.university, &state.db)
-                .await
+            match ParticipantInfo::delete_from_database_with_university(
+                id,
+                claims.university,
+                &state.db,
+            )
+            .await
             {
                 Ok(_) => (StatusCode::CREATED, "Participant deleted".to_string()),
                 Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
diff --git a/server/src/routes/get_participant.rs b/server/src/routes/get_participant.rs
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d074f127bfb3755dbcd568f7513ac37a5fd5bfe9 100644
--- a/server/src/routes/get_participant.rs
+++ b/server/src/routes/get_participant.rs
@@ -0,0 +1,50 @@
+use axum::extract::{Path, State};
+use axum::http::StatusCode;
+use axum::response::IntoResponse;
+use axum::Json;
+use uuid::Uuid;
+
+use crate::model::participant_info::ParticipantInfo;
+use crate::{auth::claims::Claims, model::role::Role, SharedState};
+
+pub async fn get_participant(
+    claims: Claims,
+    State(state): State<SharedState>,
+    Path(id): Path<Uuid>,
+) -> impl IntoResponse {
+    match claims.role {
+        Role::Organizer | Role::Volunteer => {
+            match ParticipantInfo::get_participant(id, &state.db).await {
+                Ok(participant) => (StatusCode::OK, Json(participant)).into_response(),
+                Err(e) => {
+                    tracing::error!("Failed to get participant: {}", e);
+                    (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response()
+                }
+            }
+        }
+        Role::Chef => {
+            match ParticipantInfo::get_participant_with_university(id, claims.university, &state.db)
+                .await
+            {
+                Ok(participant) => (StatusCode::OK, Json(participant)).into_response(),
+                Err(e) => {
+                    tracing::error!("Failed to get participant: {}", e);
+                    (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response()
+                }
+            }
+        }
+        Role::Participant => {
+            if id == claims.id {
+                match ParticipantInfo::get_participant(id, &state.db).await {
+                    Ok(participant) => (StatusCode::OK, Json(participant)).into_response(),
+                    Err(e) => {
+                        tracing::error!("Failed to get participant: {}", e);
+                        (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response()
+                    }
+                }
+            } else {
+                (StatusCode::FORBIDDEN, "Forbidden").into_response()
+            }
+        }
+    }
+}
diff --git a/server/src/routes/get_participants.rs b/server/src/routes/get_participants.rs
index 4240c5ebdccd15fe9cf69fb0d6793a7aeea4b3cc..4011c653dff8b15eb243f9942e1fbd7d7b2bb7c1 100644
--- a/server/src/routes/get_participants.rs
+++ b/server/src/routes/get_participants.rs
@@ -21,11 +21,8 @@ pub async fn get_participants(
             }
         }
         Role::Chef => {
-            match ParticipantPreview::get_participants_from_university(
-                &state.db,
-                &claims.university,
-            )
-            .await
+            match ParticipantPreview::get_participants_from_university(&state.db, claims.university)
+                .await
             {
                 Ok(participants) => return (StatusCode::OK, Json(participants)).into_response(),
                 Err(e) => {
diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs
index dc51889cb1a6e0b631a929e2efa63787795ff81a..7b81b8f34f48675127681c882d33b1890caf826a 100644
--- a/server/src/routes/mod.rs
+++ b/server/src/routes/mod.rs
@@ -8,10 +8,12 @@ use crate::SharedState;
 
 pub mod change_password;
 pub mod delete_participant;
+pub mod get_participant;
 pub mod get_participants;
 pub mod login;
 pub mod new_participant;
 pub mod patch_participant;
+pub mod send_email_reset;
 pub mod test_token;
 
 pub fn api_router(state: SharedState) -> Router {
@@ -23,11 +25,14 @@ pub fn api_router(state: SharedState) -> Router {
         )
         .route(
             "/participant/:id",
-            delete(delete_participant::delete_participant),
+            delete(delete_participant::delete_participant).get(get_participant::get_participant),
         )
         .route("/participants", get(get_participants::get_participants))
         .route("/login", post(login::login))
         .route("/test", get(test_token::test_token))
-        .route("/password", put(change_password::change_password))
+        .route(
+            "/password",
+            put(change_password::change_password).post(send_email_reset::send_email_reset),
+        )
         .with_state(state)
 }
diff --git a/server/src/routes/new_participant.rs b/server/src/routes/new_participant.rs
index a2e7531351be38a11b10017da224ec704ffef91f..c098d1bdf7e52cf69167a7660e694128b55b5a10 100644
--- a/server/src/routes/new_participant.rs
+++ b/server/src/routes/new_participant.rs
@@ -1,15 +1,30 @@
 use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
 use rand::distributions::{Alphanumeric, DistString};
 
-use crate::{auth::claims::Claims, model::minimal_participant::MinimalParticipant, SharedState};
+use crate::{
+    auth::claims::Claims,
+    model::{minimal_participant::MinimalParticipant, role::Role},
+    SharedState,
+};
 
 pub async fn new_participant(
-    _claims: Claims,
+    claims: Claims,
     State(state): State<SharedState>,
     Json(participant): Json<MinimalParticipant>,
 ) -> impl IntoResponse {
     let password = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
 
+    if claims.role == Role::Volunteer || claims.role == Role::Participant {
+        return (StatusCode::FORBIDDEN, "Forbidden").into_response();
+    }
+
+    if claims.role == Role::Chef
+        && ((participant.role == Role::Organizer || participant.role == Role::Volunteer)
+            || participant.university != claims.university)
+    {
+        return (StatusCode::FORBIDDEN, "Forbidden").into_response();
+    }
+
     if let Err(e) = state
         .email
         .lock()
@@ -17,8 +32,7 @@ pub async fn new_participant(
         .send_email(
             "Inscription CQI/QEC 2025",
             format!(
-                r#"
-Bienvenue {} {},
+                r#"Bienvenue {} {},
 Vous avez été inscrit à la compétition CQI/QEC 2025.
 Votre courriel est : {}
 Votre mot de passe est : {}
@@ -30,8 +44,7 @@ You have been registered for the CQI/QEC 2025 competition.
 Your email is : {}
 Your password is : {}
 You can log in at the following address :
-https://cqi-qec.qc.ca/login
-        "#,
+https://cqi-qec.qc.ca/login"#,
                 &participant.first_name,
                 &participant.last_name,
                 &participant.email,
@@ -48,10 +61,7 @@ https://cqi-qec.qc.ca/login
         return (StatusCode::BAD_REQUEST, e.to_string()).into_response();
     };
 
-    if let Err(e) = participant
-        .write_to_database(&password, &state.db, _claims.university)
-        .await
-    {
+    if let Err(e) = participant.write_to_database(&password, &state.db).await {
         return (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response();
     };
 
diff --git a/server/src/routes/patch_participant.rs b/server/src/routes/patch_participant.rs
index 350063c3e280803e6ad99c80e4c77091d11d02f0..2c99769dc2c671c5fcef564186d8b3300ff2b448 100644
--- a/server/src/routes/patch_participant.rs
+++ b/server/src/routes/patch_participant.rs
@@ -1,12 +1,13 @@
 use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
 
-use crate::{model::participant::Participant, SharedState};
+use crate::{auth::claims::Claims, model::participant_info::ParticipantInfo, SharedState};
 
 pub async fn patch_participant(
+    claims: Claims,
     State(state): State<SharedState>,
-    Json(participant): Json<Participant>,
+    Json(participant): Json<ParticipantInfo>,
 ) -> impl IntoResponse {
-    match participant.write_to_database(&state.db).await {
+    match participant.write_to_database(claims.id, &state.db).await {
         Ok(_) => (StatusCode::CREATED, "Participant created".to_string()),
         Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
     }
diff --git a/server/src/routes/send_email_reset.rs b/server/src/routes/send_email_reset.rs
new file mode 100644
index 0000000000000000000000000000000000000000..607baf00563c82bbaedaea8ff0f1d8a26da626ff
--- /dev/null
+++ b/server/src/routes/send_email_reset.rs
@@ -0,0 +1,46 @@
+use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
+use serde::Deserialize;
+use ts_rs::TS;
+
+use crate::{auth::claims::Claims, SharedState};
+
+#[derive(Deserialize, TS)]
+#[ts(export)]
+pub struct EmailResetPayload {
+    email: String,
+}
+
+pub async fn send_email_reset(
+    State(state): State<SharedState>,
+    Json(email): Json<EmailResetPayload>,
+) -> impl IntoResponse {
+    let Some(claims) =
+        Claims::create_token_for_password_reset(email.email.clone(), &state.db).await
+    else {
+        return (StatusCode::BAD_REQUEST, "Email not found".to_string()).into_response();
+    };
+    if let Err(e) = state
+        .email
+        .lock()
+        .await
+        .send_email(
+            "Changement de mot de passe CQI/QEC 2025 password reinitalization",
+            format!(
+                r#"Bonjour,
+Un changement de mot de passe a été demandé pour le compte associé à ce courriel.
+Pour changer votre mot de passe, cliquez sur le lien suivant :
+
+A password change has been requested for the account associated with this email.
+To change your password, click on the following link:
+
+https://cqi-qec.qc.ca/change-password/{}"#,
+                claims
+            ),
+            &email.email,
+        )
+        .await
+    {
+        return (StatusCode::BAD_REQUEST, e.to_string()).into_response();
+    };
+    (StatusCode::OK, "Email sent".to_string()).into_response()
+}
diff --git a/server/src/routes/test_token.rs b/server/src/routes/test_token.rs
index 1c49ec6f745a5bd955a23c42692ef6923bb67b58..684b7065c03f14d66df7fde5bf2a9672b6719842 100644
--- a/server/src/routes/test_token.rs
+++ b/server/src/routes/test_token.rs
@@ -1,14 +1,7 @@
 use axum::{http::StatusCode, response::IntoResponse, Json};
-use serde::{Deserialize, Serialize};
 
-use crate::{auth::claims::Claims, model::role::Role};
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct AuthResponse {
-    pub role: Role,
-}
+use crate::auth::claims::Claims;
 
 pub async fn test_token(claims: Claims) -> impl IntoResponse {
-    let auth = AuthResponse { role: claims.role };
-    (StatusCode::OK, Json(auth)).into_response()
+    (StatusCode::OK, Json(claims)).into_response()
 }