diff --git a/src/client/components/AdvancedSearch.vue b/src/client/components/AdvancedSearch.vue
index 86b49c7f59bb97a1e6b230397f1dcf7a470b0109..2c752a148199dec103d129b0b4280d34faf6f397 100644
--- a/src/client/components/AdvancedSearch.vue
+++ b/src/client/components/AdvancedSearch.vue
@@ -40,7 +40,7 @@
         ORGANISM
         <button
           class="select-all-button"
-          :class="{ 'all-selected': allSelected('species', speciesList) }"
+          :class="{ 'all-selected': allSelected('species', speciesList.length) }"
           type="button"
           @click="selectAll('species', speciesList)"
         >
@@ -53,15 +53,12 @@
           :key="species"
           class="checkbox"
         >
-          <input
-            :id="species.replace(' ', '-') + '-checkbox'"
+          <AppCheckbox
             v-model="filters.species"
             :value="species"
-            type="checkbox"
           >
-          <label :for="species.replace(' ', '-') + '-checkbox'">
             {{ species }}
-          </label>
+          </AppCheckbox>
         </div>
       </div>
     </div>
@@ -71,7 +68,7 @@
         SOURCES
         <button
           class="select-all-button"
-          :class="{ 'all-selected': allSelected('sources', sourcesList) }"
+          :class="{ 'all-selected': allSelected('sources', sourcesList.length) }"
           type="button"
           @click="selectAll('sources', sourcesList)"
         >
@@ -84,15 +81,12 @@
           :key="source"
           class="checkbox"
         >
-          <input
-            :id="source + '-checkbox'"
+          <AppCheckbox
             v-model="filters.sources"
             :value="source"
-            type="checkbox"
           >
-          <label :for="source + '-checkbox'">
             {{ source }}
-          </label>
+          </AppCheckbox>
         </div>
       </div>
     </div>
@@ -102,7 +96,7 @@
         HEAVY CHAIN GENE SEGMENTS
         <button
           class="select-all-button"
-          :class="{ 'all-selected': allSelected('heavySegments', heavySegments) }"
+          :class="{ 'all-selected': allSelected('heavySegments', heavySegments.length) }"
           type="button"
           @click="selectAll('heavySegments', heavySegments)"
         >
@@ -115,15 +109,12 @@
           :key="heavySegment"
           class="checkbox"
         >
-          <input
-            :id="heavySegment + '-checkbox'"
+          <AppCheckbox
             v-model="filters.heavySegments"
             :value="heavySegment"
-            type="checkbox"
           >
-          <label :for="heavySegment + '-checkbox'">
             {{ heavySegment }}
-          </label>
+          </AppCheckbox>
         </div>
       </div>
     </div>
@@ -133,7 +124,7 @@
         LIGHT CHAIN GENE SEGMENTS
         <button
           class="select-all-button"
-          :class="{ 'all-selected': allSelected('lightSegments', lightSegments) }"
+          :class="{ 'all-selected': allSelected('lightSegments', lightSegments.length) }"
           type="button"
           @click="selectAll('lightSegments', lightSegments)"
         >
@@ -146,15 +137,12 @@
           :key="lightSegment"
           class="checkbox"
         >
-          <input
-            :id="lightSegment + '-checkbox'"
+          <AppCheckbox
             v-model="filters.lightSegments"
             :value="lightSegment"
-            type="checkbox"
           >
-          <label :for="lightSegment + '-checkbox'">
             {{ lightSegment }}
-          </label>
+          </AppCheckbox>
         </div>
       </div>
     </div>
@@ -176,6 +164,7 @@ import { type Ref, computed, onMounted, ref } from 'vue'
 import AppDialog from './AppDialog.vue'
 import { useStore } from '../store'
 import { type AdvancedFilters, type FilterChip } from '../types'
