diff --git a/js/.eslintrc.js b/js/.eslintrc.js
index ac692e5ee..d29e98c47 100644
--- a/js/.eslintrc.js
+++ b/js/.eslintrc.js
@@ -48,6 +48,8 @@ module.exports = {
     "import/prefer-default-export": "off",
     "import/extensions": "off",
     "import/no-unresolved": "off",
+    "no-shadow": "off",
+    "@typescript-eslint/no-shadow": ["error"],
   },
 
   ignorePatterns: ["src/typings/*.d.ts", "vue.config.js"],
diff --git a/js/src/@types/dom.d.ts b/js/src/@types/dom.d.ts
new file mode 100644
index 000000000..59a3a0781
--- /dev/null
+++ b/js/src/@types/dom.d.ts
@@ -0,0 +1,18 @@
+declare global {
+  interface GeolocationCoordinates {
+    readonly accuracy: number;
+    readonly altitude: number | null;
+    readonly altitudeAccuracy: number | null;
+    readonly heading: number | null;
+    readonly latitude: number;
+    readonly longitude: number;
+    readonly speed: number | null;
+  }
+
+  interface GeolocationPosition {
+    readonly coords: GeolocationCoordinates;
+    readonly timestamp: number;
+  }
+}
+
+export {};
diff --git a/js/src/apollo/user.ts b/js/src/apollo/user.ts
index 5abd70fcf..824df6f73 100644
--- a/js/src/apollo/user.ts
+++ b/js/src/apollo/user.ts
@@ -1,8 +1,11 @@
+import { ICurrentUserRole } from "@/types/enums";
 import { ApolloCache } from "apollo-cache";
 import { NormalizedCacheObject } from "apollo-cache-inmemory";
-import { ICurrentUserRole } from "@/types/current-user.model";
+import { Resolvers } from "apollo-client/core/types";
 
