diff --git a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..70da2822b084251d2eca1459de9a54b18ded695c
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java
@@ -0,0 +1,51 @@
+package fr.inra.oresing.rest;
+
+import lombok.Value;
+
+import java.util.Map;
+import java.util.Set;
+
+@Value
+public class ApplicationResult {
+    String id;
+    String name;
+    String title;
+    Map<String, Reference> references;
+    Map<String, DataType> dataTypes;
+
+    @Value
+    public static class Reference {
+        String id;
+        String label;
+        Set<String> children;
+        Map<String, Column> columns;
+
+        @Value
+        public static class Column {
+            String id;
+            String title;
+            boolean key;
+            String linkedTo;
+        }
+    }
+
+    @Value
+    public static class DataType {
+        String id;
+        String label;
+        Map<String, Variable> variables;
+
+        @Value
+        public static class Variable {
+            String id;
+            String label;
+            Map<String, Component> components;
+
+            @Value
+            public static class Component {
+                String id;
+                String label;
+            }
+        }
+    }
+}
diff --git a/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1488cc30339b532c7c736f93bb06c42731430e9
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java
@@ -0,0 +1,18 @@
+package fr.inra.oresing.rest;
+
+import lombok.Value;
+
+import java.util.Map;
+import java.util.Set;
+
+@Value
+public class GetReferenceResult {
+    Set<ReferenceValue> referenceValues;
+
+    @Value
+    public static class ReferenceValue {
+        String hierarchicalKey;
+        String naturalKey;
+        Map<String, String> values;
+    }
+}
diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java
index 6be34e4b2e23db24a110b1784d92f5ec5e4e708c..b94fbf1098eb2138307e19e30dc7da710b71a645 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java
@@ -1,9 +1,16 @@
 package fr.inra.oresing.rest;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.TreeMultimap;
 import fr.inra.oresing.checker.CheckerException;
 import fr.inra.oresing.model.Application;
 import fr.inra.oresing.model.BinaryFile;