+import AppCheckbox from './AppCheckbox.vue';
 
 onMounted(() => {
   if (store.antibodiesSources.length === 0) {
@@ -246,16 +235,28 @@ function updateFilters(): void {
   emit('filtersUpdate', filters.value)
 }
 
-function selectAll(filter: keyof AdvancedFilters, list: Array<string>): void {
+/**
+ * Select all the values of a filter group.
+ * @param filter - The name of the filter group
+ * @param list - The list of values to select
+ */
+function selectAll(filter: keyof AdvancedFilters, list: Readonly<Array<string>>): void {
   if (filters.value[filter].length === list.length) {
     filters.value[filter] = []
   } else {
-    filters.value[filter] = list
+    filters.value[filter] = Array.from(list)
   }
 }
 
-function allSelected(filter: keyof AdvancedFilters, list: Array<string>): boolean {
-  return filters.value[filter].length === list.length
+/**
+ * A marker to know if the values of filter group
+ * are currently all selected.
+ * @param filter - The name of the filter group
+ * @param listLength - The number of values in this group
+ * @return If all the values are currently selected
+ */
+function allSelected(filter: keyof AdvancedFilters, valuesNumber: number): boolean {
+  return filters.value[filter].length === valuesNumber
 }
 
 /**
@@ -331,7 +332,7 @@ function removeFilter(filterChip: FilterChip): void {
   color: var(--black);
 }
 
-.options-group .checkbox-list {
+.checkbox-list {
   display: flex;
   flex-flow: row wrap;
   gap: var(--spacing);
@@ -344,29 +345,6 @@ function removeFilter(filterChip: FilterChip): void {
   transition: color 0.1s;
 }
 
-.checkbox input {
-  display: none;
-}
-
-.checkbox label {
-  border-radius: var(--big-radius);
-  border: 1px solid var(--white);
-  cursor: pointer;
-  padding: calc(var(--spacing) / 3) var(--half-spacing);
-  transition: all 0.2s;
-
-  &:hover {
-    border-color: var(--primary);
-    color: var(--primary);
-  }
-}
-
-.checkbox input:checked+label {
-  background-color: var(--primary);
-  border-color: var(--primary);
-  color: var(--black);
-}
-
 .advanced-search-dialog footer {
   align-items: center;
   display: flex;
diff --git a/src/client/components/AppCheckbox.vue b/src/client/components/AppCheckbox.vue
new file mode 100644
index 0000000000000000000000000000000000000000..eac8a96873d6f5753370159684a6c348e5204550
--- /dev/null
+++ b/src/client/components/AppCheckbox.vue
@@ -0,0 +1,44 @@
+<template>
+  <input
+    :id="value + '-checkbox'"
+    v-model="modelValue"
+    :value="value"
+    type="checkbox"
+  >
+  <label :for="value + '-checkbox'">
+    <slot />
+  </label>
+</template>
+
+<script setup lang="ts">
+defineProps<{
+  value: string
+}>()
+
+const modelValue = defineModel<Array<string>>()
+</script>
+
+<style scoped>
+input {
+  display: none;
+}
+
+label {
+  border-radius: var(--big-radius);
+  border: 1px solid var(--white);
+  cursor: pointer;
+  padding: calc(var(--spacing) / 3) var(--half-spacing);
+  transition: all 0.2s;
+
+  &:hover {
+    border-color: var(--primary);
+    color: var(--primary);
+  }
+}
+
+input:checked+label {
+  background-color: var(--primary);
+  border-color: var(--primary);
+  color: var(--black);
+}
+</style>
diff --git a/src/client/store.ts b/src/client/store.ts
index e9620c6150595b1f25bc28bdd1cc031229017bd1..5ba0948a6f5af12455e0a3170d6a0c83f9c1e574 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -15,16 +15,16 @@ import alphanumSort from './utils/alphanumSort'
 interface State {
   antibodies: Antibody[]
   antibodiesCount: number
-  antibodiesSources: Array<FastaHeader['source']>
-  antibodiesSpecies: Array<Antibody['species']>
-  antibodiesHeavySegments: Array<FastaHeader['vGeneSegment']>
-  antibodiesLightSegments: Array<FastaHeader['vGeneSegment']>
+  antibodiesSources: Readonly<Array<FastaHeader['source']>>
+  antibodiesSpecies: Readonly<Array<Antibody['species']>>
+  antibodiesHeavySegments: Readonly<Array<FastaHeader['vGeneSegment']>>
+  antibodiesLightSegments: Readonly<Array<FastaHeader['vGeneSegment']>>
   archives: Array<string>
   isDownloading: boolean
   isFetchingCount: boolean
   noResults: boolean
   request: APIFetchParams
-  sourceMeta: SourceMeta
+  readonly sourceMeta: SourceMeta
 }
 
 export const useStore = defineStore('store', {
@@ -89,18 +89,18 @@ export const useStore = defineStore('store', {
       })
     },
 
-    getAntibodiesSources (): void {
-      api.getAntibodiesSources().then(response => {
-        this.antibodiesSources = response.data
+    getAntibodiesSpecies (): void {
+      api.getAntibodiesSpecies().then(response => {
+        this.antibodiesSpecies = Object.freeze(response.data)
       }).catch((err: AxiosError) => {
         alert(err.message)
         console.log(err)
       })
     },
 
-    getAntibodiesSpecies (): void {
-      api.getAntibodiesSpecies().then(response => {
-        this.antibodiesSpecies = response.data
+    getAntibodiesSources (): void {
+      api.getAntibodiesSources().then(response => {
+        this.antibodiesSources = Object.freeze(response.data)
       }).catch((err: AxiosError) => {
         alert(err.message)
         console.log(err)
@@ -109,8 +109,8 @@ export const useStore = defineStore('store', {
 
     getAntibodiesSegments (): void {
       api.getAntibodiesSegments().then(response => {
-        this.antibodiesHeavySegments = response.data.heavySegments.sort(alphanumSort)
-        this.antibodiesLightSegments = response.data.lightSegments.sort(alphanumSort)
+        this.antibodiesHeavySegments = Object.freeze(response.data.heavySegments.sort(alphanumSort))
+        this.antibodiesLightSegments = Object.freeze(response.data.lightSegments.sort(alphanumSort))
       }).catch((err: AxiosError) => {
         alert(err.message)
         console.log(err)