-export default function buildCurrentUserResolver(cache: ApolloCache<NormalizedCacheObject>) {
+export default function buildCurrentUserResolver(
+  cache: ApolloCache<NormalizedCacheObject>
+): Resolvers {
   cache.writeData({
     data: {
       currentUser: {
diff --git a/js/src/components/Account/Identities.vue b/js/src/components/Account/Identities.vue
index 81c08e66a..6dea19a45 100644
--- a/js/src/components/Account/Identities.vue
+++ b/js/src/components/Account/Identities.vue
@@ -53,7 +53,7 @@ export default class Identities extends Vue {
 
   errors: string[] = [];
 
-  isCurrentIdentity(identity: IPerson) {
+  isCurrentIdentity(identity: IPerson): boolean {
     return identity.preferredUsername === this.currentIdentityName;
   }
 }
diff --git a/js/src/components/Account/ParticipantCard.vue b/js/src/components/Account/ParticipantCard.vue
deleted file mode 100644
index 807e2f3a5..000000000
--- a/js/src/components/Account/ParticipantCard.vue
+++ /dev/null
@@ -1,94 +0,0 @@
-<docs>
-```vue
-<participant-card :participant="{ actor: { preferredUsername: 'user1', name: 'someoneIDontLike' }, role: 'REJECTED' }" />
-```
-
-```vue
-<participant-card :participant="{ actor: { preferredUsername: 'user2', name: 'someoneWhoWillWait' }, role: 'NOT_APPROVED' }" />
-```
-
-```vue
-<participant-card :participant="{ actor: { preferredUsername: 'user3', name: 'a_participant' }, role: 'PARTICIPANT' }" />
-```
-
-```vue
-<participant-card :participant="{ actor: { preferredUsername: 'me', name: 'myself' }, role: 'CREATOR' }" />
-```
-</docs>
-<template>
-  <article class="card">
-    <div class="card-content">
-      <div class="media">
-        <div class="media-left" v-if="participant.actor.avatar">
-          <figure class="image is-48x48">
-            <img :src="participant.actor.avatar.url" />
-          </figure>
-        </div>
-        <div class="media-content">
-          <span ref="title">{{ actorDisplayName }}</span
-          ><br />
-          <small class="has-text-grey" v-if="participant.actor.domain"
-            >@{{ participant.actor.preferredUsername }}@{{ participant.actor.domain }}</small
-          >
-          <small class="has-text-grey" v-else>@{{ participant.actor.preferredUsername }}</small>
-        </div>
-      </div>
-    </div>
-    <footer class="card-footer">
-      <b-button
-        v-if="[ParticipantRole.NOT_APPROVED, ParticipantRole.REJECTED].includes(participant.role)"
-        @click="accept(participant)"
-        type="is-success"
-        class="card-footer-item"
-        >{{ $t("Approve") }}</b-button
-      >
-      <b-button
-        v-if="participant.role === ParticipantRole.NOT_APPROVED"
-        @click="reject(participant)"
-        type="is-danger"
-        class="card-footer-item"
-        >{{ $t("Reject") }}</b-button
-      >
-      <b-button
-        v-if="participant.role === ParticipantRole.PARTICIPANT"
-        @click="exclude(participant)"
-        type="is-danger"
-        class="card-footer-item"
-        >{{ $t("Exclude") }}</b-button
-      >
-      <span v-if="participant.role === ParticipantRole.CREATOR" class="card-footer-item">{{
-        $t("Creator")
-      }}</span>
-    </footer>
-  </article>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from "vue-property-decorator";
-import { IParticipant, ParticipantRole } from "../../types/participant.model";
-import { IPerson, Person } from "../../types/actor";
-
-@Component
-export default class ParticipantCard extends Vue {
-  @Prop({ required: true }) participant!: IParticipant;
-
-  @Prop({ type: Function }) accept!: Function;
-
-  @Prop({ type: Function }) reject!: Function;
-
-  @Prop({ type: Function }) exclude!: Function;
-
-  ParticipantRole = ParticipantRole;
-
-  get actorDisplayName(): string {
-    const actor = new Person(this.participant.actor as IPerson);
-    return actor.displayName();
-  }
-}
-</script>
-
-<style lang="scss">
-.card-footer-item {
-  height: $control-height;
-}
-</style>
diff --git a/js/src/components/Account/PopoverActorCard.vue b/js/src/components/Account/PopoverActorCard.vue
index a61d08880..7374376c5 100644
--- a/js/src/components/Account/PopoverActorCard.vue
+++ b/js/src/components/Account/PopoverActorCard.vue
@@ -12,8 +12,9 @@
   </v-popover>
 </template>
 <script lang="ts">
+import { ActorType } from "@/types/enums";
 import { Component, Vue, Prop } from "vue-property-decorator";
-import { IActor, ActorType } from "../../types/actor";
+import { IActor } from "../../types/actor";
 import ActorCard from "./ActorCard.vue";
 
 @Component({
diff --git a/js/src/components/Admin/Followings.vue b/js/src/components/Admin/Followings.vue
index d39a8c746..f3531d931 100644
--- a/js/src/components/Admin/Followings.vue
+++ b/js/src/components/Admin/Followings.vue
@@ -103,7 +103,6 @@ import { SnackbarProgrammatic as Snackbar } from "buefy";
 import { formatDistanceToNow } from "date-fns";
 import { ADD_RELAY, REMOVE_RELAY } from "../../graphql/admin";
 import { IFollower } from "../../types/actor/follower.model";
-import { Paginate } from "../../types/paginate";
 import RelayMixin from "../../mixins/relay";
 
 @Component({
diff --git a/js/src/components/Comment/Comment.vue b/js/src/components/Comment/Comment.vue
index 825c81628..9f9d3b304 100644
--- a/js/src/components/Comment/Comment.vue
+++ b/js/src/components/Comment/Comment.vue
@@ -137,7 +137,7 @@ import { Component, Prop, Vue, Ref } from "vue-property-decorator";
 import EditorComponent from "@/components/Editor.vue";
 import { SnackbarProgrammatic as Snackbar } from "buefy";
 import { formatDistanceToNow } from "date-fns";
-import { CommentModeration } from "../../types/event-options.model";
+import { CommentModeration } from "@/types/enums";
 import { CommentModel, IComment } from "../../types/comment.model";
 import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
 import { IPerson, usernameWithDomain } from "../../types/actor";
diff --git a/js/src/components/Comment/CommentTree.vue b/js/src/components/Comment/CommentTree.vue
index ab6ce3286..06b61a31c 100644
--- a/js/src/components/Comment/CommentTree.vue
+++ b/js/src/components/Comment/CommentTree.vue
@@ -51,7 +51,7 @@
 import { Prop, Vue, Component, Watch } from "vue-property-decorator";
 import Comment from "@/components/Comment/Comment.vue";
 import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue";
-import { CommentModeration } from "../../types/event-options.model";
+import { CommentModeration } from "@/types/enums";
 import { CommentModel, IComment } from "../../types/comment.model";
 import {
   CREATE_COMMENT_FROM_EVENT,
diff --git a/js/src/components/Editor.vue b/js/src/components/Editor.vue
index 8117e5526..7223d4ba3 100644
--- a/js/src/components/Editor.vue
+++ b/js/src/components/Editor.vue
@@ -395,15 +395,7 @@ export default class EditorComponent extends Vue {
         new Image(),
         new MaxSize({ maxSize: this.maxSize }),
       ],
-      onUpdate: ({
-        getHTML,
-        transaction,
-        getJSON,
-      }: {
-        getHTML: Function;
-        getJSON: Function;
-        transaction: unknown;
-      }) => {
+      onUpdate: ({ getHTML }: { getHTML: Function }) => {
         this.$emit("input", getHTML());
       },
     });
diff --git a/js/src/components/Editor/MaxSize.ts b/js/src/components/Editor/MaxSize.ts
index a1d113704..3205263f6 100644
--- a/js/src/components/Editor/MaxSize.ts
+++ b/js/src/components/Editor/MaxSize.ts
@@ -1,11 +1,14 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
 // @ts-nocheck
 import { Extension, Plugin } from "tiptap";
 
 export default class MaxSize extends Extension {
+  // eslint-disable-next-line class-methods-use-this
   get name() {
     return "maxSize";
   }
 
+  // eslint-disable-next-line class-methods-use-this
   get defaultOptions() {
     return {
       maxSize: null,
@@ -21,7 +24,7 @@ export default class MaxSize extends Extension {
           const newLength = newState.doc.content.size;
 
           if (newLength > max && newLength > oldLength) {
-            let newTr = newState.tr;
+            const newTr = newState.tr;
             newTr.insertText("", max + 1, newLength);
 
             return newTr;
diff --git a/js/src/components/Event/AddressAutoComplete.vue b/js/src/components/Event/AddressAutoComplete.vue
index 49a93b9e7..17e6c139d 100644
--- a/js/src/components/Event/AddressAutoComplete.vue
+++ b/js/src/components/Event/AddressAutoComplete.vue
@@ -50,7 +50,7 @@
 <script lang="ts">
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
 import { LatLng } from "leaflet";
-import { debounce } from "lodash";
+import { debounce, DebouncedFunc } from "lodash";
 import { Address, IAddress } from "../../types/address.model";
 import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address";
 import { CONFIG } from "../../graphql/config";
@@ -81,7 +81,7 @@ export default class AddressAutoComplete extends Vue {
 
   private gettingLocation = false;
 
-  private location!: Position;
+  private location!: GeolocationPosition;
 
   private gettingLocationError: any;
 
@@ -89,7 +89,7 @@ export default class AddressAutoComplete extends Vue {
 
   config!: IConfig;
 
-  fetchAsyncData!: Function;
+  fetchAsyncData!: DebouncedFunc<(query: string) => Promise<void>>;
 
   // We put this in data because of issues like
   // https://github.com/vuejs/vue-class-component/issues/263
@@ -207,7 +207,7 @@ export default class AddressAutoComplete extends Vue {
     this.gettingLocation = false;
   }
 
-  static async getLocation(): Promise<Position> {
+  static async getLocation(): Promise<GeolocationPosition> {
     return new Promise((resolve, reject) => {
       if (!("geolocation" in navigator)) {
         reject(new Error("Geolocation is not available."));
diff --git a/js/src/components/Event/EventCard.vue b/js/src/components/Event/EventCard.vue
index a399a5021..31d95b799 100644
--- a/js/src/components/Event/EventCard.vue
+++ b/js/src/components/Event/EventCard.vue
@@ -77,7 +77,7 @@ import { IEvent, IEventCardOptions } from "@/types/event.model";
 import { Component, Prop, Vue } from "vue-property-decorator";
 import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
 import { Actor, Person } from "@/types/actor";
-import { ParticipantRole } from "../../types/participant.model";
+import { ParticipantRole } from "@/types/enums";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/components/Event/EventListCard.vue b/js/src/components/Event/EventListCard.vue
index 780bd96f0..6f2953e74 100644
--- a/js/src/components/Event/EventListCard.vue
+++ b/js/src/components/Event/EventListCard.vue
@@ -187,8 +187,9 @@ import { Component, Prop } from "vue-property-decorator";
 import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
 import { mixins } from "vue-class-component";
 import { RawLocation, Route } from "vue-router";
-import { IParticipant, ParticipantRole } from "../../types/participant.model";
-import { EventVisibility, IEventCardOptions } from "../../types/event.model";
+import { EventVisibility, ParticipantRole } from "@/types/enums";
+import { IParticipant } from "../../types/participant.model";
+import { IEventCardOptions } from "../../types/event.model";
 import { IPerson } from "../../types/actor";
 import ActorMixin from "../../mixins/actor";
 import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
diff --git a/js/src/components/Event/EventListViewCard.vue b/js/src/components/Event/EventListViewCard.vue
index 895637dbc..99113f40d 100644
--- a/js/src/components/Event/EventListViewCard.vue
+++ b/js/src/components/Event/EventListViewCard.vue
@@ -51,7 +51,7 @@
 </template>
 
 <script lang="ts">
-import { EventVisibility, IEventCardOptions, IEvent } from "@/types/event.model";
+import { IEventCardOptions, IEvent } from "@/types/event.model";
 import { Component, Prop } from "vue-property-decorator";
 import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
 import { IPerson, usernameWithDomain } from "@/types/actor";
@@ -59,7 +59,7 @@ import { mixins } from "vue-class-component";
 import ActorMixin from "@/mixins/actor";
 import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
 import EventMixin from "@/mixins/event";
-import { ParticipantRole } from "../../types/participant.model";
+import { EventVisibility, ParticipantRole } from "@/types/enums";
 import RouteName from "../../router/name";
 
 const defaultOptions: IEventCardOptions = {
diff --git a/js/src/components/Event/EventMinimalistCard.vue b/js/src/components/Event/EventMinimalistCard.vue
index 7d8455263..2f7db05a4 100644
--- a/js/src/components/Event/EventMinimalistCard.vue
+++ b/js/src/components/Event/EventMinimalistCard.vue
@@ -56,7 +56,7 @@
 import { Component, Prop, Vue } from "vue-property-decorator";
 import { IEvent } from "@/types/event.model";
 import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
-import { ParticipantRole } from "../../types/participant.model";
+import { ParticipantRole } from "@/types/enums";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/components/Event/FullAddressAutoComplete.vue b/js/src/components/Event/FullAddressAutoComplete.vue
index 00acbaa4a..14b96533d 100644
--- a/js/src/components/Event/FullAddressAutoComplete.vue
+++ b/js/src/components/Event/FullAddressAutoComplete.vue
@@ -102,7 +102,7 @@
 <script lang="ts">
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
 import { LatLng } from "leaflet";
-import { debounce } from "lodash";
+import { debounce, DebouncedFunc } from "lodash";
 import { Address, IAddress } from "../../types/address.model";
 import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address";
 import { CONFIG } from "../../graphql/config";
@@ -133,7 +133,7 @@ export default class FullAddressAutoComplete extends Vue {
 
   private gettingLocation = false;
 
-  private location!: Position;
+  private location!: GeolocationPosition;
 
   private gettingLocationError: any;
 
@@ -141,11 +141,11 @@ export default class FullAddressAutoComplete extends Vue {
 
   config!: IConfig;
 
-  fetchAsyncData!: Function;
+  fetchAsyncData!: DebouncedFunc<(query: string) => Promise<void>>;
 
   // We put this in data because of issues like
   // https://github.com/vuejs/vue-class-component/issues/263
-  data() {
+  data(): Record<string, unknown> {
     return {
       fetchAsyncData: debounce(this.asyncData, 200),
     };
@@ -266,7 +266,7 @@ export default class FullAddressAutoComplete extends Vue {
     return window.isSecureContext;
   }
 
-  static async getLocation(): Promise<Position> {
+  static async getLocation(): Promise<GeolocationPosition> {
     return new Promise((resolve, reject) => {
       if (!("geolocation" in navigator)) {
         reject(new Error("Geolocation is not available."));
diff --git a/js/src/components/Event/OrganizerPicker.vue b/js/src/components/Event/OrganizerPicker.vue
index 7eb58814b..dcc455789 100644
--- a/js/src/components/Event/OrganizerPicker.vue
+++ b/js/src/components/Event/OrganizerPicker.vue
@@ -23,9 +23,11 @@
 </template>
 <script lang="ts">
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
-import { IMember, IPerson, MemberRole, IActor, Actor } from "@/types/actor";
+import { IPerson, IActor, Actor } from "@/types/actor";
 import { PERSON_MEMBERSHIPS } from "@/graphql/actor";
 import { Paginate } from "@/types/paginate";
+import { IMember } from "@/types/actor/member.model";
+import { MemberRole } from "@/types/enums";
 
 @Component({
   apollo: {
diff --git a/js/src/components/Event/OrganizerPickerWrapper.vue b/js/src/components/Event/OrganizerPickerWrapper.vue
index abc94ea66..ff76936aa 100644
--- a/js/src/components/Event/OrganizerPickerWrapper.vue
+++ b/js/src/components/Event/OrganizerPickerWrapper.vue
@@ -115,7 +115,8 @@
 </template>
 <script lang="ts">
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
-import { IActor, IGroup, IMember, IPerson } from "../../types/actor";
+import { IMember } from "@/types/actor/member.model";
+import { IActor, IGroup, IPerson } from "../../types/actor";
 import OrganizerPicker from "./OrganizerPicker.vue";
 import { PERSON_MEMBERSHIPS_WITH_MEMBERS } from "../../graphql/actor";
 import { Paginate } from "../../types/paginate";
@@ -182,7 +183,7 @@ export default class OrganizerPickerWrapper extends Vue {
       ({ parent: { id } }) => id === this.currentActor.id
     );
     if (currentMembership) {
-      return currentMembership.parent.members.elements.map(({ actor }) => actor);
+      return currentMembership.parent.members.elements.map(({ actor }: { actor: IActor }) => actor);
     }
     return [];
   }
diff --git a/js/src/components/Event/ParticipationButton.vue b/js/src/components/Event/ParticipationButton.vue
index f77a342af..27a02da95 100644
--- a/js/src/components/Event/ParticipationButton.vue
+++ b/js/src/components/Event/ParticipationButton.vue
@@ -142,8 +142,9 @@ A button to set your participation
 
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { IParticipant, ParticipantRole } from "../../types/participant.model";
-import { EventJoinOptions, IEvent } from "../../types/event.model";
+import { EventJoinOptions, ParticipantRole } from "@/types/enums";
+import { IParticipant } from "../../types/participant.model";
+import { IEvent } from "../../types/event.model";
 import { IPerson, Person } from "../../types/actor";
 import { CURRENT_ACTOR_CLIENT, IDENTITIES } from "../../graphql/actor";
 import { CURRENT_USER_CLIENT } from "../../graphql/user";
diff --git a/js/src/components/Event/ShareEventModal.vue b/js/src/components/Event/ShareEventModal.vue
index f98056a51..56e1b341a 100644
--- a/js/src/components/Event/ShareEventModal.vue
+++ b/js/src/components/Event/ShareEventModal.vue
@@ -76,7 +76,9 @@
 
 <script lang="ts">
 import { Component, Prop, Vue, Ref } from "vue-property-decorator";
-import { IEvent, EventVisibility, EventStatus } from "../../types/event.model";
+import { EventStatus, EventVisibility } from "@/types/enums";
+import { IEvent } from "../../types/event.model";
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
 // @ts-ignore
 import DiasporaLogo from "../../assets/diaspora-icon.svg?inline";
 
@@ -124,7 +126,7 @@ export default class ShareEventModal extends Vue {
     )}&url=${encodeURIComponent(this.event.url)}`;
   }
 
-  copyURL() {
+  copyURL(): void {
     this.eventURLInput.$refs.input.select();
     document.execCommand("copy");
     this.showCopiedTooltip = true;
diff --git a/js/src/components/Event/TagInput.vue b/js/src/components/Event/TagInput.vue
index bade41cf8..0a0e82ebe 100644
--- a/js/src/components/Event/TagInput.vue
+++ b/js/src/components/Event/TagInput.vue
@@ -40,7 +40,6 @@ import { ITag } from "../../types/tag.model";
           if (typeof tag !== "string") {
             return tag;
           }
-          // @ts-ignore
           return { title: tag, slug: tag } as ITag;
         });
         this.$emit("input", tagEntities);
@@ -57,14 +56,10 @@ export default class TagInput extends Vue {
 
   filteredTags: ITag[] = [];
 
-  getFilteredTags(text: string) {
+  getFilteredTags(text: string): void {
     this.filteredTags = differenceBy(this.data, this.value, "id").filter(
       (option) => get(option, this.path).toString().toLowerCase().indexOf(text.toLowerCase()) >= 0
     );
   }
-
-  static isTag(x: any): x is ITag {
-    return x.slug !== undefined;
-  }
 }
 </script>
diff --git a/js/src/components/Group/GroupMemberCard.vue b/js/src/components/Group/GroupMemberCard.vue
index f00689077..0b94eacdd 100644
--- a/js/src/components/Group/GroupMemberCard.vue
+++ b/js/src/components/Group/GroupMemberCard.vue
@@ -54,7 +54,9 @@
 
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { IMember, MemberRole, usernameWithDomain } from "@/types/actor";
+import { usernameWithDomain } from "@/types/actor";
+import { IMember } from "@/types/actor/member.model";
+import { MemberRole } from "@/types/enums";
 import RouteName from "../../router/name";
 
 @Component
diff --git a/js/src/components/Group/GroupPicker.vue b/js/src/components/Group/GroupPicker.vue
index 071aa5b3a..12211563d 100644
--- a/js/src/components/Group/GroupPicker.vue
+++ b/js/src/components/Group/GroupPicker.vue
@@ -36,9 +36,11 @@
 </template>
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { IGroup, IMember, IPerson, Group, MemberRole } from "@/types/actor";
+import { IGroup, IPerson, Group } from "@/types/actor";
 import { PERSON_MEMBERSHIPS } from "@/graphql/actor";
 import { Paginate } from "@/types/paginate";
+import { IMember } from "@/types/actor/member.model";
+import { MemberRole } from "@/types/enums";
 
 @Component({
   apollo: {
diff --git a/js/src/components/Group/GroupPickerWrapper.vue b/js/src/components/Group/GroupPickerWrapper.vue
index c2c0a5764..61c009a32 100644
--- a/js/src/components/Group/GroupPickerWrapper.vue
+++ b/js/src/components/Group/GroupPickerWrapper.vue
@@ -61,7 +61,8 @@
 </template>
 <script lang="ts">
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
-import { IGroup, IMember, IPerson } from "../../types/actor";
+import { IMember } from "@/types/actor/member.model";
+import { IGroup, IPerson } from "../../types/actor";
 import GroupPicker from "./GroupPicker.vue";
 import { PERSON_MEMBERSHIPS } from "../../graphql/actor";
 import { Paginate } from "../../types/paginate";
diff --git a/js/src/components/Group/InvitationCard.vue b/js/src/components/Group/InvitationCard.vue
index 9292bb264..8d02ddb51 100644
--- a/js/src/components/Group/InvitationCard.vue
+++ b/js/src/components/Group/InvitationCard.vue
@@ -54,7 +54,8 @@
 
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { IMember, usernameWithDomain } from "@/types/actor";
+import { usernameWithDomain } from "@/types/actor";
+import { IMember } from "@/types/actor/member.model";
 import RouteName from "../../router/name";
 
 @Component
diff --git a/js/src/components/Group/Invitations.vue b/js/src/components/Group/Invitations.vue
index d999a737b..c7ce08b3d 100644
--- a/js/src/components/Group/Invitations.vue
+++ b/js/src/components/Group/Invitations.vue
@@ -11,10 +11,10 @@
 </template>
 <script lang="ts">
 import { ACCEPT_INVITATION, REJECT_INVITATION } from "@/graphql/member";
-import { IMember } from "@/types/actor";
 import { Component, Prop, Vue } from "vue-property-decorator";
 import InvitationCard from "@/components/Group/InvitationCard.vue";
 import { LOGGED_USER_MEMBERSHIPS } from "@/graphql/actor";
+import { IMember } from "@/types/actor/member.model";
 
 @Component({
   components: {
diff --git a/js/src/components/Map.vue b/js/src/components/Map.vue
index ab05c5248..00ebaa3a3 100644
--- a/js/src/components/Map.vue
+++ b/js/src/components/Map.vue
@@ -53,10 +53,10 @@ export default class Map extends Vue {
 
   @Prop({ type: Object, required: false }) marker!: { text: string | string[]; icon: string };
 
-  @Prop({ type: Object, required: false }) options!: object;
+  @Prop({ type: Object, required: false }) options!: Record<string, unknown>;
 
   @Prop({ type: Function, required: false })
-  updateDraggableMarkerCallback!: Function;
+  updateDraggableMarkerCallback!: (latlng: LatLng, zoom: number) => void;
 
   defaultOptions: {
     zoom: number;
@@ -86,45 +86,47 @@ export default class Map extends Vue {
   }
   /* eslint-enable */
 
-  openPopup(event: LeafletEvent) {
+  openPopup(event: LeafletEvent): void {
     this.$nextTick(() => {
       event.target.openPopup();
     });
   }
 
-  get mergedOptions(): object {
+  get mergedOptions(): Record<string, unknown> {
     return { ...this.defaultOptions, ...this.options };
   }
 
-  get lat() {
+  get lat(): number {
     return this.$props.coords.split(";")[1];
   }
 
-  get lon() {
+  get lon(): number {
     return this.$props.coords.split(";")[0];
   }
 
-  get popupMultiLine() {
+  get popupMultiLine(): Array<string> {
     if (Array.isArray(this.marker.text)) {
       return this.marker.text;
     }
     return [this.marker.text];
   }
 
-  clickMap(event: LeafletMouseEvent) {
+  clickMap(event: LeafletMouseEvent): void {
     this.updateDraggableMarkerPosition(event.latlng);
   }
 
-  updateDraggableMarkerPosition(e: LatLng) {
+  updateDraggableMarkerPosition(e: LatLng): void {
     this.updateDraggableMarkerCallback(e, this.zoom);
   }
 
-  updateZoom(zoom: number) {
+  updateZoom(zoom: number): void {
     this.zoom = zoom;
   }
 
-  get attribution() {
-    return this.config.maps.tiles.attribution || this.$t("© The OpenStreetMap Contributors");
+  get attribution(): string {
+    return (
+      this.config.maps.tiles.attribution || (this.$t("© The OpenStreetMap Contributors") as string)
+    );
   }
 }
 </script>
diff --git a/js/src/components/Map/Vue2LeafletLocateControl.vue b/js/src/components/Map/Vue2LeafletLocateControl.vue
index 9a69db9f0..df2de381e 100644
--- a/js/src/components/Map/Vue2LeafletLocateControl.vue
+++ b/js/src/components/Map/Vue2LeafletLocateControl.vue
@@ -17,13 +17,13 @@ import { Component, Prop, Vue } from "vue-property-decorator";
 
 @Component({
   beforeDestroy() {
-    // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
     // @ts-ignore
     this.parentContainer.removeLayer(this);
   },
 })
 export default class Vue2LeafletLocateControl extends Vue {
-  @Prop({ type: Object, default: () => ({}) }) options!: object;
+  @Prop({ type: Object, default: () => ({}) }) options!: Record<string, unknown>;
 
   @Prop({ type: Boolean, default: true }) visible = true;
 
@@ -33,7 +33,7 @@ export default class Vue2LeafletLocateControl extends Vue {
 
   parentContainer: any;
 
-  mounted() {
+  mounted(): void {
     this.mapObject = L.control.locate(this.options);
     DomEvent.on(this.mapObject, this.$listeners as any);
     propsBinder(this, this.mapObject, this.$props);
@@ -42,7 +42,7 @@ export default class Vue2LeafletLocateControl extends Vue {
     this.mapObject.addTo(this.parentContainer.mapObject, !this.visible);
   }
 
-  public locate() {
+  public locate(): void {
     this.mapObject.start();
   }
 }
diff --git a/js/src/components/NavBar.vue b/js/src/components/NavBar.vue
index 5af8b3f00..6846f78eb 100644
--- a/js/src/components/NavBar.vue
+++ b/js/src/components/NavBar.vue
@@ -109,13 +109,14 @@ import { Component, Vue, Watch } from "vue-property-decorator";
 import Logo from "@/components/Logo.vue";
 import { GraphQLError } from "graphql";
 import { loadLanguageAsync } from "@/utils/i18n";
+import { ICurrentUserRole } from "@/types/enums";
 import { CURRENT_USER_CLIENT, USER_SETTINGS } from "../graphql/user";
 import { changeIdentity, logout } from "../utils/auth";
 import { CURRENT_ACTOR_CLIENT, IDENTITIES, UPDATE_DEFAULT_ACTOR } from "../graphql/actor";
 import { IPerson, Person } from "../types/actor";
 import { CONFIG } from "../graphql/config";
 import { IConfig } from "../types/config.model";
-import { ICurrentUser, ICurrentUserRole, IUser } from "../types/current-user.model";
+import { ICurrentUser, IUser } from "../types/current-user.model";
 import SearchField from "./SearchField.vue";
 import RouteName from "../router/name";
 
diff --git a/js/src/components/Participation/ConfirmParticipation.vue b/js/src/components/Participation/ConfirmParticipation.vue
index 8630e0362..a72c8d4d6 100644
--- a/js/src/components/Participation/ConfirmParticipation.vue
+++ b/js/src/components/Participation/ConfirmParticipation.vue
@@ -38,9 +38,9 @@
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
 import { confirmLocalAnonymousParticipation } from "@/services/AnonymousParticipationStorage";
+import { EventJoinOptions } from "@/types/enums";
 import { IParticipant } from "../../types/participant.model";
 import RouteName from "../../router/name";
-import { EventJoinOptions } from "../../types/event.model";
 import { CONFIRM_PARTICIPATION } from "../../graphql/event";
 
 @Component
diff --git a/js/src/components/Participation/ParticipationWithoutAccount.vue b/js/src/components/Participation/ParticipationWithoutAccount.vue
index 3f6c67830..980f2432e 100644
--- a/js/src/components/Participation/ParticipationWithoutAccount.vue
+++ b/js/src/components/Participation/ParticipationWithoutAccount.vue
@@ -74,12 +74,13 @@
 </template>
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { EventModel, IEvent, EventJoinOptions } from "@/types/event.model";
+import { EventModel, IEvent } from "@/types/event.model";
 import { FETCH_EVENT, JOIN_EVENT } from "@/graphql/event";
 import { IConfig } from "@/types/config.model";
 import { CONFIG } from "@/graphql/config";
 import { addLocalUnconfirmedAnonymousParticipation } from "@/services/AnonymousParticipationStorage";
-import { IParticipant, ParticipantRole } from "../../types/participant.model";
+import { EventJoinOptions, ParticipantRole } from "@/types/enums";
+import { IParticipant } from "../../types/participant.model";
 
 @Component({
   apollo: {
diff --git a/js/src/components/Post/PostElementItem.vue b/js/src/components/Post/PostElementItem.vue
index 1e1f8b3e1..f377c8aae 100644
--- a/js/src/components/Post/PostElementItem.vue
+++ b/js/src/components/Post/PostElementItem.vue
@@ -43,9 +43,10 @@
 </template>
 <script lang="ts">
 import { usernameWithDomain } from "@/types/actor";
+import { PostVisibility } from "@/types/enums";
 import { Component, Prop, Vue } from "vue-property-decorator";
 import RouteName from "../../router/name";
-import { IPost, PostVisibility } from "../../types/post.model";
+import { IPost } from "../../types/post.model";
 
 @Component
 export default class PostElementItem extends Vue {
diff --git a/js/src/components/Report/ReportCard.vue b/js/src/components/Report/ReportCard.vue
index 1f305f30c..0ae5a991b 100644
--- a/js/src/components/Report/ReportCard.vue
+++ b/js/src/components/Report/ReportCard.vue
@@ -36,7 +36,7 @@
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
 import { IReport } from "@/types/report.model";
-import { ActorType } from "@/types/actor";
+import { ActorType } from "@/types/enums";
 
 @Component
 export default class ReportCard extends Vue {
diff --git a/js/src/components/Report/ReportModal.vue b/js/src/components/Report/ReportModal.vue
index 020725eb7..57eed0e97 100644
--- a/js/src/components/Report/ReportModal.vue
+++ b/js/src/components/Report/ReportModal.vue
@@ -82,7 +82,7 @@ import { IComment } from "../../types/comment.model";
   },
 })
 export default class ReportModal extends Vue {
-  @Prop({ type: Function }) onConfirm!: Function;
+  @Prop({ type: Function }) onConfirm!: (content: string, forward: boolean) => void;
 
   @Prop({ type: String }) title!: string;
 
diff --git a/js/src/components/Resource/ResourceDropdown.vue b/js/src/components/Resource/ResourceDropdown.vue
index d1a2e566c..3546381be 100644
--- a/js/src/components/Resource/ResourceDropdown.vue
+++ b/js/src/components/Resource/ResourceDropdown.vue
@@ -17,7 +17,7 @@
   </b-dropdown>
 </template>
 <script lang="ts">
-import { Component, Vue, Prop } from "vue-property-decorator";
+import { Component, Vue } from "vue-property-decorator";
 
 @Component
 export default class ResourceDropdown extends Vue {}
diff --git a/js/src/components/Resource/ResourceSelector.vue b/js/src/components/Resource/ResourceSelector.vue
index 755604055..2b1fb874b 100644
--- a/js/src/components/Resource/ResourceSelector.vue
+++ b/js/src/components/Resource/ResourceSelector.vue
@@ -47,7 +47,7 @@
     <b-button type="is-primary" @click="updateResource" :disabled="moveDisabled">{{
       $t("Move resource to {folder}", { folder: resource.title })
     }}</b-button>
-    <b-button type="is-text" @click="$emit('closeMoveModal')">{{ $t("Cancel") }}</b-button>
+    <b-button type="is-text" @click="$emit('close-move-modal')">{{ $t("Cancel") }}</b-button>
   </div>
 </template>
 <script lang="ts">
@@ -81,15 +81,15 @@ export default class ResourceSelector extends Vue {
 
   resource: IResource | undefined = this.initialResource.parent;
 
-  goDown(element: IResource) {
+  goDown(element: IResource): void {
     if (element.type === "folder" && element.id !== this.initialResource.id) {
       this.resource = element;
     }
   }
 
-  updateResource() {
+  updateResource(): void {
     this.$emit(
-      "updateResource",
+      "update-resource",
       {
         id: this.initialResource.id,
         title: this.initialResource.title,
@@ -100,12 +100,12 @@ export default class ResourceSelector extends Vue {
     );
   }
 
-  get moveDisabled() {
+  get moveDisabled(): boolean | undefined {
     return (
       (this.initialResource.parent &&
         this.resource &&
         this.initialResource.parent.path === this.resource.path) ||
-      (this.initialResource.parent == undefined && this.resource && this.resource.path === "/")
+      (this.initialResource.parent === undefined && this.resource && this.resource.path === "/")
     );
   }
 }
diff --git a/js/src/components/SearchField.vue b/js/src/components/SearchField.vue
index 1e2a27a86..9261059a3 100644
--- a/js/src/components/SearchField.vue
+++ b/js/src/components/SearchField.vue
@@ -23,9 +23,9 @@ export default class SearchField extends Vue {
 
   search = "";
 
-  enter() {
+  async enter(): Promise<void> {
     this.$emit("navbar-search");
-    this.$router.push({
+    await this.$router.push({
       name: RouteName.SEARCH,
       query: { term: this.search },
     });
diff --git a/js/src/components/Settings/SettingMenuItem.vue b/js/src/components/Settings/SettingMenuItem.vue
index 2f201ae94..5c9103491 100644
--- a/js/src/components/Settings/SettingMenuItem.vue
+++ b/js/src/components/Settings/SettingMenuItem.vue
@@ -16,7 +16,7 @@ export default class SettingMenuItem extends Vue {
 
   @Prop({ required: true, type: Object }) to!: Route;
 
-  get isActive() {
+  get isActive(): boolean {
     if (!this.to) return false;
     if (this.to.name === this.$route.name) {
       if (this.to.params) {
diff --git a/js/src/components/Settings/SettingMenuSection.vue b/js/src/components/Settings/SettingMenuSection.vue
index cc2d1953a..264eb19b1 100644
--- a/js/src/components/Settings/SettingMenuSection.vue
+++ b/js/src/components/Settings/SettingMenuSection.vue
@@ -20,11 +20,12 @@ export default class SettingMenuSection extends Vue {
 
   @Prop({ required: true, type: Object }) to!: Route;
 
-  get sectionActive() {
+  get sectionActive(): boolean {
     if (this.$slots.default) {
       return this.$slots.default.some(
         ({
           componentOptions: {
+            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
             // @ts-ignore
             propsData: { to },
           },
diff --git a/js/src/components/Settings/SettingsMenu.vue b/js/src/components/Settings/SettingsMenu.vue
index d64ec2d5c..09f713c1c 100644
--- a/js/src/components/Settings/SettingsMenu.vue
+++ b/js/src/components/Settings/SettingsMenu.vue
@@ -55,13 +55,14 @@
   </aside>
 </template>
 <script lang="ts">
-import { Component, Prop, Vue } from "vue-property-decorator";
+import { Component, Vue } from "vue-property-decorator";
+import { ICurrentUserRole } from "@/types/enums";
 import SettingMenuSection from "./SettingMenuSection.vue";
 import SettingMenuItem from "./SettingMenuItem.vue";
 import { IDENTITIES } from "../../graphql/actor";
 import { IPerson, Person } from "../../types/actor";
 import { CURRENT_USER_CLIENT } from "../../graphql/user";
-import { ICurrentUser, ICurrentUserRole } from "../../types/current-user.model";
+import { ICurrentUser } from "../../types/current-user.model";
 
 import RouteName from "../../router/name";
 
diff --git a/js/src/components/Todo/FullTodo.vue b/js/src/components/Todo/FullTodo.vue
index 3ba34e7e3..9ccf2e9b7 100644
--- a/js/src/components/Todo/FullTodo.vue
+++ b/js/src/components/Todo/FullTodo.vue
@@ -18,7 +18,7 @@
 </template>
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { debounce } from "lodash";
+import { debounce, DebouncedFunc } from "lodash";
 import { SnackbarProgrammatic as Snackbar } from "buefy";
 import { ITodo } from "../../types/todos";
 import RouteName from "../../router/name";
@@ -36,7 +36,7 @@ export default class Todo extends Vue {
 
   editMode = false;
 
-  debounceUpdateTodo!: Function;
+  debounceUpdateTodo!: DebouncedFunc<(obj: Record<string, unknown>) => Promise<void>>;
 
   // We put this in data because of issues like
   // https://github.com/vuejs/vue-class-component/issues/263
diff --git a/js/src/components/Utils/RedirectWithAccount.vue b/js/src/components/Utils/RedirectWithAccount.vue
index 52c2fb8f1..bd1fa1c17 100644
--- a/js/src/components/Utils/RedirectWithAccount.vue
+++ b/js/src/components/Utils/RedirectWithAccount.vue
@@ -54,7 +54,7 @@
 import { Component, Prop, Vue } from "vue-property-decorator";
 import VerticalDivider from "@/components/Utils/VerticalDivider.vue";
 import Subtitle from "@/components/Utils/Subtitle.vue";
-import { LoginErrorCode } from "@/types/login-error-code.model";
+import { LoginErrorCode } from "@/types/enums";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/mixins/actor.ts b/js/src/mixins/actor.ts
index 9954edf5a..779eae0a7 100644
--- a/js/src/mixins/actor.ts
+++ b/js/src/mixins/actor.ts
@@ -4,9 +4,9 @@ import { Component, Vue } from "vue-property-decorator";
 
 @Component
 export default class ActorMixin extends Vue {
-  static actorIsOrganizer(actor: IActor, event: IEvent) {
+  static actorIsOrganizer(actor: IActor, event: IEvent): boolean {
     console.log("actorIsOrganizer actor", actor.id);
     console.log("actorIsOrganizer event", event);
-    return event.organizerActor && actor.id === event.organizerActor.id;
+    return event.organizerActor !== undefined && actor.id === event.organizerActor.id;
   }
 }
diff --git a/js/src/mixins/event.ts b/js/src/mixins/event.ts
index 8bcf9d659..ef672c7c5 100644
--- a/js/src/mixins/event.ts
+++ b/js/src/mixins/event.ts
@@ -1,7 +1,8 @@
 import { mixins } from "vue-class-component";
 import { Component, Vue } from "vue-property-decorator";
 import { SnackbarProgrammatic as Snackbar } from "buefy";
-import { IParticipant, ParticipantRole } from "../types/participant.model";
+import { ParticipantRole } from "@/types/enums";
+import { IParticipant } from "../types/participant.model";
 import { IEvent } from "../types/event.model";
 import {
   DELETE_EVENT,
diff --git a/js/src/mixins/group.ts b/js/src/mixins/group.ts
index d39e593b4..db47fb957 100644
--- a/js/src/mixins/group.ts
+++ b/js/src/mixins/group.ts
@@ -2,7 +2,8 @@ import { PERSON_MEMBERSHIPS, CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
 import { GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED } from "@/graphql/event";
 import { FETCH_GROUP } from "@/graphql/group";
 import RouteName from "@/router/name";
-import { Group, IActor, IGroup, IPerson, MemberRole } from "@/types/actor";
+import { Group, IActor, IGroup, IPerson } from "@/types/actor";
+import { MemberRole } from "@/types/enums";
 import { Component, Vue } from "vue-property-decorator";
 
 @Component({
diff --git a/js/src/mixins/relay.ts b/js/src/mixins/relay.ts
index 3b754a5fd..20d3238d6 100644
--- a/js/src/mixins/relay.ts
+++ b/js/src/mixins/relay.ts
@@ -1,8 +1,9 @@
 import { Component, Vue, Ref } from "vue-property-decorator";
-import { ActorType, IActor } from "@/types/actor";
+import { IActor } from "@/types/actor";
 import { IFollower } from "@/types/actor/follower.model";
 import { RELAY_FOLLOWERS, RELAY_FOLLOWINGS } from "@/graphql/admin";
 import { Paginate } from "@/types/paginate";
+import { ActorType } from "@/types/enums";
 
 @Component({
   apollo: {
diff --git a/js/src/router/event.ts b/js/src/router/event.ts
index 6dbc6addb..f443235f4 100644
--- a/js/src/router/event.ts
+++ b/js/src/router/event.ts
@@ -18,7 +18,6 @@ export enum EventRouteName {
   EVENT_PARTICIPATE_WITHOUT_ACCOUNT = "EVENT_PARTICIPATE_WITHOUT_ACCOUNT",
   EVENT_PARTICIPATE_LOGGED_OUT = "EVENT_PARTICIPATE_LOGGED_OUT",
   EVENT_PARTICIPATE_CONFIRM = "EVENT_PARTICIPATE_CONFIRM",
-  LOCATION = "Location",
   TAG = "Tag",
 }
 
@@ -46,14 +45,17 @@ export const eventRoutes: RouteConfig[] = [
     name: EventRouteName.EDIT_EVENT,
     component: editEvent,
     meta: { requiredAuth: true },
-    props: (route: Route) => ({ ...route.params, ...{ isUpdate: true } }),
+    props: (route: Route): Record<string, unknown> => ({ ...route.params, ...{ isUpdate: true } }),
   },
   {
     path: "/events/duplicate/:eventId",
     name: EventRouteName.DUPLICATE_EVENT,
     component: editEvent,
     meta: { requiredAuth: true },
-    props: (route: Route) => ({ ...route.params, ...{ isDuplicate: true } }),
+    props: (route: Route): Record<string, unknown> => ({
+      ...route.params,
+      ...{ isDuplicate: true },
+    }),
   },
   {
     path: "/events/:eventId/participations",
@@ -62,12 +64,6 @@ export const eventRoutes: RouteConfig[] = [
     meta: { requiredAuth: true },
     props: true,
   },
-  {
-    path: "/location/new",
-    name: EventRouteName.LOCATION,
-    component: () => import(/* webpackChunkName: "Location" */ "@/views/Location.vue"),
-    meta: { requiredAuth: true },
-  },
   {
     path: "/events/:uuid",
     name: EventRouteName.EVENT,
diff --git a/js/src/router/guards/auth-guard.ts b/js/src/router/guards/auth-guard.ts
index 15b8566b3..4dfa635e1 100644
--- a/js/src/router/guards/auth-guard.ts
+++ b/js/src/router/guards/auth-guard.ts
@@ -1,7 +1,7 @@
 import { NavigationGuard } from "vue-router";
 import { UserRouteName } from "@/router/user";
-import { LoginErrorCode } from "@/types/login-error-code.model";
 import { AUTH_ACCESS_TOKEN } from "@/constants";
+import { LoginErrorCode } from "@/types/enums";
 
 // eslint-disable-next-line import/prefer-default-export
 export const authGuardIfNeeded: NavigationGuard = async (to, from, next) => {
diff --git a/js/src/router/guards/register-guard.ts b/js/src/router/guards/register-guard.ts
index b78acb63e..879d67f83 100644
--- a/js/src/router/guards/register-guard.ts
+++ b/js/src/router/guards/register-guard.ts
@@ -1,6 +1,6 @@
+import { ErrorCode } from "@/types/enums";
 import { NavigationGuard } from "vue-router";
 import { CONFIG } from "../../graphql/config";
-import { ErrorCode } from "../../types/error-code.model";
 import apolloProvider from "../../vue-apollo";
 
 // eslint-disable-next-line import/prefer-default-export
diff --git a/js/src/router/settings.ts b/js/src/router/settings.ts
index 67fcabdae..c4ddacf0c 100644
--- a/js/src/router/settings.ts
+++ b/js/src/router/settings.ts
@@ -1,4 +1,4 @@
-import { RouteConfig } from "vue-router";
+import { Route, RouteConfig } from "vue-router";
 
 export enum SettingsRouteName {
   SETTINGS = "SETTINGS",
@@ -199,7 +199,10 @@ export const settingsRoutes: RouteConfig[] = [
           import(
             /* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue"
           ),
-        props: (route) => ({ identityName: route.params.identityName, isUpdate: false }),
+        props: (route: Route): Record<string, unknown> => ({
+          identityName: route.params.identityName,
+          isUpdate: false,
+        }),
         meta: { requiredAuth: true },
       },
       {
@@ -209,7 +212,10 @@ export const settingsRoutes: RouteConfig[] = [
           import(
             /* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue"
           ),
-        props: (route) => ({ identityName: route.params.identityName, isUpdate: true }),
+        props: (route: Route): Record<string, unknown> => ({
+          identityName: route.params.identityName,
+          isUpdate: true,
+        }),
         meta: { requiredAuth: true },
       },
     ],
diff --git a/js/src/router/user.ts b/js/src/router/user.ts
index 96989b5af..fd7ce296a 100644
--- a/js/src/router/user.ts
+++ b/js/src/router/user.ts
@@ -1,5 +1,5 @@
 import { beforeRegisterGuard } from "@/router/guards/register-guard";
-import { RouteConfig } from "vue-router";
+import { Route, RouteConfig } from "vue-router";
 
 export enum UserRouteName {
   REGISTER = "Register",
@@ -27,7 +27,7 @@ export const userRoutes: RouteConfig[] = [
     component: () =>
       import(/* webpackChunkName: "RegisterProfile" */ "@/views/Account/Register.vue"),
     // We can only pass string values through params, therefore
-    props: (route) => ({
+    props: (route: Route): Record<string, unknown> => ({
       email: route.params.email,
       userAlreadyActivated: route.params.userAlreadyActivated === "true",
     }),
diff --git a/js/src/services/AnonymousParticipationStorage.ts b/js/src/services/AnonymousParticipationStorage.ts
index 43eb9fbe2..a8f376d3c 100644
--- a/js/src/services/AnonymousParticipationStorage.ts
+++ b/js/src/services/AnonymousParticipationStorage.ts
@@ -16,6 +16,14 @@ class AnonymousParticipationNotFoundError extends Error {
   }
 }
 
+function jsonToMap(jsonStr: string): Map<string, IAnonymousParticipation> {
+  return new Map(JSON.parse(jsonStr));
+}
+
+function mapToJson(map: Map<any, any>): string {
+  return JSON.stringify([...map]);
+}
+
 /**
  * Fetch existing anonymous participations saved inside this browser
  */
@@ -25,13 +33,6 @@ function getLocalAnonymousParticipations(): Map<string, IAnonymousParticipation>
   );
 }
 
-function mapToJson(map: Map<any, any>): string {
-  return JSON.stringify([...map]);
-}
-function jsonToMap(jsonStr: string): Map<string, IAnonymousParticipation> {
-  return new Map(JSON.parse(jsonStr));
-}
-
 /**
  * Purge participations which expiration has been reached
  * @param participations Map
@@ -39,6 +40,7 @@ function jsonToMap(jsonStr: string): Map<string, IAnonymousParticipation> {
 function purgeOldParticipations(
   participations: Map<string, IAnonymousParticipation>
 ): Map<string, IAnonymousParticipation> {
+  // eslint-disable-next-line no-restricted-syntax
   for (const [hashedUUID, { expiration }] of participations) {
     if (expiration < new Date()) {
       participations.delete(hashedUUID);
@@ -67,7 +69,18 @@ function buildExpiration(event: IEvent): Date {
   return expiration;
 }
 
-async function addLocalUnconfirmedAnonymousParticipation(event: IEvent, cancellationToken: string) {
+async function digestMessage(message: string): Promise<string> {
+  const encoder = new TextEncoder();
+  const data = encoder.encode(message);
+  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
+  const hashArray = Array.from(new Uint8Array(hashBuffer));
+  return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
+}
+
+async function addLocalUnconfirmedAnonymousParticipation(
+  event: IEvent,
+  cancellationToken: string
+): Promise<void> {
   /**
    * We hash the event UUID so that we can't know which events an anonymous user goes by looking up it's localstorage
    */
@@ -84,7 +97,7 @@ async function addLocalUnconfirmedAnonymousParticipation(event: IEvent, cancella
   });
 }
 
-async function confirmLocalAnonymousParticipation(uuid: string) {
+async function confirmLocalAnonymousParticipation(uuid: string): Promise<void> {
   const participations = purgeOldParticipations(getLocalAnonymousParticipations());
   const hashedUUID = await digestMessage(uuid);
   const participation = participations.get(hashedUUID);
@@ -95,11 +108,6 @@ async function confirmLocalAnonymousParticipation(uuid: string) {
   }
 }
 
-async function isParticipatingInThisEvent(eventUUID: string): Promise<boolean> {
-  const participation = await getParticipation(eventUUID);
-  return participation !== undefined && participation.confirmed;
-}
-
 async function getParticipation(eventUUID: string): Promise<IAnonymousParticipation> {
   const hashedUUID = await digestMessage(eventUUID);
   const participation = purgeOldParticipations(getLocalAnonymousParticipations()).get(hashedUUID);
@@ -109,6 +117,11 @@ async function getParticipation(eventUUID: string): Promise<IAnonymousParticipat
   throw new AnonymousParticipationNotFoundError("Participation not found");
 }
 
+async function isParticipatingInThisEvent(eventUUID: string): Promise<boolean> {
+  const participation = await getParticipation(eventUUID);
+  return participation !== undefined && participation.confirmed;
+}
+
 async function getLeaveTokenForParticipation(eventUUID: string): Promise<string> {
   return (await getParticipation(eventUUID)).token;
 }
@@ -120,14 +133,6 @@ async function removeAnonymousParticipation(eventUUID: string): Promise<void> {
   localStorage.setItem(ANONYMOUS_PARTICIPATIONS_LOCALSTORAGE_KEY, mapToJson(participations));
 }
 
-async function digestMessage(message: string): Promise<string> {
-  const encoder = new TextEncoder();
-  const data = encoder.encode(message);
-  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
-  const hashArray = Array.from(new Uint8Array(hashBuffer));
-  return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
-}
-
 export {
   addLocalUnconfirmedAnonymousParticipation,
   confirmLocalAnonymousParticipation,
diff --git a/js/src/types/actor/actor.model.ts b/js/src/types/actor/actor.model.ts
index d74db12ed..b4f86e078 100644
--- a/js/src/types/actor/actor.model.ts
+++ b/js/src/types/actor/actor.model.ts
@@ -1,12 +1,5 @@
-import { IMedia } from "@/types/media.model";
-
-export enum ActorType {
-  PERSON = "PERSON",
-  APPLICATION = "APPLICATION",
-  GROUP = "GROUP",
-  ORGANISATION = "ORGANISATION",
-  SERVICE = "SERVICE",
-}
+import type { IMedia } from "@/types/media.model";
+import { ActorType } from "../enums";
 
 export interface IActor {
   id?: string;
diff --git a/js/src/types/actor/follower.model.ts b/js/src/types/actor/follower.model.ts
index 21f51ec16..9c96b7ec0 100644
--- a/js/src/types/actor/follower.model.ts
+++ b/js/src/types/actor/follower.model.ts
@@ -1,4 +1,4 @@
-import { IActor } from "@/types/actor/actor.model";
+import type { IActor } from "@/types/actor/actor.model";
 
 export interface IFollower {
   id?: string;
diff --git a/js/src/types/actor/group.model.ts b/js/src/types/actor/group.model.ts
index 41cb6f877..f3966c122 100644
--- a/js/src/types/actor/group.model.ts
+++ b/js/src/types/actor/group.model.ts
@@ -1,38 +1,15 @@
-import { Actor, ActorType, IActor } from "./actor.model";
-import { Paginate } from "../paginate";
-import { IResource } from "../resource";
-import { ITodoList } from "../todos";
-import { IEvent } from "../event.model";
-import { IDiscussion } from "../discussions";
-import { IPerson } from "./person.model";
-import { IPost } from "../post.model";
-import { IAddress, Address } from "../address.model";
-
-export enum MemberRole {
-  NOT_APPROVED = "NOT_APPROVED",
-  INVITED = "INVITED",
-  MEMBER = "MEMBER",
-  MODERATOR = "MODERATOR",
-  ADMINISTRATOR = "ADMINISTRATOR",
-  CREATOR = "CREATOR",
-  REJECTED = "REJECTED",
-}
-
-export enum Openness {
-  INVITE_ONLY = "INVITE_ONLY",
-  MODERATED = "MODERATED",
-  OPEN = "OPEN",
-}
-
-export interface IMember {
-  id?: string;
-  role: MemberRole;
-  parent: IGroup;
-  actor: IActor;
-  invitedBy?: IPerson;
-  insertedAt: string;
-  updatedAt: string;
-}
+import type { IActor } from "./actor.model";
+import { Actor } from "./actor.model";
+import type { Paginate } from "../paginate";
+import type { IResource } from "../resource";
+import type { IEvent } from "../event.model";
+import type { IDiscussion } from "../discussions";
+import type { IPost } from "../post.model";
+import type { IAddress } from "../address.model";
+import { Address } from "../address.model";
+import { ActorType, Openness } from "../enums";
+import type { IMember } from "./member.model";
+import type { ITodoList } from "../todolist";
 
 export interface IGroup extends IActor {
   members: Paginate<IMember>;
diff --git a/js/src/types/actor/member.model.ts b/js/src/types/actor/member.model.ts
new file mode 100644
index 000000000..24f1c3756
--- /dev/null
+++ b/js/src/types/actor/member.model.ts
@@ -0,0 +1,12 @@
+import type { IActor, IGroup, IPerson } from ".";
+import { MemberRole } from "../enums";
+
+export interface IMember {
+  id?: string;
+  role: MemberRole;
+  parent: IGroup;
+  actor: IActor;
+  invitedBy?: IPerson;
+  insertedAt: string;
+  updatedAt: string;
+}
diff --git a/js/src/types/actor/person.model.ts b/js/src/types/actor/person.model.ts
index 928854e71..699f8a72d 100644
--- a/js/src/types/actor/person.model.ts
+++ b/js/src/types/actor/person.model.ts
@@ -1,15 +1,11 @@
-import { ICurrentUser } from "../current-user.model";
-import { IEvent } from "../event.model";
-import { Actor, IActor } from "./actor.model";
-import { Paginate } from "../paginate";
-import { IMember } from "./group.model";
-import { IParticipant } from "../participant.model";
-
-export interface IFeedToken {
-  token: string;
-  actor?: IPerson;
-  user: ICurrentUser;
-}
+import type { ICurrentUser } from "../current-user.model";
+import type { IEvent } from "../event.model";
+import { Actor } from "./actor.model";
+import type { IActor } from "./actor.model";
+import type { Paginate } from "../paginate";
+import type { IParticipant } from "../participant.model";
+import type { IMember } from "./member.model";
+import type { IFeedToken } from "../feedtoken.model";
 
 export interface IPerson extends IActor {
   feedTokens: IFeedToken[];
diff --git a/js/src/types/address.model.ts b/js/src/types/address.model.ts
index e320f59a9..a306a6f1c 100644
--- a/js/src/types/address.model.ts
+++ b/js/src/types/address.model.ts
@@ -1,4 +1,5 @@
-import { poiIcons, IPOIIcon } from "@/utils/poiIcons";
+import { poiIcons } from "@/utils/poiIcons";
+import type { IPOIIcon } from "@/utils/poiIcons";
 
 export interface IAddress {
   id?: string;
@@ -53,7 +54,7 @@ export class Address implements IAddress {
     this.originId = hash.originId;
   }
 
-  get poiInfos() {
+  get poiInfos(): { name: string; alternativeName: string; poiIcon: IPOIIcon } {
     /* generate name corresponding to poi type */
     let name = "";
     let alternativeName = "";
diff --git a/js/src/types/admin.model.ts b/js/src/types/admin.model.ts
index 9872e5aca..00d165428 100644
--- a/js/src/types/admin.model.ts
+++ b/js/src/types/admin.model.ts
@@ -1,5 +1,6 @@
-import { IEvent } from "@/types/event.model";
-import { IGroup } from "./actor";
+import type { IEvent } from "@/types/event.model";
+import type { IGroup } from "./actor";
+import { InstanceTermsType } from "./enums";
 
 export interface IDashboard {
   lastPublicEventPublished: IEvent;
@@ -14,23 +15,10 @@ export interface IDashboard {
   numberOfConfirmedParticipationsToLocalEvents: number;
 }
 
-export enum InstanceTermsType {
-  DEFAULT = "DEFAULT",
-  URL = "URL",
-  CUSTOM = "CUSTOM",
-}
-
-export enum InstancePrivacyType {
-  DEFAULT = "DEFAULT",
-  URL = "URL",
-  CUSTOM = "CUSTOM",
-}
-
 export interface ILanguage {
   code: string;
   name: string;
 }
-
 export interface IAdminSettings {
   instanceName: string;
   instanceDescription: string;
diff --git a/js/src/types/comment.model.ts b/js/src/types/comment.model.ts
index 5f45f4bd7..95de6f3af 100644
--- a/js/src/types/comment.model.ts
+++ b/js/src/types/comment.model.ts
@@ -1,5 +1,7 @@
-import { Actor, IActor } from "@/types/actor";
-import { EventModel, IEvent } from "@/types/event.model";
+import { Actor } from "@/types/actor";
+import type { IActor } from "@/types/actor";
+import type { IEvent } from "@/types/event.model";
+import { EventModel } from "@/types/event.model";
 
 export interface IComment {
   id?: string;
diff --git a/js/src/types/config.model.ts b/js/src/types/config.model.ts
index 3c314b387..af43f666e 100644
--- a/js/src/types/config.model.ts
+++ b/js/src/types/config.model.ts
@@ -1,5 +1,5 @@
-import { InstanceTermsType, InstancePrivacyType } from "./admin.model";
-import { IProvider } from "./resource";
+import { InstancePrivacyType, InstanceTermsType } from "./enums";
+import type { IProvider } from "./resource";
 
 export interface IOAuthProvider {
   id: string;
diff --git a/js/src/types/current-user.model.ts b/js/src/types/current-user.model.ts
index 3b2a29ea0..2c834c552 100644
--- a/js/src/types/current-user.model.ts
+++ b/js/src/types/current-user.model.ts
@@ -1,13 +1,8 @@
-import { IEvent } from "@/types/event.model";
-import { IPerson } from "@/types/actor/person.model";
-import { Paginate } from "./paginate";
-import { IParticipant } from "./participant.model";
-
-export enum ICurrentUserRole {
-  USER = "USER",
-  MODERATOR = "MODERATOR",
-  ADMINISTRATOR = "ADMINISTRATOR",
-}
+import type { IEvent } from "@/types/event.model";
+import type { IPerson } from "@/types/actor/person.model";
+import type { Paginate } from "./paginate";
+import type { IParticipant } from "./participant.model";
+import { ICurrentUserRole, INotificationPendingEnum } from "./enums";
 
 export interface ICurrentUser {
   id: string;
@@ -17,13 +12,6 @@ export interface ICurrentUser {
   defaultActor?: IPerson;
 }
 
-export enum INotificationPendingEnum {
-  NONE = "NONE",
-  DIRECT = "DIRECT",
-  ONE_DAY = "ONE_DAY",
-  ONE_HOUR = "ONE_HOUR",
-}
-
 export interface IUserSettings {
   timezone: string;
   notificationOnDay: boolean;
@@ -49,14 +37,3 @@ export interface IUser extends ICurrentUser {
   currentSignInIp: string;
   currentSignInAt: string;
 }
-
-export enum IAuthProvider {
-  LDAP = "ldap",
-  GOOGLE = "google",
-  DISCORD = "discord",
-  GITHUB = "github",
-  KEYCLOAK = "keycloak",
-  FACEBOOK = "facebook",
-  GITLAB = "gitlab",
-  TWITTER = "twitter",
-}
diff --git a/js/src/types/discussions.ts b/js/src/types/discussions.ts
index 11ced50ad..d3b483b9b 100644
--- a/js/src/types/discussions.ts
+++ b/js/src/types/discussions.ts
@@ -1,6 +1,7 @@
-import { IActor, IPerson } from "@/types/actor";
-import { IComment, CommentModel } from "@/types/comment.model";
-import { Paginate } from "@/types/paginate";
+import type { IActor, IPerson } from "@/types/actor";
+import type { IComment } from "@/types/comment.model";
+import { CommentModel } from "@/types/comment.model";
+import type { Paginate } from "@/types/paginate";
 
 export interface IDiscussion {
   id?: string;
diff --git a/js/src/types/enums.ts b/js/src/types/enums.ts
new file mode 100644
index 000000000..1fce2d6c4
--- /dev/null
+++ b/js/src/types/enums.ts
@@ -0,0 +1,161 @@
+export enum InstanceTermsType {
+  DEFAULT = "DEFAULT",
+  URL = "URL",
+  CUSTOM = "CUSTOM",
+}
+
+export enum InstancePrivacyType {
+  DEFAULT = "DEFAULT",
+  URL = "URL",
+  CUSTOM = "CUSTOM",
+}
+
+export enum ICurrentUserRole {
+  USER = "USER",
+  MODERATOR = "MODERATOR",
+  ADMINISTRATOR = "ADMINISTRATOR",
+}
+
+export enum INotificationPendingEnum {
+  NONE = "NONE",
+  DIRECT = "DIRECT",
+  ONE_DAY = "ONE_DAY",
+  ONE_HOUR = "ONE_HOUR",
+}
+
+export enum IAuthProvider {
+  LDAP = "ldap",
+  GOOGLE = "google",
+  DISCORD = "discord",
+  GITHUB = "github",
+  KEYCLOAK = "keycloak",
+  FACEBOOK = "facebook",
+  GITLAB = "gitlab",
+  TWITTER = "twitter",
+}
+
+export enum ErrorCode {
+  UNKNOWN = "unknown",
+  REGISTRATION_CLOSED = "registration_closed",
+}
+
+export enum CommentModeration {
+  ALLOW_ALL = "ALLOW_ALL",
+  MODERATED = "MODERATED",
+  CLOSED = "CLOSED",
+}
+
+export enum EventStatus {
+  TENTATIVE = "TENTATIVE",
+  CONFIRMED = "CONFIRMED",
+  CANCELLED = "CANCELLED",
+}
+
+export enum EventVisibility {
+  PUBLIC = "PUBLIC",
+  UNLISTED = "UNLISTED",
+  RESTRICTED = "RESTRICTED",
+  PRIVATE = "PRIVATE",
+}
+
+export enum EventJoinOptions {
+  FREE = "FREE",
+  RESTRICTED = "RESTRICTED",
+  INVITE = "INVITE",
+}
+
+export enum EventVisibilityJoinOptions {
+  PUBLIC = "PUBLIC",
+  LINK = "LINK",
+  LIMITED = "LIMITED",
+}
+
+export enum Category {
+  BUSINESS = "business",
+  CONFERENCE = "conference",
+  BIRTHDAY = "birthday",
+  DEMONSTRATION = "demonstration",
+  MEETING = "meeting",
+}
+
+export enum LoginErrorCode {
+  NEED_TO_LOGIN = "need_to_login",
+}
+
+export enum LoginError {
+  USER_NOT_CONFIRMED = "User account not confirmed",
+  USER_DOES_NOT_EXIST = "No user with this email was found",
+  USER_EMAIL_PASSWORD_INVALID = "Impossible to authenticate, either your email or password are invalid.",
+  LOGIN_PROVIDER_ERROR = "Error with Login Provider",
+  LOGIN_PROVIDER_NOT_FOUND = "Login Provider not found",
+  USER_DISABLED = "This user has been disabled",
+}
+
+export enum ResetError {
+  USER_IMPOSSIBLE_TO_RESET = "This user can't reset their password",
+}
+
+export enum ParticipantRole {
+  NOT_APPROVED = "NOT_APPROVED",
+  NOT_CONFIRMED = "NOT_CONFIRMED",
+  REJECTED = "REJECTED",
+  PARTICIPANT = "PARTICIPANT",
+  MODERATOR = "MODERATOR",
+  ADMINISTRATOR = "ADMINISTRATOR",
+  CREATOR = "CREATOR",
+}
+
+export enum PostVisibility {
+  PUBLIC = "PUBLIC",
+  UNLISTED = "UNLISTED",
+  RESTRICTED = "RESTRICTED",
+  PRIVATE = "PRIVATE",
+}
+
+export enum ReportStatusEnum {
+  OPEN = "OPEN",
+  CLOSED = "CLOSED",
+  RESOLVED = "RESOLVED",
+}
+
+export enum ActionLogAction {
+  NOTE_CREATION = "NOTE_CREATION",
+  NOTE_DELETION = "NOTE_DELETION",
+  REPORT_UPDATE_CLOSED = "REPORT_UPDATE_CLOSED",
+  REPORT_UPDATE_OPENED = "REPORT_UPDATE_OPENED",
+  REPORT_UPDATE_RESOLVED = "REPORT_UPDATE_RESOLVED",
+  EVENT_DELETION = "EVENT_DELETION",
+  COMMENT_DELETION = "COMMENT_DELETION",
+  ACTOR_SUSPENSION = "ACTOR_SUSPENSION",
+  ACTOR_UNSUSPENSION = "ACTOR_UNSUSPENSION",
+  USER_DELETION = "USER_DELETION",
+}
+
+export enum SearchTabs {
+  EVENTS = 0,
+  GROUPS = 1,
+}
+
+export enum ActorType {
+  PERSON = "PERSON",
+  APPLICATION = "APPLICATION",
+  GROUP = "GROUP",
+  ORGANISATION = "ORGANISATION",
+  SERVICE = "SERVICE",
+}
+
+export enum MemberRole {
+  NOT_APPROVED = "NOT_APPROVED",
+  INVITED = "INVITED",
+  MEMBER = "MEMBER",
+  MODERATOR = "MODERATOR",
+  ADMINISTRATOR = "ADMINISTRATOR",
+  CREATOR = "CREATOR",
+  REJECTED = "REJECTED",
+}
+
+export enum Openness {
+  INVITE_ONLY = "INVITE_ONLY",
+  MODERATED = "MODERATED",
+  OPEN = "OPEN",
+}
diff --git a/js/src/types/error-code.model.ts b/js/src/types/error-code.model.ts
deleted file mode 100644
index 03346340d..000000000
--- a/js/src/types/error-code.model.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export enum ErrorCode {
-  UNKNOWN = "unknown",
-  REGISTRATION_CLOSED = "registration_closed",
-}
diff --git a/js/src/types/event-options.model.ts b/js/src/types/event-options.model.ts
index 95e9ec405..f045d7f55 100644
--- a/js/src/types/event-options.model.ts
+++ b/js/src/types/event-options.model.ts
@@ -1,3 +1,5 @@
+import { CommentModeration } from "./enums";
+
 export interface IParticipationCondition {
   title: string;
   content: string;
@@ -10,12 +12,6 @@ export interface IOffer {
   url: string;
 }
 
-export enum CommentModeration {
-  ALLOW_ALL = "ALLOW_ALL",
-  MODERATED = "MODERATED",
-  CLOSED = "CLOSED",
-}
-
 export interface IEventOptions {
   maximumAttendeeCapacity: number;
   remainingAttendeeCapacity: number;
diff --git a/js/src/types/event.model.ts b/js/src/types/event.model.ts
index 9c47d894f..f00d11501 100644
--- a/js/src/types/event.model.ts
+++ b/js/src/types/event.model.ts
@@ -1,44 +1,15 @@
-import { Address, IAddress } from "@/types/address.model";
-import { ITag } from "@/types/tag.model";
-import { IMedia } from "@/types/media.model";
-import { IComment } from "@/types/comment.model";
-import { Paginate } from "@/types/paginate";
-import { Actor, Group, IActor, IGroup, IPerson } from "./actor";
-import { IParticipant } from "./participant.model";
-import { EventOptions, IEventOptions } from "./event-options.model";
-
-export enum EventStatus {
-  TENTATIVE = "TENTATIVE",
-  CONFIRMED = "CONFIRMED",
-  CANCELLED = "CANCELLED",
-}
-
-export enum EventVisibility {
-  PUBLIC = "PUBLIC",
-  UNLISTED = "UNLISTED",
-  RESTRICTED = "RESTRICTED",
-  PRIVATE = "PRIVATE",
-}
-
-export enum EventJoinOptions {
-  FREE = "FREE",
-  RESTRICTED = "RESTRICTED",
-  INVITE = "INVITE",
-}
-
-export enum EventVisibilityJoinOptions {
-  PUBLIC = "PUBLIC",
-  LINK = "LINK",
-  LIMITED = "LIMITED",
-}
-
-export enum Category {
-  BUSINESS = "business",
-  CONFERENCE = "conference",
-  BIRTHDAY = "birthday",
-  DEMONSTRATION = "demonstration",
-  MEETING = "meeting",
-}
+import { Address } from "@/types/address.model";
+import type { IAddress } from "@/types/address.model";
+import type { ITag } from "@/types/tag.model";
+import type { IMedia } from "@/types/media.model";
+import type { IComment } from "@/types/comment.model";
+import type { Paginate } from "@/types/paginate";
+import { Actor, Group } from "./actor";
+import type { IActor, IGroup, IPerson } from "./actor";
+import type { IParticipant } from "./participant.model";
+import { EventOptions } from "./event-options.model";
+import type { IEventOptions } from "./event-options.model";
+import { EventJoinOptions, EventStatus, EventVisibility } from "./enums";
 
 export interface IEventCardOptions {
   hideDate: boolean;
diff --git a/js/src/types/feedtoken.model.ts b/js/src/types/feedtoken.model.ts
new file mode 100644
index 000000000..1d08b5e14
--- /dev/null
+++ b/js/src/types/feedtoken.model.ts
@@ -0,0 +1,8 @@
+import type { IPerson } from "./actor";
+import type { ICurrentUser } from "./current-user.model";
+
+export interface IFeedToken {
+  token: string;
+  actor?: IPerson;
+  user: ICurrentUser;
+}
diff --git a/js/src/types/login-error-code.model.ts b/js/src/types/login-error-code.model.ts
deleted file mode 100644
index e691534a7..000000000
--- a/js/src/types/login-error-code.model.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export enum LoginErrorCode {
-  NEED_TO_LOGIN = "need_to_login",
-}
-
-export enum LoginError {
-  USER_NOT_CONFIRMED = "User account not confirmed",
-  USER_DOES_NOT_EXIST = "No user with this email was found",
-  USER_EMAIL_PASSWORD_INVALID = "Impossible to authenticate, either your email or password are invalid.",
-  LOGIN_PROVIDER_ERROR = "Error with Login Provider",
-  LOGIN_PROVIDER_NOT_FOUND = "Login Provider not found",
-  USER_DISABLED = "This user has been disabled",
-}
-
-export enum ResetError {
-  USER_IMPOSSIBLE_TO_RESET = "This user can't reset their password",
-}
diff --git a/js/src/types/login.model.ts b/js/src/types/login.model.ts
index a1798b040..b4750c6e9 100644
--- a/js/src/types/login.model.ts
+++ b/js/src/types/login.model.ts
@@ -1,4 +1,4 @@
-import { ICurrentUser } from "@/types/current-user.model";
+import type { ICurrentUser } from "@/types/current-user.model";
 
 export interface IToken {
   accessToken: string;
diff --git a/js/src/types/participant.model.ts b/js/src/types/participant.model.ts
index f74c71cd4..2cb516d95 100644
--- a/js/src/types/participant.model.ts
+++ b/js/src/types/participant.model.ts
@@ -1,15 +1,8 @@
-import { Actor, IActor } from "./actor";
-import { EventModel, IEvent } from "./event.model";
-
-export enum ParticipantRole {
-  NOT_APPROVED = "NOT_APPROVED",
-  NOT_CONFIRMED = "NOT_CONFIRMED",
-  REJECTED = "REJECTED",
-  PARTICIPANT = "PARTICIPANT",
-  MODERATOR = "MODERATOR",
-  ADMINISTRATOR = "ADMINISTRATOR",
-  CREATOR = "CREATOR",
-}
+import { Actor } from "./actor";
+import type { IActor } from "./actor";
+import { EventModel } from "./event.model";
+import type { IEvent } from "./event.model";
+import { ParticipantRole } from "./enums";
 
 export interface IParticipant {
   id?: string;
diff --git a/js/src/types/post.model.ts b/js/src/types/post.model.ts
index 3a5537961..c73af5b56 100644
--- a/js/src/types/post.model.ts
+++ b/js/src/types/post.model.ts
@@ -1,13 +1,7 @@
-import { ITag } from "./tag.model";
-import { IMedia } from "./media.model";
-import { IActor } from "./actor";
-
-export enum PostVisibility {
-  PUBLIC = "PUBLIC",
-  UNLISTED = "UNLISTED",
-  RESTRICTED = "RESTRICTED",
-  PRIVATE = "PRIVATE",
-}
+import type { ITag } from "./tag.model";
+import type { IMedia } from "./media.model";
+import type { IActor } from "./actor";
+import type { PostVisibility } from "./enums";
 
 export interface IPost {
   id?: string;
diff --git a/js/src/types/report.model.ts b/js/src/types/report.model.ts
index 6abfdf3ac..b7a79bdd9 100644
--- a/js/src/types/report.model.ts
+++ b/js/src/types/report.model.ts
@@ -1,13 +1,16 @@
-import { IActor, IPerson } from "@/types/actor";
-import { IEvent } from "@/types/event.model";
-import { IComment } from "@/types/comment.model";
+import type { IActor, IPerson } from "@/types/actor";
+import type { IEvent } from "@/types/event.model";
+import type { IComment } from "@/types/comment.model";
+import { ActionLogAction, ReportStatusEnum } from "./enums";
 
-export enum ReportStatusEnum {
-  OPEN = "OPEN",
-  CLOSED = "CLOSED",
-  RESOLVED = "RESOLVED",
+export interface IActionLogObject {
+  id: string;
+}
+export interface IReportNote extends IActionLogObject {
+  id: string;
+  content: string;
+  moderator: IActor;
 }
-
 export interface IReport extends IActionLogObject {
   id: string;
   reported: IActor;
@@ -21,29 +24,6 @@ export interface IReport extends IActionLogObject {
   status: ReportStatusEnum;
 }
 
-export interface IReportNote extends IActionLogObject {
-  id: string;
-  content: string;
-  moderator: IActor;
-}
-
-export interface IActionLogObject {
-  id: string;
-}
-
-export enum ActionLogAction {
-  NOTE_CREATION = "NOTE_CREATION",
-  NOTE_DELETION = "NOTE_DELETION",
-  REPORT_UPDATE_CLOSED = "REPORT_UPDATE_CLOSED",
-  REPORT_UPDATE_OPENED = "REPORT_UPDATE_OPENED",
-  REPORT_UPDATE_RESOLVED = "REPORT_UPDATE_RESOLVED",
-  EVENT_DELETION = "EVENT_DELETION",
-  COMMENT_DELETION = "COMMENT_DELETION",
-  ACTOR_SUSPENSION = "ACTOR_SUSPENSION",
-  ACTOR_UNSUSPENSION = "ACTOR_UNSUSPENSION",
-  USER_DELETION = "USER_DELETION",
-}
-
 export interface IActionLog {
   id: string;
   object: IReport | IReportNote | IEvent | IComment | IActor;
diff --git a/js/src/types/resource.ts b/js/src/types/resource.ts
index 85024bffe..2fa2dff7a 100644
--- a/js/src/types/resource.ts
+++ b/js/src/types/resource.ts
@@ -1,6 +1,20 @@
-import { Paginate } from "@/types/paginate";
-import { IActor } from "@/types/actor";
+import type { Paginate } from "@/types/paginate";
+import type { IActor } from "@/types/actor";
 
+export interface IResourceMetadata {
+  title?: string;
+  description?: string;
+  imageRemoteUrl?: string;
+  height?: number;
+  width?: number;
+  type?: string;
+  authorName?: string;
+  authorUrl?: string;
+  providerName?: string;
+  providerUrl?: string;
+  html?: string;
+  faviconUrl?: string;
+}
 export interface IResource {
   id?: string;
   title: string;
@@ -18,22 +32,7 @@ export interface IResource {
   type?: string;
 }
 
-export interface IResourceMetadata {
-  title?: string;
-  description?: string;
-  imageRemoteUrl?: string;
-  height?: number;
-  width?: number;
-  type?: string;
-  authorName?: string;
-  authorUrl?: string;
-  providerName?: string;
-  providerUrl?: string;
-  html?: string;
-  faviconUrl?: string;
-}
-
-export const mapServiceTypeToIcon: object = {
+export const mapServiceTypeToIcon: Record<string, string> = {
   pad: "file-document-outline",
   calc: "google-spreadsheet",
   visio: "webcam",
diff --git a/js/src/types/search.model.ts b/js/src/types/search.model.ts
index 4d4ddaf9c..e60b71c26 100644
--- a/js/src/types/search.model.ts
+++ b/js/src/types/search.model.ts
@@ -1,5 +1,5 @@
-import { IGroup, IPerson } from "@/types/actor";
-import { IEvent } from "@/types/event.model";
+import type { IGroup, IPerson } from "@/types/actor";
+import type { IEvent } from "@/types/event.model";
 
 export interface SearchEvent {
   total: number;
@@ -15,8 +15,3 @@ export interface SearchPerson {
   total: number;
   elements: IPerson[];
 }
-
-export enum SearchTabs {
-  EVENTS = 0,
-  GROUPS = 1,
-}
diff --git a/js/src/types/todolist.ts b/js/src/types/todolist.ts
new file mode 100644
index 000000000..fb5795818
--- /dev/null
+++ b/js/src/types/todolist.ts
@@ -0,0 +1,10 @@
+import type { IActor } from "./actor";
+import type { Paginate } from "./paginate";
+import type { ITodo } from "./todos";
+
+export interface ITodoList {
+  id: string;
+  title: string;
+  todos: Paginate<ITodo>;
+  actor?: IActor;
+}
diff --git a/js/src/types/todos.ts b/js/src/types/todos.ts
index 060443c56..ad3dd8a5c 100644
--- a/js/src/types/todos.ts
+++ b/js/src/types/todos.ts
@@ -1,12 +1,5 @@
-import { Paginate } from "@/types/paginate";
-import { IActor, IPerson } from "@/types/actor";
-
-export interface ITodoList {
-  id: string;
-  title: string;
-  todos: Paginate<ITodo>;
-  actor?: IActor;
-}
+import type { IActor, IPerson } from "@/types/actor";
+import { ITodoList } from "./todolist";
 
 export interface ITodo {
   id?: string;
diff --git a/js/src/utils/.editorconfig b/js/src/utils/.editorconfig
deleted file mode 100644
index b6b82f05c..000000000
--- a/js/src/utils/.editorconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-max_line_length = 120
-tab_width = 4
-trim_trailing_whitespace = true
-
-[*.ex]
-indent_size = 2
-tab_width = 2
-
-[*.scss]
-indent_size = 2
-
-[*.ts]
-indent_size = 2
-tab_width = 2
diff --git a/js/src/utils/asyncForEach.ts b/js/src/utils/asyncForEach.ts
index 5d6dc549e..ec4bb1cd6 100644
--- a/js/src/utils/asyncForEach.ts
+++ b/js/src/utils/asyncForEach.ts
@@ -1,5 +1,9 @@
-async function asyncForEach(array: Array<any>, callback: Function) {
+async function asyncForEach(
+  array: Array<any>,
+  callback: (arg0: any, arg1: number, arg2: Array<any>) => any
+): Promise<void> {
   for (let index = 0; index < array.length; index += 1) {
+    // eslint-disable-next-line no-await-in-loop
     await callback(array[index], index, array);
   }
 }
diff --git a/js/src/utils/auth.ts b/js/src/utils/auth.ts
index dbf56b057..abd073437 100644
--- a/js/src/utils/auth.ts
+++ b/js/src/utils/auth.ts
@@ -10,10 +10,10 @@ import {
 import { ILogin, IToken } from "@/types/login.model";
 import { UPDATE_CURRENT_USER_CLIENT } from "@/graphql/user";
 import ApolloClient from "apollo-client";
-import { ICurrentUserRole } from "@/types/current-user.model";
 import { IPerson } from "@/types/actor";
 import { IDENTITIES, UPDATE_CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
 import { NormalizedCacheObject } from "apollo-cache-inmemory";
+import { ICurrentUserRole } from "@/types/enums";
 
 export function saveTokenData(obj: IToken): void {
   localStorage.setItem(AUTH_ACCESS_TOKEN, obj.accessToken);
@@ -37,14 +37,19 @@ export function saveActorData(obj: IPerson): void {
 }
 
 export function deleteUserData(): void {
-  [AUTH_USER_ID, AUTH_USER_EMAIL, AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN, AUTH_USER_ROLE].forEach((key) => {
-    localStorage.removeItem(key);
-  });
+  [AUTH_USER_ID, AUTH_USER_EMAIL, AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN, AUTH_USER_ROLE].forEach(
+    (key) => {
+      localStorage.removeItem(key);
+    }
+  );
 }
 
 export class NoIdentitiesException extends Error {}
 
-export async function changeIdentity(apollo: ApolloClient<NormalizedCacheObject>, identity: IPerson): Promise<void> {
+export async function changeIdentity(
+  apollo: ApolloClient<NormalizedCacheObject>,
+  identity: IPerson
+): Promise<void> {
   await apollo.mutate({
     mutation: UPDATE_CURRENT_ACTOR_CLIENT,
     variables: identity,
@@ -69,7 +74,8 @@ export async function initializeCurrentActor(apollo: ApolloClient<any>): Promise
     console.warn("Logged user has no identities!");
     throw new NoIdentitiesException();
   }
-  const activeIdentity = identities.find((identity: IPerson) => identity.id === actorId) || (identities[0] as IPerson);
+  const activeIdentity =
+    identities.find((identity: IPerson) => identity.id === actorId) || (identities[0] as IPerson);
 
   if (activeIdentity) {
     await changeIdentity(apollo, activeIdentity);
diff --git a/js/src/utils/html.ts b/js/src/utils/html.ts
index 65ff595dd..ee6cea891 100644
--- a/js/src/utils/html.ts
+++ b/js/src/utils/html.ts
@@ -1,3 +1,3 @@
-export function nl2br(text: string) {
+export function nl2br(text: string): string {
   return text.replace(/(?:\r\n|\r|\n)/g, "<br>");
 }
diff --git a/js/src/utils/i18n.ts b/js/src/utils/i18n.ts
index a5605ab4a..30e2b06c7 100644
--- a/js/src/utils/i18n.ts
+++ b/js/src/utils/i18n.ts
@@ -7,10 +7,15 @@ import langs from "../i18n/langs.json";
 
 const DEFAULT_LOCALE = "en_US";
 
-let language = localStorage.getItem(USER_LOCALE) || (document.documentElement.getAttribute("lang") as string);
-language = language || ((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_");
+let language =
+  localStorage.getItem(USER_LOCALE) || (document.documentElement.getAttribute("lang") as string);
+language =
+  language ||
+  ((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_");
 export const locale =
-  language && Object.prototype.hasOwnProperty.call(langs, language) ? language : language.split("-")[0];
+  language && Object.prototype.hasOwnProperty.call(langs, language)
+    ? language
+    : language.split("-")[0];
 
 Vue.use(VueI18n);
 
diff --git a/js/src/utils/image.ts b/js/src/utils/image.ts
index 8a32e6a67..996f8bcf3 100644
--- a/js/src/utils/image.ts
+++ b/js/src/utils/image.ts
@@ -9,7 +9,11 @@ export async function buildFileFromIMedia(obj: IMedia | null | undefined): Promi
   return new File([blob], obj.name);
 }
 
-export function buildFileVariable(file: File | null, name: string, alt?: string): Record<string, unknown> {
+export function buildFileVariable(
+  file: File | null,
+  name: string,
+  alt?: string
+): Record<string, unknown> {
   if (!file) return {};
 
   return {
diff --git a/js/src/utils/object.ts b/js/src/utils/object.ts
deleted file mode 100644
index 0946c7186..000000000
--- a/js/src/utils/object.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export function buildObjectCollection<T, U>(collection: T[] | undefined, builder: new (p: T) => U) {
-  if (!collection || Array.isArray(collection) === false) return [];
-
-  return collection.map((v) => new builder(v));
-}
diff --git a/js/src/utils/username.ts b/js/src/utils/username.ts
index c565f7890..91fa7dae4 100644
--- a/js/src/utils/username.ts
+++ b/js/src/utils/username.ts
@@ -1,15 +1,5 @@
 import { IActor } from "@/types/actor";
 
-function autoUpdateUsername(actor: IActor, newDisplayName: string | null): IActor {
-  const oldUsername = convertToUsername(actor.name);
-
-  if (actor.preferredUsername === oldUsername) {
-    actor.preferredUsername = convertToUsername(newDisplayName);
-  }
-
-  return actor;
-}
-
 function convertToUsername(value: string | null): string {
   if (!value) return "";
 
@@ -22,6 +12,17 @@ function convertToUsername(value: string | null): string {
     .replace(/[^a-z0-9_]/g, "");
 }
 
+function autoUpdateUsername(actor: IActor, newDisplayName: string | null): IActor {
+  const actor2 = { ...actor };
+  const oldUsername = convertToUsername(actor.name);
+
+  if (actor.preferredUsername === oldUsername) {
+    actor2.preferredUsername = convertToUsername(newDisplayName);
+  }
+
+  return actor2;
+}
+
 function validateUsername(actor: IActor): boolean {
   return actor.preferredUsername === convertToUsername(actor.preferredUsername);
 }
diff --git a/js/src/utils/validators.ts b/js/src/utils/validators.ts
index a137d8d20..9270f0b61 100644
--- a/js/src/utils/validators.ts
+++ b/js/src/utils/validators.ts
@@ -1,7 +1,7 @@
-export function validateEmailField(value: string) {
+export function validateEmailField(value: string): boolean | string {
   return value.includes("@") || "Invalid e-mail.";
 }
 
-export function validateRequiredField(value: any) {
+export function validateRequiredField(value: unknown): boolean | string {
   return !!value || "Required.";
 }
diff --git a/js/src/views/About/Privacy.vue b/js/src/views/About/Privacy.vue
index 4d9da6174..80a36581d 100644
--- a/js/src/views/About/Privacy.vue
+++ b/js/src/views/About/Privacy.vue
@@ -9,7 +9,7 @@
 import { Component, Vue, Watch } from "vue-property-decorator";
 import { PRIVACY } from "@/graphql/config";
 import { IConfig } from "@/types/config.model";
-import { InstancePrivacyType } from "@/types/admin.model";
+import { InstancePrivacyType } from "@/types/enums";
 
 @Component({
   apollo: {
@@ -31,19 +31,18 @@ export default class Privacy extends Vue {
 
   locale: string | null = null;
 
-  created() {
+  created(): void {
     this.locale = this.$i18n.locale;
   }
 
   @Watch("config", { deep: true })
-  watchConfig(config: IConfig) {
+  watchConfig(config: IConfig): void {
     if (config.privacy.type) {
-      console.log(this.config.privacy);
       this.redirectToUrl();
     }
   }
 
-  redirectToUrl() {
+  redirectToUrl(): void {
     if (this.config.privacy.type === InstancePrivacyType.URL) {
       window.location.replace(this.config.privacy.url);
     }
diff --git a/js/src/views/About/Rules.vue b/js/src/views/About/Rules.vue
index b2b5651e1..2dd0059f3 100644
--- a/js/src/views/About/Rules.vue
+++ b/js/src/views/About/Rules.vue
@@ -7,10 +7,9 @@
 </template>
 
 <script lang="ts">
-import { Component, Vue, Watch } from "vue-property-decorator";
+import { Component, Vue } from "vue-property-decorator";
 import { RULES } from "@/graphql/config";
 import { IConfig } from "@/types/config.model";
-import { InstanceTermsType } from "@/types/admin.model";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/views/About/Terms.vue b/js/src/views/About/Terms.vue
index 5e55d78c1..7d60e8f7e 100644
--- a/js/src/views/About/Terms.vue
+++ b/js/src/views/About/Terms.vue
@@ -9,7 +9,7 @@
 import { Component, Vue, Watch } from "vue-property-decorator";
 import { TERMS } from "@/graphql/config";
 import { IConfig } from "@/types/config.model";
-import { InstanceTermsType } from "@/types/admin.model";
+import { InstanceTermsType } from "@/types/enums";
 
 @Component({
   apollo: {
@@ -31,19 +31,18 @@ export default class Terms extends Vue {
 
   locale: string | null = null;
 
-  created() {
+  created(): void {
     this.locale = this.$i18n.locale;
   }
 
   @Watch("config", { deep: true })
-  watchConfig(config: IConfig) {
+  watchConfig(config: IConfig): void {
     if (config.terms.type) {
-      console.log(this.config.terms);
       this.redirectToUrl();
     }
   }
 
-  redirectToUrl() {
+  redirectToUrl(): void {
     if (this.config.terms.type === InstanceTermsType.URL) {
       window.location.replace(this.config.terms.url);
     }
diff --git a/js/src/views/Admin/AdminGroupProfile.vue b/js/src/views/Admin/AdminGroupProfile.vue
index 6b7cb9279..85407e5f1 100644
--- a/js/src/views/Admin/AdminGroupProfile.vue
+++ b/js/src/views/Admin/AdminGroupProfile.vue
@@ -199,8 +199,9 @@
 import { Component, Vue, Prop } from "vue-property-decorator";
 import { GET_GROUP, REFRESH_PROFILE } from "@/graphql/group";
 import { formatBytes } from "@/utils/datetime";
+import { MemberRole } from "@/types/enums";
 import { SUSPEND_PROFILE, UNSUSPEND_PROFILE } from "../../graphql/actor";
-import { IGroup, MemberRole } from "../../types/actor";
+import { IGroup } from "../../types/actor";
 import { usernameWithDomain, IActor } from "../../types/actor/actor.model";
 import RouteName from "../../router/name";
 import ActorCard from "../../components/Account/ActorCard.vue";
diff --git a/js/src/views/Admin/AdminUserProfile.vue b/js/src/views/Admin/AdminUserProfile.vue
index fa0c43084..5a6ad751f 100644
--- a/js/src/views/Admin/AdminUserProfile.vue
+++ b/js/src/views/Admin/AdminUserProfile.vue
@@ -64,10 +64,11 @@
 import { Component, Vue, Prop } from "vue-property-decorator";
 import { Route } from "vue-router";
 import { formatBytes } from "@/utils/datetime";
+import { ICurrentUserRole } from "@/types/enums";
 import { GET_USER, SUSPEND_USER } from "../../graphql/user";
 import { usernameWithDomain } from "../../types/actor/actor.model";
 import RouteName from "../../router/name";
-import { IUser, ICurrentUserRole } from "../../types/current-user.model";
+import { IUser } from "../../types/current-user.model";
 import { IPerson } from "../../types/actor";
 
 @Component({
diff --git a/js/src/views/Admin/GroupProfiles.vue b/js/src/views/Admin/GroupProfiles.vue
index 5a99ae7a9..ae0f9dc46 100644
--- a/js/src/views/Admin/GroupProfiles.vue
+++ b/js/src/views/Admin/GroupProfiles.vue
@@ -83,7 +83,6 @@
 <script lang="ts">
 import { Component, Vue, Watch } from "vue-property-decorator";
 import { LIST_GROUPS } from "@/graphql/group";
-import { LIST_PROFILES } from "../../graphql/actor";
 import RouteName from "../../router/name";
 
 const PROFILES_PER_PAGE = 10;
@@ -124,7 +123,7 @@ export default class GroupProfiles extends Vue {
 
   RouteName = RouteName;
 
-  async onPageChange(page: number) {
+  async onPageChange(page: number): Promise<void> {
     this.page = page;
     await this.$apollo.queries.groups.fetchMore({
       variables: {
@@ -150,13 +149,19 @@ export default class GroupProfiles extends Vue {
     });
   }
 
-  onFiltersChange({ preferredUsername, domain }: { preferredUsername: string; domain: string }) {
+  onFiltersChange({
+    preferredUsername,
+    domain,
+  }: {
+    preferredUsername: string;
+    domain: string;
+  }): void {
     this.preferredUsername = preferredUsername;
     this.domain = domain;
   }
 
   @Watch("domain")
-  domainNotLocal() {
+  domainNotLocal(): void {
     this.local = this.domain === "";
   }
 }
diff --git a/js/src/views/Admin/Profiles.vue b/js/src/views/Admin/Profiles.vue
index eb96a0536..8ca74cc71 100644
--- a/js/src/views/Admin/Profiles.vue
+++ b/js/src/views/Admin/Profiles.vue
@@ -123,7 +123,7 @@ export default class Profiles extends Vue {
 
   RouteName = RouteName;
 
-  async onPageChange(page: number) {
+  async onPageChange(page: number): Promise<void> {
     this.page = page;
     await this.$apollo.queries.persons.fetchMore({
       variables: {
@@ -149,13 +149,19 @@ export default class Profiles extends Vue {
     });
   }
 
-  onFiltersChange({ preferredUsername, domain }: { preferredUsername: string; domain: string }) {
+  onFiltersChange({
+    preferredUsername,
+    domain,
+  }: {
+    preferredUsername: string;
+    domain: string;
+  }): void {
     this.preferredUsername = preferredUsername;
     this.domain = domain;
   }
 
   @Watch("domain")
-  domainNotLocal() {
+  domainNotLocal(): void {
     this.local = this.domain === "";
   }
 }
diff --git a/js/src/views/Admin/Settings.vue b/js/src/views/Admin/Settings.vue
index 417645690..a38b75474 100644
--- a/js/src/views/Admin/Settings.vue
+++ b/js/src/views/Admin/Settings.vue
@@ -290,12 +290,8 @@
 <script lang="ts">
 import { Component, Vue, Watch } from "vue-property-decorator";
 import { ADMIN_SETTINGS, SAVE_ADMIN_SETTINGS, LANGUAGES } from "@/graphql/admin";
-import {
-  IAdminSettings,
-  InstanceTermsType,
-  InstancePrivacyType,
-  ILanguage,
-} from "../../types/admin.model";
+import { InstancePrivacyType, InstanceTermsType } from "@/types/enums";
+import { IAdminSettings, ILanguage } from "../../types/admin.model";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/views/Admin/Users.vue b/js/src/views/Admin/Users.vue
index b554328bb..b9f7a225f 100644
--- a/js/src/views/Admin/Users.vue
+++ b/js/src/views/Admin/Users.vue
@@ -123,7 +123,7 @@ export default class Users extends Vue {
 
   RouteName = RouteName;
 
-  async onPageChange(page: number) {
+  async onPageChange(page: number): Promise<void> {
     this.page = page;
     await this.$apollo.queries.users.fetchMore({
       variables: {
diff --git a/js/src/views/Discussions/Discussion.vue b/js/src/views/Discussions/Discussion.vue
index 4faaba3f1..fa50209d2 100644
--- a/js/src/views/Discussions/Discussion.vue
+++ b/js/src/views/Discussions/Discussion.vue
@@ -222,23 +222,24 @@ export default class discussion extends mixins(GroupMixin) {
           },
         });
         if (!discussionData) return;
-        const { discussion } = discussionData;
-        discussion.lastComment = replyToDiscussion.lastComment;
-        discussion.comments.elements.push(replyToDiscussion.lastComment);
-        discussion.comments.total += 1;
+        const { discussion: discussionCached } = discussionData;
+        discussionCached.lastComment = replyToDiscussion.lastComment;
+        discussionCached.comments.elements.push(replyToDiscussion.lastComment);
+        discussionCached.comments.total += 1;
         store.writeQuery({
           query: GET_DISCUSSION,
           variables: { slug: this.slug, page: this.page },
-          data: { discussion },
+          data: { discussion: discussionCached },
         });
       },
-      // We don't need to handle cache update since there's the subscription that handles this for us
+      // We don't need to handle cache update since
+      // there's the subscription that handles this for us
     });
     this.newComment = "";
   }
 
   async updateComment(comment: IComment): Promise<void> {
-    const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({
+    await this.$apollo.mutate<{ deleteComment: IComment }>({
       mutation: UPDATE_COMMENT,
       variables: {
         commentId: comment.id,
@@ -256,25 +257,25 @@ export default class discussion extends mixins(GroupMixin) {
           },
         });
         if (!discussionData) return;
-        const { discussion } = discussionData;
-        const index = discussion.comments.elements.findIndex(
+        const { discussion: discussionCached } = discussionData;
+        const index = discussionCached.comments.elements.findIndex(
           ({ id }) => id === data.deleteComment.id
         );
         if (index > -1) {
-          discussion.comments.elements.splice(index, 1);
-          discussion.comments.total -= 1;
+          discussionCached.comments.elements.splice(index, 1);
+          discussionCached.comments.total -= 1;
         }
         store.writeQuery({
           query: GET_DISCUSSION,
           variables: { slug: this.slug, page: this.page },
-          data: { discussion },
+          data: { discussion: discussionCached },
         });
       },
     });
   }
 
   async deleteComment(comment: IComment): Promise<void> {
-    const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({
+    await this.$apollo.mutate<{ deleteComment: IComment }>({
       mutation: DELETE_COMMENT,
       variables: {
         commentId: comment.id,
@@ -291,21 +292,21 @@ export default class discussion extends mixins(GroupMixin) {
           },
         });
         if (!discussionData) return;
-        const { discussion } = discussionData;
-        const index = discussion.comments.elements.findIndex(
+        const { discussion: discussionCached } = discussionData;
+        const index = discussionCached.comments.elements.findIndex(
           ({ id }) => id === data.deleteComment.id
         );
         if (index > -1) {
-          const updatedComment = discussion.comments.elements[index];
+          const updatedComment = discussionCached.comments.elements[index];
           updatedComment.deletedAt = new Date();
           updatedComment.actor = null;
           updatedComment.text = "";
-          discussion.comments.elements.splice(index, 1, updatedComment);
+          discussionCached.comments.elements.splice(index, 1, updatedComment);
         }
         store.writeQuery({
           query: GET_DISCUSSION,
           variables: { slug: this.slug, page: this.page },
-          data: { discussion },
+          data: { discussion: discussionCached },
         });
       },
     });
@@ -327,13 +328,13 @@ export default class discussion extends mixins(GroupMixin) {
           if (!fetchMoreResult) return previousResult;
           const newComments = fetchMoreResult.discussion.comments.elements;
           this.hasMoreComments = newComments.length === 1;
-          const { discussion } = previousResult;
-          discussion.comments.elements = [
+          const { discussion: discussionCached } = previousResult;
+          discussionCached.comments.elements = [
             ...previousResult.discussion.comments.elements,
             ...newComments,
           ];
 
-          return { discussion };
+          return { discussion: discussionCached };
         },
       });
     } catch (e) {
@@ -359,12 +360,12 @@ export default class discussion extends mixins(GroupMixin) {
           },
         });
         if (!discussionData) return;
-        const { discussion } = discussionData;
-        discussion.title = updateDiscussion.title;
+        const { discussion: discussionCached } = discussionData;
+        discussionCached.title = updateDiscussion.title;
         store.writeQuery({
           query: GET_DISCUSSION,
           variables: { slug: this.slug, page: this.page },
-          data: { discussion },
+          data: { discussion: discussionCached },
         });
       },
     });
diff --git a/js/src/views/Error.vue b/js/src/views/Error.vue
index e1e758843..e68e246e7 100644
--- a/js/src/views/Error.vue
+++ b/js/src/views/Error.vue
@@ -11,8 +11,8 @@
 </template>
 
 <script lang="ts">
+import { ErrorCode } from "@/types/enums";
 import { Component, Vue } from "vue-property-decorator";
-import { ErrorCode } from "@/types/error-code.model";
 
 @Component
 export default class ErrorPage extends Vue {
@@ -20,7 +20,7 @@ export default class ErrorPage extends Vue {
 
   ErrorCode = ErrorCode;
 
-  mounted() {
+  mounted(): void {
     this.code = this.$route.query.code as ErrorCode;
   }
 }
diff --git a/js/src/views/Event/Edit.vue b/js/src/views/Event/Edit.vue
index e14f7dcf5..bd87b7fff 100644
--- a/js/src/views/Event/Edit.vue
+++ b/js/src/views/Event/Edit.vue
@@ -353,8 +353,13 @@ import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue";
 import Subtitle from "@/components/Utils/Subtitle.vue";
 import { Route } from "vue-router";
 import { formatList } from "@/utils/i18n";
-import { CommentModeration } from "../../types/event-options.model";
-import { ParticipantRole } from "../../types/participant.model";
+import {
+  CommentModeration,
+  EventJoinOptions,
+  EventStatus,
+  EventVisibility,
+  ParticipantRole,
+} from "@/types/enums";
 import OrganizerPickerWrapper from "../../components/Event/OrganizerPickerWrapper.vue";
 import {
   CREATE_EVENT,
@@ -362,13 +367,7 @@ import {
   EVENT_PERSON_PARTICIPATION,
   FETCH_EVENT,
 } from "../../graphql/event";
-import {
-  EventJoinOptions,
-  EventModel,
-  EventStatus,
-  EventVisibility,
-  IEvent,
-} from "../../types/event.model";
+import { EventModel, IEvent } from "../../types/event.model";
 import {
   CURRENT_ACTOR_CLIENT,
   LOGGED_USER_DRAFTS,
@@ -837,9 +836,9 @@ export default class EditEvent extends Vue {
   /**
    * Confirm cancel
    */
-  confirmGoElsewhere(callback: (value?: string) => any): void | Function {
+  confirmGoElsewhere(callback: (value?: string) => any): void {
     if (!this.isEventModified) {
-      return callback();
+      callback();
     }
     const title: string = this.isUpdate
       ? (this.$t("Cancel edition") as string)
@@ -872,7 +871,8 @@ export default class EditEvent extends Vue {
     this.confirmGoElsewhere(() => this.$router.go(-1));
   }
 
-  beforeRouteLeave(to: Route, from: Route, next: Function): void {
+  // eslint-disable-next-line consistent-return
+  beforeRouteLeave(to: Route, from: Route, next: () => void): void {
     if (to.name === RouteName.EVENT) return next();
     this.confirmGoElsewhere(() => next());
   }
diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue
index 8e7f63592..21adf746b 100644
--- a/js/src/views/Event/Event.vue
+++ b/js/src/views/Event/Event.vue
@@ -504,6 +504,7 @@
 <script lang="ts">
 import { Component, Prop, Watch } from "vue-property-decorator";
 import BIcon from "buefy/src/components/icon/Icon.vue";
+import { EventJoinOptions, EventStatus, EventVisibility, ParticipantRole } from "@/types/enums";
 import {
   EVENT_PERSON_PARTICIPATION,
   EVENT_PERSON_PARTICIPATION_SUBSCRIPTION_CHANGED,
@@ -511,13 +512,7 @@ import {
   JOIN_EVENT,
 } from "../../graphql/event";
 import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
-import {
-  EventModel,
-  EventStatus,
-  EventVisibility,
-  IEvent,
-  EventJoinOptions,
-} from "../../types/event.model";
+import { EventModel, IEvent } from "../../types/event.model";
 import { IActor, IPerson, Person, usernameWithDomain } from "../../types/actor";
 import { GRAPHQL_API_ENDPOINT } from "../../api/_entrypoint";
 import DateCalendarIcon from "../../components/Event/DateCalendarIcon.vue";
@@ -546,7 +541,7 @@ import Tag from "../../components/Tag.vue";
 import EventMetadataBlock from "../../components/Event/EventMetadataBlock.vue";
 import ActorCard from "../../components/Account/ActorCard.vue";
 import PopoverActorCard from "../../components/Account/PopoverActorCard.vue";
-import { IParticipant, ParticipantRole } from "../../types/participant.model";
+import { IParticipant } from "../../types/participant.model";
 
 @Component({
   components: {
diff --git a/js/src/views/Event/GroupEvents.vue b/js/src/views/Event/GroupEvents.vue
index a839b6252..07b1b6e73 100644
--- a/js/src/views/Event/GroupEvents.vue
+++ b/js/src/views/Event/GroupEvents.vue
@@ -74,7 +74,8 @@ import Subtitle from "@/components/Utils/Subtitle.vue";
 import EventListViewCard from "@/components/Event/EventListViewCard.vue";
 import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor";
 import GroupMixin from "@/mixins/group";
-import { IGroup, IMember, IPerson, usernameWithDomain } from "../../types/actor";
+import { IMember } from "@/types/actor/member.model";
+import { IGroup, IPerson, usernameWithDomain } from "../../types/actor";
 
 @Component({
   apollo: {
diff --git a/js/src/views/Event/MyEvents.vue b/js/src/views/Event/MyEvents.vue
index 99caf50bb..2640e5de1 100644
--- a/js/src/views/Event/MyEvents.vue
+++ b/js/src/views/Event/MyEvents.vue
@@ -88,7 +88,8 @@
 
 <script lang="ts">
 import { Component, Vue } from "vue-property-decorator";
-import { IParticipant, Participant, ParticipantRole } from "../../types/participant.model";
+import { ParticipantRole } from "@/types/enums";
+import { IParticipant, Participant } from "../../types/participant.model";
 import { LOGGED_USER_PARTICIPATIONS, LOGGED_USER_DRAFTS } from "../../graphql/actor";
 import { EventModel, IEvent } from "../../types/event.model";
 import EventListCard from "../../components/Event/EventListCard.vue";
diff --git a/js/src/views/Event/Participants.vue b/js/src/views/Event/Participants.vue
index 2bd7dcddf..7f604538d 100644
--- a/js/src/views/Event/Participants.vue
+++ b/js/src/views/Event/Participants.vue
@@ -185,7 +185,8 @@
 
 <script lang="ts">
 import { Component, Prop, Vue, Watch, Ref } from "vue-property-decorator";
-import { IParticipant, ParticipantRole } from "../../types/participant.model";
+import { ParticipantRole } from "@/types/enums";
+import { IParticipant } from "../../types/participant.model";
 import { IEvent, IEventParticipantStats } from "../../types/event.model";
 import { PARTICIPANTS, UPDATE_PARTICIPANT } from "../../graphql/event";
 import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
diff --git a/js/src/views/Group/Create.vue b/js/src/views/Group/Create.vue
index 4acdacdac..1401ee85e 100644
--- a/js/src/views/Group/Create.vue
+++ b/js/src/views/Group/Create.vue
@@ -67,14 +67,15 @@
 
 <script lang="ts">
 import { Component, Watch } from "vue-property-decorator";
-import { Group, IPerson, usernameWithDomain, MemberRole } from "@/types/actor";
+import { Group, IPerson, usernameWithDomain } from "@/types/actor";
 import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor";
 import { CREATE_GROUP } from "@/graphql/group";
-import PictureUpload from "@/components/PictureUpload.vue";
 import { mixins } from "vue-class-component";
 import IdentityEditionMixin from "@/mixins/identityEdition";
+import { MemberRole } from "@/types/enums";
 import RouteName from "../../router/name";
 import { convertToUsername } from "../../utils/username";
+import PictureUpload from "../../components/PictureUpload.vue";
 
 @Component({
   components: {
diff --git a/js/src/views/Group/Group.vue b/js/src/views/Group/Group.vue
index ddf687f55..858ef5827 100644
--- a/js/src/views/Group/Group.vue
+++ b/js/src/views/Group/Group.vue
@@ -362,7 +362,7 @@
 <script lang="ts">
 import { Component, Prop, Watch } from "vue-property-decorator";
 import EventCard from "@/components/Event/EventCard.vue";
-import { IActor, usernameWithDomain, MemberRole, IMember, Openness } from "@/types/actor";
+import { IActor, usernameWithDomain } from "@/types/actor";
 import Subtitle from "@/components/Utils/Subtitle.vue";
 import CompactTodo from "@/components/Todo/CompactTodo.vue";
 import EventMinimalistCard from "@/components/Event/EventMinimalistCard.vue";
@@ -380,6 +380,8 @@ import { IConfig } from "@/types/config.model";
 import GroupMixin from "@/mixins/group";
 import { mixins } from "vue-class-component";
 import { JOIN_GROUP } from "@/graphql/member";
+import { MemberRole, Openness } from "@/types/enums";
+import { IMember } from "@/types/actor/member.model";
 import RouteName from "../../router/name";
 import GroupSection from "../../components/Group/GroupSection.vue";
 import ReportModal from "../../components/Report/ReportModal.vue";
diff --git a/js/src/views/Group/GroupMembers.vue b/js/src/views/Group/GroupMembers.vue
index 72e6e19ac..ec1974313 100644
--- a/js/src/views/Group/GroupMembers.vue
+++ b/js/src/views/Group/GroupMembers.vue
@@ -184,10 +184,11 @@ import { Component, Watch } from "vue-property-decorator";
 import GroupMixin from "@/mixins/group";
 import { mixins } from "vue-class-component";
 import { FETCH_GROUP } from "@/graphql/group";
+import { MemberRole } from "@/types/enums";
+import { IMember } from "@/types/actor/member.model";
 import RouteName from "../../router/name";
 import { INVITE_MEMBER, GROUP_MEMBERS, REMOVE_MEMBER, UPDATE_MEMBER } from "../../graphql/member";
 import { usernameWithDomain } from "../../types/actor";
-import { IMember, MemberRole } from "../../types/actor/group.model";
 
 @Component({
   apollo: {
diff --git a/js/src/views/Group/GroupSettings.vue b/js/src/views/Group/GroupSettings.vue
index 2e82c0e43..837001bcf 100644
--- a/js/src/views/Group/GroupSettings.vue
+++ b/js/src/views/Group/GroupSettings.vue
@@ -152,9 +152,10 @@ import { Route } from "vue-router";
 import PictureUpload from "@/components/PictureUpload.vue";
 import { mixins } from "vue-class-component";
 import GroupMixin from "@/mixins/group";
+import { Openness } from "@/types/enums";
 import RouteName from "../../router/name";
 import { UPDATE_GROUP, DELETE_GROUP } from "../../graphql/group";
-import { IGroup, usernameWithDomain, Openness } from "../../types/actor";
+import { IGroup, usernameWithDomain } from "../../types/actor";
 import { Address, IAddress } from "../../types/address.model";
 
 @Component({
diff --git a/js/src/views/Group/MyGroups.vue b/js/src/views/Group/MyGroups.vue
index e8051adaf..1cdf67b97 100644
--- a/js/src/views/Group/MyGroups.vue
+++ b/js/src/views/Group/MyGroups.vue
@@ -51,8 +51,10 @@ import { LEAVE_GROUP } from "@/graphql/group";
 import GroupMemberCard from "@/components/Group/GroupMemberCard.vue";
 import Invitations from "@/components/Group/Invitations.vue";
 import { Paginate } from "@/types/paginate";
-import { IGroup, IMember, MemberRole, usernameWithDomain } from "@/types/actor";
+import { IGroup, usernameWithDomain } from "@/types/actor";
 import { Route } from "vue-router";
+import { IMember } from "@/types/actor/member.model";
+import { MemberRole } from "@/types/enums";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/views/Home.vue b/js/src/views/Home.vue
index dd1a84e23..d27d09587 100644
--- a/js/src/views/Home.vue
+++ b/js/src/views/Home.vue
@@ -126,8 +126,7 @@
           </span>
           <div>
             <EventListCard
-              v-for="participation in row[1]"
-              v-if="isInLessThanSevenDays(row[0])"
+              v-for="participation in thisWeek(row)"
               @event-deleted="eventDeleted"
               :key="participation[1].id"
               :participation="participation[1]"
@@ -173,7 +172,8 @@
 
 <script lang="ts">
 import { Component, Vue, Watch } from "vue-property-decorator";
-import { IParticipant, Participant, ParticipantRole } from "../types/participant.model";
+import { ParticipantRole } from "@/types/enums";
+import { IParticipant, Participant } from "../types/participant.model";
 import { FETCH_EVENTS } from "../graphql/event";
 import EventListCard from "../components/Event/EventListCard.vue";
 import EventCard from "../components/Event/EventCard.vue";
@@ -286,6 +286,13 @@ export default class Home extends Vue {
     return window.localStorage.getItem("new-registered-user") === "yes";
   }
 
+  thisWeek(row: [string, Map<string, IParticipant>]): Map<string, IParticipant> {
+    if (this.isInLessThanSevenDays(row[0])) {
+      return row[1];
+    }
+    return new Map();
+  }
+
   // eslint-disable-next-line class-methods-use-this
   mounted(): void {
     if (window.localStorage.getItem("welcome-back")) {
diff --git a/js/src/views/Location.vue b/js/src/views/Location.vue
deleted file mode 100644
index 608d5eb89..000000000
--- a/js/src/views/Location.vue
+++ /dev/null
@@ -1,32 +0,0 @@
-<template>
-  <div>{{ center.lat }} - {{ center.lng }}</div>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from "vue-property-decorator";
-
-@Component
-export default class Location extends Vue {
-  @Prop(String) address!: string;
-
-  description = "Paris, France";
-
-  center = { lat: 48.85, lng: 2.35 };
-
-  markers: any[] = [];
-
-  setPlace(place: any) {
-    this.center = {
-      lat: place.geometry.location.lat(),
-      lng: place.geometry.location.lng(),
-    };
-    this.markers = [
-      {
-        position: { lat: this.center.lat, lng: this.center.lng },
-      },
-    ];
-
-    this.$emit("input", place.formatted_address);
-  }
-}
-</script>
diff --git a/js/src/views/Moderation/Logs.vue b/js/src/views/Moderation/Logs.vue
index c5369f9ec..b0cc89c6f 100644
--- a/js/src/views/Moderation/Logs.vue
+++ b/js/src/views/Moderation/Logs.vue
@@ -158,9 +158,10 @@
 </template>
 <script lang="ts">
 import { Component, Vue } from "vue-property-decorator";
-import { IActionLog, ActionLogAction } from "@/types/report.model";
+import { IActionLog } from "@/types/report.model";
 import { LOGS } from "@/graphql/report";
 import ReportCard from "@/components/Report/ReportCard.vue";
+import { ActionLogAction } from "@/types/enums";
 import RouteName from "../../router/name";
 import { displayNameAndUsername } from "../../types/actor";
 
diff --git a/js/src/views/Moderation/Report.vue b/js/src/views/Moderation/Report.vue
index c2dacf34e..2534bb6a7 100644
--- a/js/src/views/Moderation/Report.vue
+++ b/js/src/views/Moderation/Report.vue
@@ -241,14 +241,15 @@
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
 import { CREATE_REPORT_NOTE, REPORT, UPDATE_REPORT } from "@/graphql/report";
-import { IReport, IReportNote, ReportStatusEnum } from "@/types/report.model";
+import { IReport, IReportNote } from "@/types/report.model";
 import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
-import { IPerson, ActorType, displayNameAndUsername } from "@/types/actor";
+import { IPerson, displayNameAndUsername } from "@/types/actor";
 import { DELETE_EVENT } from "@/graphql/event";
 import { uniq } from "lodash";
 import { nl2br } from "@/utils/html";
 import { DELETE_COMMENT } from "@/graphql/comment";
 import { IComment } from "@/types/comment.model";
+import { ActorType, ReportStatusEnum } from "@/types/enums";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/views/Moderation/ReportList.vue b/js/src/views/Moderation/ReportList.vue
index c8ea560a5..4a134d518 100644
--- a/js/src/views/Moderation/ReportList.vue
+++ b/js/src/views/Moderation/ReportList.vue
@@ -45,9 +45,10 @@
 </template>
 <script lang="ts">
 import { Component, Vue, Watch } from "vue-property-decorator";
-import { IReport, ReportStatusEnum } from "@/types/report.model";
+import { IReport } from "@/types/report.model";
 import { REPORTS } from "@/graphql/report";
 import ReportCard from "@/components/Report/ReportCard.vue";
+import { ReportStatusEnum } from "@/types/enums";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/views/PageNotFound.vue b/js/src/views/PageNotFound.vue
index dcbde73e6..d2cb39aea 100644
--- a/js/src/views/PageNotFound.vue
+++ b/js/src/views/PageNotFound.vue
@@ -46,8 +46,8 @@ export default class PageNotFound extends Vue {
     return this.$t("Search events, groups, etc.") as string;
   }
 
-  enter() {
-    this.$router.push({
+  async enter(): Promise<void> {
+    await this.$router.push({
       name: RouteName.SEARCH,
       query: { term: this.searchText },
     });
diff --git a/js/src/views/Posts/Edit.vue b/js/src/views/Posts/Edit.vue
index 9af397afc..fe30780ba 100644
--- a/js/src/views/Posts/Edit.vue
+++ b/js/src/views/Posts/Edit.vue
@@ -105,11 +105,12 @@ import { mixins } from "vue-class-component";
 import { FETCH_GROUP } from "@/graphql/group";
 import { buildFileFromIMedia, readFileAsync } from "@/utils/image";
 import GroupMixin from "@/mixins/group";
+import { PostVisibility } from "@/types/enums";
 import { TAGS } from "../../graphql/tags";
 import { CONFIG } from "../../graphql/config";
 import { FETCH_POST, CREATE_POST, UPDATE_POST, DELETE_POST } from "../../graphql/post";
 
-import { IPost, PostVisibility } from "../../types/post.model";
+import { IPost } from "../../types/post.model";
 import Editor from "../../components/Editor.vue";
 import { IActor, IGroup, usernameWithDomain } from "../../types/actor";
 import TagInput from "../../components/Event/TagInput.vue";
diff --git a/js/src/views/Posts/List.vue b/js/src/views/Posts/List.vue
index f8c89bd4f..5ddb22c22 100644
--- a/js/src/views/Posts/List.vue
+++ b/js/src/views/Posts/List.vue
@@ -82,10 +82,11 @@ import { Component, Prop } from "vue-property-decorator";
 import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor";
 import { mixins } from "vue-class-component";
 import GroupMixin from "@/mixins/group";
+import { IMember } from "@/types/actor/member.model";
 import { FETCH_GROUP_POSTS } from "../../graphql/post";
 import { Paginate } from "../../types/paginate";
 import { IPost } from "../../types/post.model";
-import { IGroup, IMember, IPerson, usernameWithDomain } from "../../types/actor";
+import { IGroup, IPerson, usernameWithDomain } from "../../types/actor";
 import RouteName from "../../router/name";
 import PostElementItem from "../../components/Post/PostElementItem.vue";
 
diff --git a/js/src/views/Posts/Post.vue b/js/src/views/Posts/Post.vue
index 197f2b375..77d9f6b05 100644
--- a/js/src/views/Posts/Post.vue
+++ b/js/src/views/Posts/Post.vue
@@ -47,13 +47,14 @@
 <script lang="ts">
 import { Component, Prop } from "vue-property-decorator";
 import { mixins } from "vue-class-component";
-import Editor from "@/components/Editor.vue";
 import GroupMixin from "@/mixins/group";
+import { PostVisibility } from "@/types/enums";
+import { IMember } from "@/types/actor/member.model";
 import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "../../graphql/actor";
 import { FETCH_POST } from "../../graphql/post";
 
-import { IPost, PostVisibility } from "../../types/post.model";
-import { IMember, IPerson, usernameWithDomain } from "../../types/actor";
+import { IPost } from "../../types/post.model";
+import { IPerson, usernameWithDomain } from "../../types/actor";
 import RouteName from "../../router/name";
 import Tag from "../../components/Tag.vue";
 
diff --git a/js/src/views/Resources/ResourceFolder.vue b/js/src/views/Resources/ResourceFolder.vue
index 3c3b3972d..7e7188cec 100644
--- a/js/src/views/Resources/ResourceFolder.vue
+++ b/js/src/views/Resources/ResourceFolder.vue
@@ -21,9 +21,8 @@
           >
         </li>
         <li
-          v-if="resource.path !== '/'"
           :class="{ 'is-active': index + 1 === ResourceMixin.resourcePathArray(resource).length }"
-          v-for="(pathFragment, index) in ResourceMixin.resourcePathArray(resource)"
+          v-for="(pathFragment, index) in filteredPath"
           :key="pathFragment"
         >
           <router-link
@@ -145,8 +144,8 @@
           <resource-selector
             :initialResource="updatedResource"
             :username="usernameWithDomain(resource.actor)"
-            @updateResource="moveResource"
-            @closeMoveModal="moveModal = false"
+            @update-resource="moveResource"
+            @close-move-modal="moveModal = false"
           />
         </section>
       </div>
@@ -303,6 +302,13 @@ export default class Resources extends Mixins(ResourceMixin) {
     return path[0] !== "/" ? `/${path}` : path;
   }
 
+  get filteredPath(): string[] {
+    if (this.resource && this.resource.path !== "/") {
+      return ResourceMixin.resourcePathArray(this.resource);
+    }
+    return [];
+  }
+
   async createResource(): Promise<void> {
     if (!this.resource.actor) return;
     try {
diff --git a/js/src/views/Search.vue b/js/src/views/Search.vue
index b175ff0d2..54ec306af 100644
--- a/js/src/views/Search.vue
+++ b/js/src/views/Search.vue
@@ -152,6 +152,7 @@ import {
   startOfMonth,
   eachWeekendOfInterval,
 } from "date-fns";
+import { SearchTabs } from "@/types/enums";
 import EventCard from "../components/Event/EventCard.vue";
 import { FETCH_EVENTS } from "../graphql/event";
 import { IEvent } from "../types/event.model";
@@ -160,7 +161,6 @@ import { IAddress, Address } from "../types/address.model";
 import AddressAutoComplete from "../components/Event/AddressAutoComplete.vue";
 import { SEARCH_EVENTS, SEARCH_GROUPS } from "../graphql/search";
 import { Paginate } from "../types/paginate";
-import { SearchTabs } from "../types/search.model";
 import { IGroup } from "../types/actor";
 import GroupCard from "../components/Group/GroupCard.vue";
 import { CONFIG } from "../graphql/config";
diff --git a/js/src/views/Settings.vue b/js/src/views/Settings.vue
index 50222d26b..6d51de272 100644
--- a/js/src/views/Settings.vue
+++ b/js/src/views/Settings.vue
@@ -10,14 +10,13 @@
   </div>
 </template>
 <script lang="ts">
-import { Component, Vue, Watch } from "vue-property-decorator";
-import { Route } from "vue-router";
+import { Component, Vue } from "vue-property-decorator";
 import SettingsMenu from "../components/Settings/SettingsMenu.vue";
 import RouteName from "../router/name";
 import { IPerson, Person } from "../types/actor";
 import { IDENTITIES } from "../graphql/actor";
 import { CURRENT_USER_CLIENT } from "../graphql/user";
-import { ICurrentUser, ICurrentUserRole } from "../types/current-user.model";
+import { ICurrentUser } from "../types/current-user.model";
 
 @Component({
   components: { SettingsMenu },
diff --git a/js/src/views/Settings/AccountSettings.vue b/js/src/views/Settings/AccountSettings.vue
index d9e195013..1402e4f97 100644
--- a/js/src/views/Settings/AccountSettings.vue
+++ b/js/src/views/Settings/AccountSettings.vue
@@ -176,11 +176,12 @@
 </template>
 
 <script lang="ts">
+import { IAuthProvider } from "@/types/enums";
 import { Component, Vue, Ref } from "vue-property-decorator";
 import { Route } from "vue-router";
 import { CHANGE_EMAIL, CHANGE_PASSWORD, DELETE_ACCOUNT, LOGGED_USER } from "../../graphql/user";
 import RouteName from "../../router/name";
-import { IUser, IAuthProvider } from "../../types/current-user.model";
+import { IUser } from "../../types/current-user.model";
 import { logout, SELECTED_PROVIDERS } from "../../utils/auth";
 
 @Component({
@@ -299,7 +300,7 @@ export default class AccountSettings extends Vue {
   get hasUserGotAPassword(): boolean {
     return (
       this.loggedUser &&
-      (this.loggedUser.provider == null || this.loggedUser.provider == IAuthProvider.LDAP)
+      (this.loggedUser.provider == null || this.loggedUser.provider === IAuthProvider.LDAP)
     );
   }
 
diff --git a/js/src/views/Settings/Notifications.vue b/js/src/views/Settings/Notifications.vue
index 718569056..82e76d9bd 100644
--- a/js/src/views/Settings/Notifications.vue
+++ b/js/src/views/Settings/Notifications.vue
@@ -102,8 +102,9 @@
 </template>
 <script lang="ts">
 import { Component, Vue, Watch } from "vue-property-decorator";
+import { INotificationPendingEnum } from "@/types/enums";
 import { USER_SETTINGS, SET_USER_SETTINGS } from "../../graphql/user";
-import { IUser, INotificationPendingEnum } from "../../types/current-user.model";
+import { IUser } from "../../types/current-user.model";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/views/Todos/TodoList.vue b/js/src/views/Todos/TodoList.vue
index c32938198..c8bdc1228 100644
--- a/js/src/views/Todos/TodoList.vue
+++ b/js/src/views/Todos/TodoList.vue
@@ -42,11 +42,12 @@
 </template>
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { ITodo, ITodoList } from "@/types/todos";
+import { ITodo } from "@/types/todos";
 import { CREATE_TODO, FETCH_TODO_LIST } from "@/graphql/todos";
 import CompactTodo from "@/components/Todo/CompactTodo.vue";
 import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
 import { IActor } from "@/types/actor";
+import { ITodoList } from "@/types/todolist";
 import RouteName from "../../router/name";
 
 @Component({
@@ -77,7 +78,7 @@ export default class TodoList extends Vue {
 
   RouteName = RouteName;
 
-  async createNewTodo() {
+  async createNewTodo(): Promise<void> {
     await this.$apollo.mutate({
       mutation: CREATE_TODO,
       variables: {
diff --git a/js/src/views/Todos/TodoLists.vue b/js/src/views/Todos/TodoLists.vue
index 537bffdee..8886b455b 100644
--- a/js/src/views/Todos/TodoLists.vue
+++ b/js/src/views/Todos/TodoLists.vue
@@ -54,9 +54,9 @@
 import { Component, Prop, Vue } from "vue-property-decorator";
 import { FETCH_GROUP } from "@/graphql/group";
 import { IGroup, usernameWithDomain } from "@/types/actor";
-import { ITodoList } from "@/types/todos";
 import { CREATE_TODO_LIST } from "@/graphql/todos";
 import CompactTodo from "@/components/Todo/CompactTodo.vue";
+import { ITodoList } from "@/types/todolist";
 import RouteName from "../../router/name";
 
 @Component({
diff --git a/js/src/views/User/Login.vue b/js/src/views/User/Login.vue
index ce4370831..0531acacd 100644
--- a/js/src/views/User/Login.vue
+++ b/js/src/views/User/Login.vue
@@ -98,14 +98,14 @@
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
 import { Route } from "vue-router";
+import { ICurrentUser } from "@/types/current-user.model";
+import { LoginError, LoginErrorCode } from "@/types/enums";
 import { LOGIN } from "../../graphql/auth";
 import { validateEmailField, validateRequiredField } from "../../utils/validators";
 import { initializeCurrentActor, NoIdentitiesException, saveUserData } from "../../utils/auth";
 import { ILogin } from "../../types/login.model";
 import { CURRENT_USER_CLIENT, UPDATE_CURRENT_USER_CLIENT } from "../../graphql/user";
 import RouteName from "../../router/name";
-import { LoginErrorCode, LoginError } from "../../types/login-error-code.model";
-import { ICurrentUser } from "../../types/current-user.model";
 import { CONFIG } from "../../graphql/config";
 import { IConfig } from "../../types/config.model";
 import AuthProviders from "../../components/User/AuthProviders.vue";
diff --git a/js/src/views/User/PasswordReset.vue b/js/src/views/User/PasswordReset.vue
index b9a407c87..e36cfe9a6 100644
--- a/js/src/views/User/PasswordReset.vue
+++ b/js/src/views/User/PasswordReset.vue
@@ -52,21 +52,21 @@ export default class PasswordReset extends Vue {
   errors: string[] = [];
 
   rules = {
-    passwordLength: (value: string) =>
+    passwordLength: (value: string): boolean | string =>
       value.length > 6 || "Password must be at least 6 characters long",
     required: validateRequiredField,
-    passwordEqual: (value: string) =>
+    passwordEqual: (value: string): boolean | string =>
       value === this.credentials.password || "Passwords must be the same",
   };
 
-  get samePasswords() {
+  get samePasswords(): boolean {
     return (
       this.rules.passwordLength(this.credentials.password) === true &&
       this.credentials.password === this.credentials.passwordConfirmation
     );
   }
 
-  async resetAction(e: Event) {
+  async resetAction(e: Event): Promise<void> {
     e.preventDefault();
     this.errors.splice(0);
 
diff --git a/js/src/views/User/ProviderValidation.vue b/js/src/views/User/ProviderValidation.vue
index f62dd62c4..83cbf605a 100644
--- a/js/src/views/User/ProviderValidation.vue
+++ b/js/src/views/User/ProviderValidation.vue
@@ -1,59 +1,58 @@
-<template></template>
 <script lang="ts">
-import { Component, Prop, Vue } from "vue-property-decorator";
-import { VALIDATE_USER, UPDATE_CURRENT_USER_CLIENT, LOGGED_USER } from "../../graphql/user";
+import { Component, Vue } from "vue-property-decorator";
+import { ICurrentUserRole } from "@/types/enums";
+import { UPDATE_CURRENT_USER_CLIENT, LOGGED_USER } from "../../graphql/user";
 import RouteName from "../../router/name";
 import { saveUserData, changeIdentity } from "../../utils/auth";
-import { ILogin } from "../../types/login.model";
-import { ICurrentUserRole, ICurrentUser, IUser } from "../../types/current-user.model";
-import { IDENTITIES } from "../../graphql/actor";
+import { IUser } from "../../types/current-user.model";
 
 @Component
 export default class ProviderValidate extends Vue {
-  async mounted() {
+  async mounted(): Promise<void> {
     const accessToken = this.getValueFromMeta("auth-access-token");
     const refreshToken = this.getValueFromMeta("auth-refresh-token");
     const userId = this.getValueFromMeta("auth-user-id");
     const userEmail = this.getValueFromMeta("auth-user-email");
     const userRole = this.getValueFromMeta("auth-user-role") as ICurrentUserRole;
-    const userActorId = this.getValueFromMeta("auth-user-actor-id");
 
     if (!(userId && userEmail && userRole && accessToken && refreshToken)) {
-      return this.$router.push("/");
-    }
-    const login = {
-      user: { id: userId, email: userEmail, role: userRole, isLoggedIn: true },
-      accessToken,
-      refreshToken,
-    };
-    saveUserData(login);
-    await this.$apollo.mutate({
-      mutation: UPDATE_CURRENT_USER_CLIENT,
-      variables: {
-        id: userId,
-        email: userEmail,
-        isLoggedIn: true,
-        role: ICurrentUserRole.USER,
-      },
-    });
-    const { data } = await this.$apollo.query<{ loggedUser: IUser }>({
-      query: LOGGED_USER,
-    });
-    const { loggedUser } = data;
-
-    if (loggedUser.defaultActor) {
-      await changeIdentity(this.$apollo.provider.defaultClient, loggedUser.defaultActor);
-      await this.$router.push({ name: RouteName.HOME });
+      await this.$router.push("/");
     } else {
-      // If the user didn't register any profile yet, let's create one for them
-      await this.$router.push({
-        name: RouteName.REGISTER_PROFILE,
-        params: { email: loggedUser.email, userAlreadyActivated: "true" },
+      const login = {
+        user: { id: userId, email: userEmail, role: userRole, isLoggedIn: true },
+        accessToken,
+        refreshToken,
+      };
+      saveUserData(login);
+      await this.$apollo.mutate({
+        mutation: UPDATE_CURRENT_USER_CLIENT,
+        variables: {
+          id: userId,
+          email: userEmail,
+          isLoggedIn: true,
+          role: ICurrentUserRole.USER,
+        },
       });
+      const { data } = await this.$apollo.query<{ loggedUser: IUser }>({
+        query: LOGGED_USER,
+      });
+      const { loggedUser } = data;
+
+      if (loggedUser.defaultActor) {
+        await changeIdentity(this.$apollo.provider.defaultClient, loggedUser.defaultActor);
+        await this.$router.push({ name: RouteName.HOME });
+      } else {
+        // If the user didn't register any profile yet, let's create one for them
+        await this.$router.push({
+          name: RouteName.REGISTER_PROFILE,
+          params: { email: loggedUser.email, userAlreadyActivated: "true" },
+        });
+      }
     }
   }
 
-  getValueFromMeta(name: string) {
+  // eslint-disable-next-line class-methods-use-this
+  getValueFromMeta(name: string): string | null {
     const element = document.querySelector(`meta[name="${name}"]`);
     if (element && element.getAttribute("content")) {
       return element.getAttribute("content");
diff --git a/js/src/views/User/Register.vue b/js/src/views/User/Register.vue
index 63da0155d..9b112b692 100644
--- a/js/src/views/User/Register.vue
+++ b/js/src/views/User/Register.vue
@@ -143,7 +143,6 @@
 
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
-import { Route } from "vue-router";
 import { CREATE_USER } from "../../graphql/user";
 import RouteName from "../../router/name";
 import { IConfig } from "../../types/config.model";
diff --git a/js/src/views/User/ResendConfirmation.vue b/js/src/views/User/ResendConfirmation.vue
index 24b5dd54b..292f72331 100644
--- a/js/src/views/User/ResendConfirmation.vue
+++ b/js/src/views/User/ResendConfirmation.vue
@@ -68,11 +68,11 @@ export default class ResendConfirmation extends Vue {
     email: validateEmailField,
   };
 
-  mounted() {
+  mounted(): void {
     this.credentials.email = this.email;
   }
 
-  async resendConfirmationAction(e: Event) {
+  async resendConfirmationAction(e: Event): Promise<void> {
     e.preventDefault();
     this.error = false;
 
diff --git a/js/src/views/User/Validate.vue b/js/src/views/User/Validate.vue
index f6df0fe0f..0eb980fd1 100644
--- a/js/src/views/User/Validate.vue
+++ b/js/src/views/User/Validate.vue
@@ -16,11 +16,11 @@
 
 <script lang="ts">
 import { Component, Prop, Vue } from "vue-property-decorator";
+import { ICurrentUserRole } from "@/types/enums";
 import { VALIDATE_USER, UPDATE_CURRENT_USER_CLIENT } from "../../graphql/user";
 import RouteName from "../../router/name";
 import { saveUserData, saveTokenData, changeIdentity } from "../../utils/auth";
 import { ILogin } from "../../types/login.model";
-import { ICurrentUserRole } from "../../types/current-user.model";
 
 @Component
 export default class Validate extends Vue {
@@ -30,11 +30,11 @@ export default class Validate extends Vue {
 
   failed = false;
 
-  async created() {
+  async created(): Promise<void> {
     await this.validateAction();
   }
 
-  async validateAction() {
+  async validateAction(): Promise<void> {
     try {
       const { data } = await this.$apollo.mutate<{ validateUser: ILogin }>({
         mutation: VALIDATE_USER,