+import fr.inra.oresing.model.Configuration;
 import fr.inra.oresing.model.ReferenceValue;
 import fr.inra.oresing.persistence.OreSiRepository;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -24,6 +31,7 @@ import org.springframework.web.util.UriUtils;
 import java.io.IOException;
 import java.net.URI;
 import java.nio.charset.Charset;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -81,9 +89,39 @@ public class OreSiResources {
     }
 
     @GetMapping(value = "/applications/{nameOrId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<Application> getApplication(@PathVariable("nameOrId") String nameOrId) {
+    public ResponseEntity<ApplicationResult> getApplication(@PathVariable("nameOrId") String nameOrId) {
         Application application = service.getApplication(nameOrId);
-        return ResponseEntity.ok(application);
+        TreeMultimap<String, String> childrenPerReferences = TreeMultimap.create();
+        application.getConfiguration().getCompositeReferences().values().forEach(compositeReferenceDescription -> {
+            ImmutableList<String> referenceTypes = compositeReferenceDescription.getComponents().stream()
+                    .map(Configuration.CompositeReferenceComponentDescription::getReference)
+                    .collect(ImmutableList.toImmutableList());
+            ImmutableSortedSet<String> sortedReferenceTypes = ImmutableSortedSet.copyOf(Ordering.explicit(referenceTypes), referenceTypes);
+            sortedReferenceTypes.forEach(reference -> {
+                String child = sortedReferenceTypes.higher(reference);
+                if (child == null) {
+                    // on est sur le dernier élément de la hiérarchie, pas de descendant
+                } else {
+                    childrenPerReferences.put(reference, child);
+                }
+            });
+        });
+        Map<String, ApplicationResult.Reference> references = Maps.transformEntries(application.getConfiguration().getReferences(), (reference, referenceDescription) -> {
+            Map<String, ApplicationResult.Reference.Column> columns = Maps.transformEntries(referenceDescription.getColumns(), (column, columnDescription) -> new ApplicationResult.Reference.Column(column, column, referenceDescription.getKeyColumns().contains(column), null));
+            Set<String> children = childrenPerReferences.get(reference);
+            return new ApplicationResult.Reference(reference, reference, children, columns);
+        });
+        Map<String, ApplicationResult.DataType> dataTypes = Maps.transformEntries(application.getConfiguration().getDataTypes(), (dataType, dataTypeDescription) -> {
+            Map<String, ApplicationResult.DataType.Variable> variables = Maps.transformEntries(dataTypeDescription.getData(), (variable, variableDescription) -> {
+                Map<String, ApplicationResult.DataType.Variable.Component> components = Maps.transformEntries(variableDescription.getComponents(), (component, componentDescription) -> {
+                    return new ApplicationResult.DataType.Variable.Component(component, component);
+                });
+                return new ApplicationResult.DataType.Variable(variable, variable, components);
+            });
+            return new ApplicationResult.DataType(dataType, dataType, variables);
+        });
+        ApplicationResult applicationResult = new ApplicationResult(application.getId().toString(), application.getName(), application.getConfiguration().getApplication().getName(), references, dataTypes);
+        return ResponseEntity.ok(applicationResult);
     }
 
     @GetMapping(value = "/applications/{nameOrId}/configuration", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@@ -137,12 +175,21 @@ public class OreSiResources {
      * @return un tableau de chaine
      */
     @GetMapping(value = "/applications/{nameOrId}/references/{refType}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<List<ReferenceValue>> listReferences(
+    public ResponseEntity<GetReferenceResult> listReferences(
             @PathVariable("nameOrId") String nameOrId,
             @PathVariable("refType") String refType,
             @RequestParam MultiValueMap<String, String> params) {
         List<ReferenceValue> list = service.findReference(nameOrId, refType, params);
-        return ResponseEntity.ok(list);
+        ImmutableSet<GetReferenceResult.ReferenceValue> referenceValues = list.stream()
+                .map(referenceValue ->
+                        new GetReferenceResult.ReferenceValue(
+                            referenceValue.getHierarchicalKey(),
+                            referenceValue.getNaturalKey(),
+                            referenceValue.getRefValues()
+                        )
+                )
+                .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetReferenceResult.ReferenceValue::getHierarchicalKey)));
+        return ResponseEntity.ok(new GetReferenceResult(referenceValues));
     }
 
     @GetMapping(value = "/applications/{nameOrId}/references/{refType}/{column}", produces = MediaType.APPLICATION_JSON_VALUE)
diff --git a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
index 0d5469b709960446e5ebce4f965a8b83a8f8120a..ed6123d073e4bd9f2e460228f50581cba1701822 100644
--- a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
+++ b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
@@ -5,7 +5,6 @@ import com.google.common.base.Charsets;
 import com.google.common.io.Resources;
 import com.jayway.jsonpath.JsonPath;
 import fr.inra.oresing.OreSiNg;
-import fr.inra.oresing.model.Application;
 import fr.inra.oresing.model.OreSiUser;
 import fr.inra.oresing.persistence.AuthenticationService;
 import lombok.extern.slf4j.Slf4j;
@@ -37,9 +36,8 @@ import javax.servlet.http.Cookie;
 import java.io.InputStream;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
-import java.util.Date;
-import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@@ -118,12 +116,11 @@ public class OreSiResourcesTest {
                 .andExpect(jsonPath("$.id", Is.is(appId)))
                 .andReturn().getResponse().getContentAsString();
 
-        Application app2 = objectMapper.readValue(response, Application.class);
+        ApplicationResult applicationResult = objectMapper.readValue(response, ApplicationResult.class);
 
-        Date now = new Date();
-        Assert.assertEquals("monsore", app2.getName());
-        Assert.assertEquals(List.of("especes", "projet", "sites", "themes", "type de fichiers", "type_de_sites", "types_de_donnees_par_themes_de_sites_et_projet", "unites", "valeurs_qualitatives", "variables", "variables_et_unites_par_types_de_donnees"), app2.getReferenceType());
-        Assert.assertEquals(List.of("pem"), app2.getDataType());
+        Assert.assertEquals("monsore", applicationResult.getName());
+        Assert.assertEquals(Set.of("especes", "projet", "sites", "themes", "type de fichiers", "type_de_sites", "types_de_donnees_par_themes_de_sites_et_projet", "unites", "valeurs_qualitatives", "variables", "variables_et_unites_par_types_de_donnees"), applicationResult.getReferences().keySet());
+//        Assert.assertEquals(List.of("pem"), applicationResult.getDataType());
 
         // Ajout de referentiel
         for (Map.Entry<String, String> e : fixtures.getMonsoreReferentielFiles().entrySet()) {
@@ -148,8 +145,8 @@ public class OreSiResourcesTest {
                 .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
                 .andReturn().getResponse().getContentAsString();
 
-        List refs = objectMapper.readValue(getReferencesResponse, List.class);
-        Assert.assertEquals(9, refs.size());
+        GetReferenceResult GetReferenceResult = objectMapper.readValue(getReferencesResponse, GetReferenceResult.class);
+        Assert.assertEquals(9, GetReferenceResult.getReferenceValues().size());
 
         // ajout de data
         resource = getClass().getResource(fixtures.getPemDataResourceName());
@@ -373,8 +370,8 @@ public class OreSiResourcesTest {
                 .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
                 .andReturn().getResponse().getContentAsString();
 
-        List refs = objectMapper.readValue(getReferenceResponse, List.class);
-        Assert.assertEquals(103, refs.size());
+        GetReferenceResult refs = objectMapper.readValue(getReferenceResponse, GetReferenceResult.class);
+        Assert.assertEquals(103, refs.getReferenceValues().size());
 
         // Ajout de referentiel
         for (Map.Entry<String, String> e : fixtures.getAcbbReferentielFiles().entrySet()) {
@@ -399,8 +396,8 @@ public class OreSiResourcesTest {
                 .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
                 .andReturn().getResponse().getContentAsString();
 
-        refs = objectMapper.readValue(getReferenceResponse, List.class);
-        Assert.assertEquals(103, refs.size());
+        refs = objectMapper.readValue(getReferenceResponse, GetReferenceResult.class);
+        Assert.assertEquals(103, refs.getReferenceValues().size());
 
         // ajout de data
         try (InputStream in = getClass().getResourceAsStream(fixtures.getFluxToursDataResourceName())) {
diff --git a/ui2/src/components/common/CollapsibleTree.vue b/ui2/src/components/common/CollapsibleTree.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d12ccdda55e11176e2286d3b7d0582b152119bd8
--- /dev/null
+++ b/ui2/src/components/common/CollapsibleTree.vue
@@ -0,0 +1,137 @@
+<template>
+  <div>
+    <div
+      :class="`CollapsibleTree-header ${children && children.length !== 0 ? 'clickable' : ''} ${
+        children && children.length !== 0 && displayChildren ? '' : 'mb-1'
+      }`"
+      :style="`background-color:rgba(240, 245, 245, ${1 - level / 2})`"
+      @click="displayChildren = !displayChildren"
+    >
+      <div class="CollapsibleTree-header-infos">
+        <FontAwesomeIcon
+          v-if="children && children.length !== 0"
+          :icon="displayChildren ? 'caret-down' : 'caret-right'"
+          class="clickable mr-3"
+        />
+        <div
+          class="link"
+          :style="`transform:translate(${level * 50}px);`"
+          @click="(event) => onClickLabelCb(event, label)"
+        >
+          {{ label }}
+        </div>
+      </div>
+      <div class="CollapsibleTree-buttons">
+        <b-field class="file button is-small is-info" v-if="onUploadCb">
+          <b-upload
+            v-model="refFile"
+            class="file-label"
+            accept=".csv"
+            @input="() => onUploadCb(label, refFile)"
+          >
+            <span class="file-name" v-if="refFile">
+              {{ refFile.name }}
+            </span>
+            <span class="file-cta">
+              <b-icon class="file-icon" icon="upload"></b-icon>
+            </span>
+          </b-upload>
+        </b-field>
+        <div v-for="button in buttons" :key="button.id">
+          <b-button
+            :icon-left="button.iconName"
+            size="is-small"
+            @click="button.clickCb(label)"
+            class="ml-1"
+            :type="button.type"
+          >
+            {{ button.label }}</b-button
+          >
+        </div>
+      </div>
+    </div>
+    <div v-if="displayChildren">
+      <CollapsibleTree
+        v-for="child in children"
+        :key="child.id"
+        :label="child.label"
+        :children="child.children"
+        :level="level + 1"
+        :onClickLabelCb="onClickLabelCb"
+        :onUploadCb="onUploadCb"
+        :buttons="buttons"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+import { Component, Prop, Vue } from "vue-property-decorator";
+import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
+
+@Component({
+  components: { FontAwesomeIcon },
+})
+export default class CollapsibleTree extends Vue {
+  @Prop() label;
+  @Prop() children;
+  @Prop() level;
+  @Prop() onClickLabelCb;
+  @Prop() onUploadCb;
+  @Prop() buttons;
+
+  displayChildren = false;
+  refFile = null;
+}
+</script>
+
+<style lang="scss" scoped>
+$row-height: 40px;
+
+.CollapsibleTree-header {
+  display: flex;
+  align-items: center;
+  height: $row-height;
+  padding: 0.75rem;
+  justify-content: space-between;
+
+  .file-icon {
+    margin-right: 0;
+  }
+
+  .file-name {
+    border-top-style: none;
+    border-right-style: none;
+    border-bottom-style: none;
+    border-left-width: 2px;
+    border-radius: 0px;
+    opacity: 0.8;
+    background-color: rgba(250, 250, 250, 1);
+
+    &:hover {
+      opacity: 1;
+    }
+  }
+}
+
+.CollapsibleTree-header-infos {
+  display: flex;
+  align-items: center;
+}
+
+.CollapsibleTree-buttons {
+  display: flex;
+  height: $row-height;
+  align-items: center;
+
+  .file {
+    margin-bottom: 0;
+
+    .file-cta {
+      height: 100%;
+      background-color: transparent;
+      border-color: transparent;
+    }
+  }
+}
+</style>
diff --git a/ui2/src/components/common/SidePanel.vue b/ui2/src/components/common/SidePanel.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ff6565ff9d4b10d131ea69f9a38fa1d2cc77a371
--- /dev/null
+++ b/ui2/src/components/common/SidePanel.vue
@@ -0,0 +1,72 @@
+<template>
+  <div :class="`SidePanel ${leftAlign ? 'left-align' : 'right-align'} ${innerOpen ? 'open' : ''}`">
+    <h1 class="title main-title">{{ title }}</h1>
+    <b-button class="SidePanel-close-button" icon-left="times" @click="innerOpen = false" />
+    <slot></slot>
+  </div>
+</template>
+
+<script>
+import { Component, Prop, Vue, Watch } from "vue-property-decorator";
+
+@Component({
+  components: {},
+})
+export default class SidePanel extends Vue {
+  @Prop({ default: false }) leftAlign;
+  @Prop({ default: false }) open;
+  @Prop({ default: "" }) title;
+  @Prop() closeCb;
+
+  innerOpen = false;
+
+  created() {
+    this.innerOpen = this.open;
+  }
+
+  @Watch("open")
+  onExternalOpenStateChanged(newVal) {
+    this.innerOpen = newVal;
+  }
+
+  @Watch("innerOpen")
+  onInnerOpenStateChanged(newVal) {
+    this.closeCb(newVal);
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.SidePanel {
+  background-color: $light;
+  z-index: 1;
+  position: absolute;
+  height: 100%;
+  top: 0;
+  width: 33%;
+  padding: $container-padding-vert 2.5rem;
+  transition: transform 250ms;
+
+  &.right-align {
+    right: 0;
+    transform: translateX(100%);
+    &.open {
+      transform: translateX(0);
+    }
+  }
+
+  &.left-align {
+    left: 0;
+    transform: translateX(-100%);
+    &.open {
+      transform: translateX(0);
+    }
+  }
+}
+
+.SidePanel-close-button {
+  position: absolute;
+  top: 0;
+  right: 0;
+}
+</style>
diff --git a/ui2/src/components/common/SubMenu.vue b/ui2/src/components/common/SubMenu.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2b5d444c67a87f5336f69ba0bc49dee4a3856a1e
--- /dev/null
+++ b/ui2/src/components/common/SubMenu.vue
@@ -0,0 +1,53 @@
+<template>
+  <div class="SubMenu">
+    <span class="SubMenu-root">{{ root }}</span>
+    <div v-for="(path, index) in paths" :key="path.label">
+      <span class="SubMenu-path-separator mr-1 ml-1">/</span>
+      <span
+        @click="index !== paths.length - 1 ? path.clickCb() : ''"
+        :class="index !== paths.length - 1 ? 'link' : ''"
+        >{{ path.label }}</span
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+import { Component, Prop, Vue } from "vue-property-decorator";
+
+export class SubMenuPath {
+  label;
+  clickCb;
+
+  constructor(label, clickCb) {
+    this.label = label;
+    this.clickCb = clickCb;
+  }
+}
+
+@Component({
+  components: {},
+})
+export default class SubMenu extends Vue {
+  @Prop() root;
+  @Prop() paths;
+}
+</script>
+
+<style lang="scss" scoped>
+.SubMenu {
+  display: flex;
+  height: 40px;
+  background-color: $info-transparent;
+  align-items: center;
+  padding: 0.5rem $container-padding-hor;
+  width: calc(100% + 2 * #{$container-padding-hor});
+  transform: translateX(-$container-padding-hor);
+}
+
+.SubMenu-root {
+  color: $dark;
+  font-weight: 600;
+  font-size: 1.2em;
+}
+</style>
diff --git a/ui2/src/components/references/ReferencesDetailsPanel.vue b/ui2/src/components/references/ReferencesDetailsPanel.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1fdae4b09e75aba1dd92e40572d6236a2c501088
--- /dev/null
+++ b/ui2/src/components/references/ReferencesDetailsPanel.vue
@@ -0,0 +1,57 @@
+<template>
+  <SidePanel
+    :open="open"
+    :leftAlign="leftAlign"
+    :title="reference && reference.label"
+    :closeCb="closeCb"
+  >
+    <div class="Panel-buttons">
+      <b-button type="is-danger" icon-left="trash-alt" @click="askDeletionConfirmation">{{
+        $t("referencesManagement.delete")
+      }}</b-button>
+    </div>
+  </SidePanel>
+</template>
+
+<script>
+import { AlertService } from "@/services/AlertService";
+import { Component, Prop, Vue } from "vue-property-decorator";
+import SidePanel from "../common/SidePanel.vue";
+
+@Component({
+  components: { SidePanel },
+})
+export default class ReferencesDetailsPanel extends Vue {
+  @Prop({ default: false }) leftAlign;
+  @Prop({ default: false }) open;
+  @Prop() reference;
+  @Prop() closeCb;
+
+  alertService = AlertService.INSTANCE;
+
+  askDeletionConfirmation() {
+    this.alertService.dialog(
+      this.$t("alert.warning"),
+      this.$t("alert.reference-deletion-msg", { label: this.reference.label }),
+      this.$t("alert.delete"),
+      "is-danger",
+      () => this.deleteReference()
+    );
+  }
+
+  deleteReference() {
+    console.log("DELETE", this.reference);
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.Panel-buttons {
+  display: flex;
+  flex-direction: column;
+
+  .button {
+    margin-bottom: 0.5rem;
+  }
+}
+</style>
diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json
index 825e994c432e373607bf268ef87b6e2009643dc5..7a13a47c233853cb82f25ffe6af65b75f1d432a4 100644
--- a/ui2/src/locales/en.json
+++ b/ui2/src/locales/en.json
@@ -2,16 +2,17 @@
   "titles": {
     "login-page": "Welcome to SI-ORE",
     "applications-page": "My applications",
-    "references-page": "My references",
+    "references-page": "{applicationName} references",
+    "references-data": "{refName} data",
     "application-creation": "Application creation"
   },
   "login": {
     "signin": "Sign in",
     "signup": "Sign up",
     "login": "Login",
-    "login-placeholder": "Write down the login",
+    "login-placeholder": "Ex: michel",
     "pwd": "Password",
-    "pwd-placeholder": "Write down the password",
+    "pwd-placeholder": "Ex: xxxx",
     "pwd-forgotten": "Forgotten password ? "
   },
   "validation": {
@@ -26,7 +27,12 @@
     "server-error": "A server error occured",
     "user-unknown": "Unknown user",
     "application-creation-success": "The app has been created!",
-    "application-validate-success": "The YAML file is valid!"
+    "application-validate-success": "The YAML file is valid!",
+    "warning": "Warning !",
+    "reference-deletion-msg": "You're about to delete the reference : {label}. Are you sure ?",
+    "delete": "Delete",
+    "reference-csv-upload-error": "An error occured while uploading the csv file",
+    "reference-updated": "Reference updated"
   },
   "message": {
     "app-config-error": "Error in yaml file",
@@ -45,7 +51,10 @@
     "create": "Create application",
     "test": "Test",
     "name": "Application name",
-    "name-placeholder": "Write down the application name"
+    "name-placeholder": "Ex : olac",
+    "creation-date": "Creation date",
+    "actions": "Actions",
+    "references": "References"
   },
   "errors": {
     "emptyFile": "File is empty",
@@ -69,5 +78,13 @@
     "unknownCheckerName": "For the validation rule : <code>{lineValidationRuleKey}</code>, '<code>{checkerName}</code>' is declared but is not a known checker",
     "csvBoundToUnknownVariable": "In the CSV format, header <code>{header}</code> is bound to unknown variable <code>{variable}</code>. Known variables: <code>{variables}</code>",
     "csvBoundToUnknownVariableComponent": "In the CSV format, header <code>{header}</code> is bound to <code>{variable}</code> but it has no <code>{component}</code> component. Known components: <code>{components}</code>"
+  },
+  "referencesManagement": {
+    "actions": "Actions",
+    "consult": "Consult",
+    "download": "Download",
+    "delete": "Delete",
+    "references": "References",
+    "data": "Data"
   }
-}
\ No newline at end of file
+}
diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json
index 5d4b60692f7dbe1aa511ab875758c14271c8ee2c..2a24d21b6d9e1f718e6196a6ad7e26ca631e8f7a 100644
--- a/ui2/src/locales/fr.json
+++ b/ui2/src/locales/fr.json
@@ -2,16 +2,17 @@
   "titles": {
     "login-page": "Bienvenue sur SI-ORE",
     "applications-page": "Mes applications",
-    "references-page": "Mes référentiels",
+    "references-page": "Référentiels de {applicationName}",
+    "references-data": "Données de {refName}",
     "application-creation": "Créer une application"
   },
   "login": {
     "signin": "Se connecter",
     "signup": "Créer un compte",
     "login": "Identifiant",
-    "login-placeholder": "Entrer l'identifiant",
+    "login-placeholder": "Ex: michel",
     "pwd": "Mot de passe",
-    "pwd-placeholder": "Entrer le mot de passe",
+    "pwd-placeholder": "Ex: xxxx",
     "pwd-forgotten": "Mot de passe oublié ?"
   },
   "validation": {
@@ -26,7 +27,12 @@
     "server-error": "Une erreur serveur est survenue",
     "user-unknown": "Identifiants inconnus",
     "application-creation-success": "L'application a été créée !",
-    "application-validate-success": "Le fichier YAML est valide !"
+    "application-validate-success": "Le fichier YAML est valide !",
+    "warning": "Attention !",
+    "reference-deletion-msg": "Vous allez supprimer le référentiel : {label}. Êtes-vous sûr ?",
+    "delete": "Supprimer",
+    "reference-csv-upload-error": "Une erreur s'est produite au téléversement du fichier csv",
+    "reference-updated": "Référentiel mis à jour"
   },
   "message": {
     "app-config-error": "Erreur dans le fichier yaml",
@@ -45,7 +51,10 @@
     "create": "Créer l'application",
     "test": "Tester",
     "name": "Nom de l'application",
-    "name-placeholder": "Entrer le nom de l'application"
+    "name-placeholder": "Ex : olac",
+    "creation-date": "Date de création",
+    "actions": "Actions",
+    "references": "Référentiels"
   },
   "errors": {
     "emptyFile": "Le fichier est vide",
@@ -69,5 +78,13 @@
     "unknownCheckerName": "Pour la règle de validation <code>{lineValidationRuleKey}</code>, '<code>{checkerName}</code>' est déclaré mais ce n’est pas un contrôle connu",
     "csvBoundToUnknownVariable": "Dans le format CSV, l’entête <code>{header}</code> est lié à la variable <code>{variable}</code> qui n’est pas connue. Variables connues <code>{variables}</code>",
     "csvBoundToUnknownVariableComponent": "Dans le format CSV, l’entête <code>{header}</code> est lié à la variable <code>{variable}</code> mais elle n’a pas de composant <code>{component}</code>. Composants connus <code>{components}</code>"
+  },
+  "referencesManagement": {
+    "actions": "Actions",
+    "consult": "Consulter",
+    "download": "Télécharger",
+    "delete": "Supprimer",
+    "references": "Référentiels",
+    "data": "Données"
   }
 }
diff --git a/ui2/src/main.js b/ui2/src/main.js
index 47d3688f4a5e61d2c3c3d3ec9c4a9677c9876fc6..4b248832a2bd0cf07b8512ea6119bae512f51154 100644
--- a/ui2/src/main.js
+++ b/ui2/src/main.js
@@ -9,15 +9,24 @@ import {
   faAngleRight,
   faArrowDown,
   faArrowUp,
+  faCaretDown,
+  faCaretUp,
   faCheck,
+  faDownload,
+  faDraftingCompass,
   faExclamationCircle,
   faEye,
   faEyeSlash,
   faGlobe,
   faPlus,
+  faPoll,
   faSignOutAlt,
+  faTimes,
+  faTrashAlt,
   faUpload,
+  faWrench,
   faVial,
+  faCaretRight,
 } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
 library.add(
@@ -33,7 +42,16 @@ library.add(
   faArrowDown,
   faAngleLeft,
   faAngleRight,
-  faVial
+  faWrench,
+  faPoll,
+  faDraftingCompass,
+  faCaretUp,
+  faCaretDown,
+  faTimes,
+  faTrashAlt,
+  faDownload,
+  faVial,
+  faCaretRight
 );
 Vue.component("vue-fontawesome", FontAwesomeIcon);
 
diff --git a/ui2/src/model/ApplicationResult.js b/ui2/src/model/ApplicationResult.js
new file mode 100644
index 0000000000000000000000000000000000000000..835c10792d19f2ee46cb412971862e76c4c80e6b
--- /dev/null
+++ b/ui2/src/model/ApplicationResult.js
@@ -0,0 +1,18 @@
+export class ApplicationResult {
+  id;
+  name;
+  title;
+  references = {
+    idRef: {
+      id: "",
+      label: "",
+      children: [],
+      columns: {
+        id: "",
+        title: "",
+        key: false,
+        linkedTo: "",
+      },
+    },
+  };
+}
diff --git a/ui2/src/model/Button.js b/ui2/src/model/Button.js
new file mode 100644
index 0000000000000000000000000000000000000000..5d3d08c397e269b3de9db1dd3f6132e53785fbe1
--- /dev/null
+++ b/ui2/src/model/Button.js
@@ -0,0 +1,15 @@
+export class Button {
+  id;
+  label;
+  iconName;
+  clickCb;
+  type;
+
+  constructor(label, iconName, clickCb, type, id) {
+    this.label = label;
+    this.iconName = iconName;
+    this.clickCb = clickCb;
+    this.id = id ? id : label ? label : iconName;
+    this.type = type;
+  }
+}
diff --git a/ui2/src/router/index.js b/ui2/src/router/index.js
index e72efccf6df1177cf727d5a01a2a5770cf0e13ac..0001e72b4f9fca083b5f531564657bb92b61caa6 100644
--- a/ui2/src/router/index.js
+++ b/ui2/src/router/index.js
@@ -1,8 +1,10 @@
 import Vue from "vue";
 import VueRouter from "vue-router";
 import LoginView from "@/views/LoginView.vue";
-import ApplicationsView from "@/views/ApplicationsView.vue";
-import ApplicationCreationView from "@/views/ApplicationCreationView.vue";
+import ApplicationsView from "@/views/application/ApplicationsView.vue";
+import ApplicationCreationView from "@/views/application/ApplicationCreationView.vue";
+import ReferencesManagementView from "@/views/references/ReferencesManagementView.vue";
+import ReferenceTable from "@/views/references/ReferenceTableView.vue";
 
 Vue.use(VueRouter);
 
@@ -26,6 +28,17 @@ const routes = [
     name: "Application creation",
     component: ApplicationCreationView,
   },
+  {
+    path: "/applications/:applicationName/references",
+    name: "References management view",
+    component: ReferencesManagementView,
+    props: true,
+  },
+  {
+    path: "/applications/:applicationName/references/:refId",
+    component: ReferenceTable,
+    props: true,
+  },
 ];
 
 const router = new VueRouter({
diff --git a/ui2/src/services/AlertService.js b/ui2/src/services/AlertService.js
index be93def851e1ebb220f2661ba68ccf985883ff89..9064f6b9e753bdbaf55ecb312cb074038edec029 100644
--- a/ui2/src/services/AlertService.js
+++ b/ui2/src/services/AlertService.js
@@ -1,6 +1,6 @@
 import { i18n } from "@/main";
 import { BuefyTypes } from "@/utils/BuefyUtils";
-import { ToastProgrammatic } from "buefy";
+import { ToastProgrammatic, DialogProgrammatic } from "buefy";
 
 const TOAST_INFO_DURATION = 3000;
 const TOAST_ERROR_DURATION = 8000;
@@ -44,4 +44,18 @@ export class AlertService {
   toastServerError(error) {
     this.toastError(i18n.t("alert.server-error"), error);
   }
+
+  dialog(title, message, confirmText, type, onConfirmCb) {
+    DialogProgrammatic.confirm({
+      title: title,
+      message: message,
+      confirmText: confirmText,
+      type: type,
+      hasIcon: true,
+      cancelText: this.cancelMsg,
+      onConfirm: () => {
+        onConfirmCb();
+      },
+    });
+  }
 }
diff --git a/ui2/src/services/rest/ApplicationService.js b/ui2/src/services/rest/ApplicationService.js
index 12df40ee045ad9c924c0c2b596c9f058f1586ebc..54869e111b8d90e025085683020dc895cf847ed3 100644
--- a/ui2/src/services/rest/ApplicationService.js
+++ b/ui2/src/services/rest/ApplicationService.js
@@ -17,6 +17,14 @@ export class ApplicationService extends Fetcher {
     return this.get("applications/");
   }
 
+  async getApplication(name) {
+    return this.get("applications/" + name);
+  }
+
+  async getDataset(dataset, applicationName) {
+    return this.get(`applications/${applicationName}/data/${dataset}`);
+  }
+
   async validateConfiguration(applicationConfig) {
     return this.post("validate-configuration", {
       file: applicationConfig.file,
diff --git a/ui2/src/services/rest/ReferenceService.js b/ui2/src/services/rest/ReferenceService.js
new file mode 100644
index 0000000000000000000000000000000000000000..36c03c4469ebf9e489a4ef49f6c4d493c98575d1
--- /dev/null
+++ b/ui2/src/services/rest/ReferenceService.js
@@ -0,0 +1,19 @@
+import { Fetcher } from "../Fetcher";
+
+export class ReferenceService extends Fetcher {
+  static INSTANCE = new ReferenceService();
+
+  constructor() {
+    super();
+  }
+
+  async getReferenceValues(applicationName, referenceId) {
+    return this.get(`applications/${applicationName}/references/${referenceId}`);
+  }
+
+  async createReference(applicationName, referenceId, refFile) {
+    return this.post(`applications/${applicationName}/references/${referenceId}`, {
+      file: refFile,
+    });
+  }
+}
diff --git a/ui2/src/style/_common.scss b/ui2/src/style/_common.scss
index 0237eb0c731c052396e9b693594069ac7a7f7f0b..04baf8edb161acee274059879406507a78225e15 100644
--- a/ui2/src/style/_common.scss
+++ b/ui2/src/style/_common.scss
@@ -6,7 +6,7 @@ body {
 
 .title {
   color: $primary;
-  margin-top: 1.5rem;
+  margin-top: $title-margin-top;
 
   &.main-title {
     display: flex;
@@ -19,6 +19,18 @@ a {
   color: $info;
 }
 
+.clickable {
+  cursor: pointer;
+}
+
+.link {
+  cursor: pointer;
+  &:hover {
+    color: $primary;
+    text-decoration: underline;
+  }
+}
+
 // Input style
 
 .input-field {
diff --git a/ui2/src/style/_variables.scss b/ui2/src/style/_variables.scss
index 4b6281368a8adcaf09b8e13c067224368c06178a..4abde752e91609d8fba1ef098c67839f4241010a 100644
--- a/ui2/src/style/_variables.scss
+++ b/ui2/src/style/_variables.scss
@@ -1,29 +1,33 @@
-/**************************************************************************************************
-*                       Global app variables (defined in the app)                                 *
-***************************************************************************************************/
-
-$font-family: "LiberationSans", Helvetica, Arial, sans-serif;
-
-$text-default-color: #2c3e50;
-$light-text: rgb(230, 230, 230);
-// InputWithValidation
-$input-field-margin-bot: 1rem;
-$input-help-margin-top: 0.25rem;
-
-// MenuView
-$menu-height: 80px;
-
-/**************************************************************************************************
-*                                   Buefy/Bulma customizations                                   *
-*        see all customizable variables here https://buefy.org/documentation/customization/       *
-***************************************************************************************************/
-
-// General variables
-$primary: rgb(0,163,166);
-$info: #4ec6c2;
-$success: #bade81;
-$warning: #ffec60;
-$danger: #d13a18;
-$dark: #4b6464;
-$light: #aab7b7;
-$family-primary: $font-family;
+/**************************************************************************************************
+*                       Global app variables (defined in the app)                                 *
+***************************************************************************************************/
+
+$font-family: "LiberationSans", Helvetica, Arial, sans-serif;
+
+$text-default-color: #2c3e50;
+$light-text: rgb(230, 230, 230);
+$primary-slightly-transparent: rgba(0, 163, 166, 0.8);
+$info-transparent: rgba(78, 198, 194, 0.3);
+
+// PageView
+$container-padding-hor: 3rem;
+$container-padding-vert: $container-padding-hor / 2;
+$title-margin-top: 1.5rem;
+
+// MenuView
+$menu-height: 80px;
+
+/**************************************************************************************************
+*                                   Buefy/Bulma customizations                                   *
+*        see all customizable variables here https://buefy.org/documentation/customization/       *
+***************************************************************************************************/
+
+// General variables
+$primary: rgb(0, 163, 166);
+$info: rgb(78, 198, 194);
+$success: #bade81;
+$warning: #ffec60;
+$danger: #d13a18;
+$dark: #4b6464;
+$light: rgb(202, 216, 216);
+$family-primary: $font-family;
diff --git a/ui2/src/utils/ConversionUtils.js b/ui2/src/utils/ConversionUtils.js
new file mode 100644
index 0000000000000000000000000000000000000000..3e35a15cb941702fee16e8478e2eedd532c6d3f2
--- /dev/null
+++ b/ui2/src/utils/ConversionUtils.js
@@ -0,0 +1,25 @@
+export function convertReferencesToTrees(initialReference) {
+  const references = JSON.parse(JSON.stringify(initialReference));
+  const parents = references.filter((ref) => {
+    return !references.some(
+      (r) => r.children && r.children.length !== 0 && r.children.some((c) => c === ref.id)
+    );
+  });
+  return replaceChildrenIdByObject(parents, references);
+}
+
+function replaceChildrenIdByObject(references, initialRef) {
+  references.forEach((ref) => {
+    if (ref.children && ref.children.length !== 0) {
+      const children = ref.children.map((c) => {
+        const index = initialRef.findIndex((r) => r.id === c);
+        const [child] = initialRef.splice(index, 1);
+        return child;
+      });
+      ref.children = replaceChildrenIdByObject(children, initialRef);
+    } else {
+      return ref;
+    }
+  });
+  return references;
+}
diff --git a/ui2/src/views/ApplicationsView.vue b/ui2/src/views/ApplicationsView.vue
deleted file mode 100644
index e6845c3e63616d50762039866580a31d6e885556..0000000000000000000000000000000000000000
--- a/ui2/src/views/ApplicationsView.vue
+++ /dev/null
@@ -1,56 +0,0 @@
-<template>
-  <div>
-    <PageView>
-      <h1 class="title main-title">{{ $t("titles.applications-page") }}</h1>
-      <div class="buttons">
-        <b-button type="is-primary" @click="createApplication" icon-right="plus">
-          {{ $t("applications.create") }}
-        </b-button>
-      </div>
-      <b-table
-        :data="applications"
-        :striped="true"
-        :isFocusable="true"
-        :isHoverable="true"
-        :sticky-header="true"
-        :paginated="true"
-        :per-page="15"
-        height="100%"
-      >
-        <b-table-column field="name" label="Name" sortable width="50%" v-slot="props">
-          {{ props.row.name }}
-        </b-table-column>
-        <b-table-column field="creationDate" label="Creation Date" sortable v-slot="props">
-          {{ new Date(props.row.creationDate) }}
-        </b-table-column>
-      </b-table>
-    </PageView>
-  </div>
-</template>
-
-<script>
-import { ApplicationService } from "@/services/rest/ApplicationService";
-import { Component, Vue } from "vue-property-decorator";
-import PageView from "./common/PageView.vue";
-
-@Component({
-  components: { PageView },
-})
-export default class ApplicationsView extends Vue {
-  applicationService = ApplicationService.INSTANCE;
-
-  applications = [];
-
-  created() {
-    this.init();
-  }
-
-  async init() {
-    this.applications = await this.applicationService.getApplications();
-  }
-
-  createApplication() {
-    this.$router.push("/applicationCreation");
-  }
-}
-</script>
diff --git a/ui2/src/views/ApplicationCreationView.vue b/ui2/src/views/application/ApplicationCreationView.vue
similarity index 100%
rename from ui2/src/views/ApplicationCreationView.vue
rename to ui2/src/views/application/ApplicationCreationView.vue
diff --git a/ui2/src/views/application/ApplicationsView.vue b/ui2/src/views/application/ApplicationsView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..bfc21d229422c9e842a03fc3aa9bd5d2d4982bc2
--- /dev/null
+++ b/ui2/src/views/application/ApplicationsView.vue
@@ -0,0 +1,71 @@
+<template>
+  <PageView>
+    <h1 class="title main-title">{{ $t("titles.applications-page") }}</h1>
+    <div class="buttons">
+      <b-button type="is-primary" @click="createApplication" icon-right="plus">
+        {{ $t("applications.create") }}
+      </b-button>
+    </div>
+    <b-table
+      :data="applications"
+      :striped="true"
+      :isFocusable="true"
+      :isHoverable="true"
+      :sticky-header="true"
+      :paginated="true"
+      :per-page="15"
+      height="100%"
+    >
+      <b-table-column field="name" :label="$t('applications.name')" sortable v-slot="props">
+        {{ props.row.name }}
+      </b-table-column>
+      <b-table-column
+        field="creationDate"
+        :label="$t('applications.creation-date')"
+        sortable
+        v-slot="props"
+      >
+        {{ new Date(props.row.creationDate) }}
+      </b-table-column>
+      <b-table-column field="actions" :label="$t('applications.actions')" v-slot="props">
+        <b-button icon-left="drafting-compass" @click="displayReferencesManagement(props.row)">{{
+          $t("applications.references")
+        }}</b-button>
+      </b-table-column>
+    </b-table>
+  </PageView>
+</template>
+
+<script>
+import { ApplicationService } from "@/services/rest/ApplicationService";
+import { Component, Vue } from "vue-property-decorator";
+import PageView from "@/views/common/PageView.vue";
+
+@Component({
+  components: { PageView },
+})
+export default class ApplicationsView extends Vue {
+  applicationService = ApplicationService.INSTANCE;
+
+  applications = [];
+
+  created() {
+    this.init();
+  }
+
+  async init() {
+    this.applications = await this.applicationService.getApplications();
+  }
+
+  createApplication() {
+    this.$router.push("/applicationCreation");
+  }
+
+  displayReferencesManagement(application) {
+    if (!application) {
+      return;
+    }
+    this.$router.push("/applications/" + application.name + "/references");
+  }
+}
+</script>
diff --git a/ui2/src/views/common/MenuView.vue b/ui2/src/views/common/MenuView.vue
index 5880b3ddd0269ef1694dac9141bce2a2bc4de8c6..b98c505e9e209d507046fd7afe6b20808669c246 100644
--- a/ui2/src/views/common/MenuView.vue
+++ b/ui2/src/views/common/MenuView.vue
@@ -1,39 +1,46 @@
 <template>
-  <b-navbar class="menu-view">
-    <template #start>
-      <b-navbar-item tag="router-link" :to="{ path: '/applications' }">
-        {{ $t("menu.applications") }}
-      </b-navbar-item>
-    </template>
-
-    <template #end>
-      <b-navbar-item tag="div">
-        <div class="buttons">
-          <b-button type="is-info" @click="logout" icon-right="sign-out-alt">{{
-            $t("menu.logout")
-          }}</b-button>
-        </div>
-      </b-navbar-item>
-      <b-navbar-item tag="div">
-        <b-field>
-          <b-select
-            v-model="chosenLocale"
-            :placeholder="$t('menu.language')"
-            icon="globe"
-            @input="setUserPrefLocale"
-          >
-            <option :value="locales.FRENCH">{{ $t("menu.french") }}</option>
-            <option :value="locales.ENGLISH">{{ $t("menu.english") }}</option>
-          </b-select>
-        </b-field>
-      </b-navbar-item>
-      <b-navbar-item href="https://www.inrae.fr/">
-        <img class="logo_blanc" src="@/assets/logo-inrae_blanc.svg" />
-        <img class="logo_vert" src="@/assets/Logo-INRAE.svg" />
-      </b-navbar-item>
-      <img class="logo_rep" src="@/assets/Rep-FR-logo.svg" />
-    </template>
-  </b-navbar>
+  <div class="menu-view-container">
+    <b-navbar class="menu-view" v-if="open">
+      <template #start>
+        <b-navbar-item tag="router-link" :to="{ path: '/applications' }">
+          {{ $t("menu.applications") }}
+        </b-navbar-item>
+      </template>
+
+      <template #end>
+        <b-navbar-item tag="div">
+          <div class="buttons">
+            <b-button type="is-info" @click="logout" icon-right="sign-out-alt">{{
+              $t("menu.logout")
+            }}</b-button>
+          </div>
+        </b-navbar-item>
+        <b-navbar-item tag="div">
+          <b-field>
+            <b-select
+              v-model="chosenLocale"
+              :placeholder="$t('menu.language')"
+              icon="globe"
+              @input="setUserPrefLocale"
+            >
+              <option :value="locales.FRENCH">{{ $t("menu.french") }}</option>
+              <option :value="locales.ENGLISH">{{ $t("menu.english") }}</option>
+            </b-select>
+          </b-field>
+        </b-navbar-item>
+        <b-navbar-item href="https://www.inrae.fr/">
+          <img class="logo_blanc" src="@/assets/logo-inrae_blanc.svg" />
+          <img class="logo_vert" src="@/assets/Logo-INRAE.svg" />
+        </b-navbar-item>
+        <img class="logo_rep" src="@/assets/Rep-FR-logo.svg" />
+      </template>
+    </b-navbar>
+    <FontAwesomeIcon
+      @click="open = !open"
+      :icon="open ? 'caret-up' : 'caret-down'"
+      class="clickable mr-3 menu-view-collapsible-icon"
+    />
+  </div>
 </template>
 
 <script>
@@ -43,9 +50,10 @@ import { LoginService } from "@/services/rest/LoginService";
 import { UserPreferencesService } from "@/services/UserPreferencesService";
 
 import { Locales } from "@/utils/LocaleUtils.js";
+import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
 
 @Component({
-  components: {},
+  components: { FontAwesomeIcon },
 })
 export default class MenuView extends Vue {
   loginService = LoginService.INSTANCE;
@@ -53,6 +61,7 @@ export default class MenuView extends Vue {
 
   locales = Locales;
   chosenLocale = "";
+  open = false;
 
   created() {
     this.chosenLocale = this.userPreferencesService.getUserPrefLocale();
@@ -119,4 +128,23 @@ export default class MenuView extends Vue {
     }
   }
 }
+
+.menu-view-container {
+  line-height: 0;
+}
+
+.menu-view-collapsible-icon {
+  width: 100%;
+  background-color: $primary-slightly-transparent;
+  height: 30px;
+  opacity: 0.8;
+
+  &:hover {
+    opacity: 1;
+  }
+
+  path {
+    fill: white;
+  }
+}
 </style>
diff --git a/ui2/src/views/common/PageView.vue b/ui2/src/views/common/PageView.vue
index d2d33980dacafdb77698562f90609a4388dedc75..0da05950142cc9ee9275d2d48a619e0e1434db2b 100644
--- a/ui2/src/views/common/PageView.vue
+++ b/ui2/src/views/common/PageView.vue
@@ -1,7 +1,7 @@
 <template>
   <div class="PageView">
     <MenuView v-if="hasMenu" />
-    <div class="container PageView-container">
+    <div :class="`PageView-container ${hasMenu ? '' : 'noMenu'}`">
       <slot></slot>
     </div>
   </div>
@@ -32,9 +32,21 @@ export default class PageView extends Vue {
 <style lang="scss" scoped>
 .PageView {
   height: 100%;
+  &.with-submenu {
+    .PageView-container {
+      padding-top: 0rem;
+    }
+  }
 }
 
 .PageView-container {
   width: 100%;
+  height: calc(100% - #{$menu-height});
+  padding: $container-padding-vert $container-padding-hor;
+  position: relative;
+
+  &.noMenu {
+    height: 100%;
+  }
 }
 </style>
diff --git a/ui2/src/views/references/ReferenceTableView.vue b/ui2/src/views/references/ReferenceTableView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ac40540392a41e616205d67dc7c50eaa1b2a10f2
--- /dev/null
+++ b/ui2/src/views/references/ReferenceTableView.vue
@@ -0,0 +1,121 @@
+<template>
+  <PageView class="with-submenu">
+    <SubMenu :root="application.title" :paths="subMenuPaths" />
+    <h1 class="title main-title">
+      {{ $t("titles.references-data", { refName: reference.label }) }}
+    </h1>
+
+    <div v-if="reference && columns">
+      <b-table
+        :data="tableValues"
+        :striped="true"
+        :isFocusable="true"
+        :isHoverable="true"
+        :sticky-header="true"
+        :paginated="true"
+        :per-page="15"
+        height="100%"
+      >
+        <b-table-column
+          v-for="column in columns"
+          :key="column.id"
+          :field="column.id"
+          :label="column.title"
+          sortable
+          :sticky="column.key"
+          v-slot="props"
+        >
+          {{ props.row[column.id] }}
+        </b-table-column>
+      </b-table>
+    </div>
+  </PageView>
+</template>
+
+<script>
+import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue";
+import { ApplicationResult } from "@/model/ApplicationResult";
+import { AlertService } from "@/services/AlertService";
+import { ApplicationService } from "@/services/rest/ApplicationService";
+import { ReferenceService } from "@/services/rest/ReferenceService";
+import { Prop, Vue, Component } from "vue-property-decorator";
+import PageView from "../common/PageView.vue";
+
+@Component({
+  components: { PageView, SubMenu },
+})
+export default class ReferenceTableView extends Vue {
+  @Prop() applicationName;
+  @Prop() refId;
+
+  alertService = AlertService.INSTANCE;
+  applicationService = ApplicationService.INSTANCE;
+  referenceService = ReferenceService.INSTANCE;
+
+  application = new ApplicationResult();
+  subMenuPaths = [];
+  reference = {};
+  columns = [];
+  referenceValues = [];
+  tableValues = [];
+
+  async created() {
+    await this.init();
+    this.setInitialVariables();
+  }
+
+  async init() {
+    try {
+      this.application = await this.applicationService.getApplication(this.applicationName);
+      const references = await this.referenceService.getReferenceValues(
+        this.applicationName,
+        this.refId
+      );
+      if (references) {
+        this.referenceValues = references.referenceValues;
+      }
+    } catch (error) {
+      this.alertService.toastServerError();
+    }
+  }
+
+  setInitialVariables() {
+    if (!this.application || !this.application.references) {
+      return;
+    }
+
+    this.reference = Object.values(this.application.references).find(
+      (ref) => ref.id === this.refId
+    );
+
+    this.subMenuPaths = [
+      new SubMenuPath(this.$t("referencesManagement.references").toLowerCase(), () =>
+        this.$router.push(`/applications/${this.applicationName}/references`)
+      ),
+      new SubMenuPath(this.reference.label, () =>
+        this.$router.push(`/applications/${this.applicationName}/references/${this.refId}`)
+      ),
+    ];
+
+    if (this.reference && this.reference.columns) {
+      this.columns = Object.values(this.reference.columns).sort((c1, c2) => {
+        if (c1.title < c2.title) {
+          return -1;
+        }
+
+        if (c1.title > c2.title) {
+          return 1;
+        }
+        return 0;
+      });
+    }
+
+    console.log(this.columns);
+
+    if (this.referenceValues) {
+      this.tableValues = Object.values(this.referenceValues).map((refValue) => refValue.values);
+      console.log(this.tableValues);
+    }
+  }
+}
+</script>
diff --git a/ui2/src/views/references/ReferencesManagementView.vue b/ui2/src/views/references/ReferencesManagementView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..370caf82f7a4765cd49c7ef1b776e08ae4b72e9d
--- /dev/null
+++ b/ui2/src/views/references/ReferencesManagementView.vue
@@ -0,0 +1,111 @@
+<template>
+  <PageView class="with-submenu">
+    <SubMenu :root="application.title" :paths="subMenuPaths" />
+    <h1 class="title main-title">
+      {{ $t("titles.references-page", { applicationName: application.title }) }}
+    </h1>
+    <div>
+      <CollapsibleTree
+        v-for="ref in references"
+        :key="ref.id"
+        :label="ref.label"
+        :children="ref.children"
+        :level="0"
+        :onClickLabelCb="(event, label) => openRefDetails(event, label)"
+        :onUploadCb="(label, refFile) => uploadReferenceCsv(label, refFile)"
+        :buttons="buttons"
+      />
+      <ReferencesDetailsPanel
+        :leftAlign="false"
+        :open="openPanel"
+        :reference="chosenRef"
+        :closeCb="(newVal) => (openPanel = newVal)"
+      />
+    </div>
+  </PageView>
+</template>
+
+<script>
+import { Component, Prop, Vue } from "vue-property-decorator";
+import { convertReferencesToTrees } from "@/utils/ConversionUtils";
+import CollapsibleTree from "@/components/common/CollapsibleTree.vue";
+import ReferencesDetailsPanel from "@/components/references/ReferencesDetailsPanel.vue";
+import { ApplicationService } from "@/services/rest/ApplicationService";
+import { ReferenceService } from "@/services/rest/ReferenceService";
+
+import PageView from "../common/PageView.vue";
+import { ApplicationResult } from "@/model/ApplicationResult";
+import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue";
+import { AlertService } from "@/services/AlertService";
+import { Button } from "@/model/Button";
+
+@Component({
+  components: { CollapsibleTree, ReferencesDetailsPanel, PageView, SubMenu },
+})
+export default class ReferencesManagementView extends Vue {
+  @Prop() applicationName;
+
+  applicationService = ApplicationService.INSTANCE;
+  referenceService = ReferenceService.INSTANCE;
+  alertService = AlertService.INSTANCE;
+
+  references = [];
+  openPanel = false;
+  chosenRef = null;
+  application = new ApplicationResult();
+  subMenuPaths = [];
+  buttons = [
+    new Button(
+      this.$t("referencesManagement.consult"),
+      "eye",
+      (label) => this.consultReference(label),
+      "is-primary"
+    ),
+    new Button(this.$t("referencesManagement.download"), "download"),
+  ];
+
+  created() {
+    this.subMenuPaths = [
+      new SubMenuPath(this.$t("referencesManagement.references").toLowerCase(), () =>
+        this.$router.push(`/applications/${this.applicationName}/references`)
+      ),
+    ];
+    this.init();
+  }
+
+  async init() {
+    try {
+      this.application = await this.applicationService.getApplication(this.applicationName);
+      if (!this.application || !this.application.id) {
+        return;
+      }
+      this.references = convertReferencesToTrees(Object.values(this.application.references));
+    } catch (error) {
+      this.alertService.toastServerError();
+    }
+  }
+
+  openRefDetails(event, label) {
+    event.stopPropagation();
+    this.openPanel = this.chosenRef && this.chosenRef.label === label ? !this.openPanel : true;
+    this.chosenRef = Object.values(this.application.references).find((ref) => ref.label === label);
+  }
+
+  consultReference(label) {
+    const ref = Object.values(this.application.references).find((ref) => ref.label === label);
+    if (ref) {
+      this.$router.push(`/applications/${this.applicationName}/references/${ref.id}`);
+    }
+  }
+
+  async uploadReferenceCsv(label, refFile) {
+    const reference = Object.values(this.application.references).find((ref) => ref.label === label);
+    try {
+      await this.referenceService.createReference(this.applicationName, reference.id, refFile);
+      this.alertService.toastSuccess(this.$t("alert.reference-updated"));
+    } catch (error) {
+      this.alertService.toastError(this.$t("alert.reference-csv-upload-error"), error);
+    }
+  }
+}
+</script>