diff --git a/client/src/app/admin/admin-shared/admin-shared.module.ts b/client/src/app/admin/admin-shared/admin-shared.module.ts
index 9b2e8c08bf694efa4634f5413e10176236ae5e20..9589d20b3b8311dcdca9f4f8db0735be2076f21c 100644
--- a/client/src/app/admin/admin-shared/admin-shared.module.ts
+++ b/client/src/app/admin/admin-shared/admin-shared.module.ts
@@ -12,6 +12,7 @@ import { NgModule } from '@angular/core';
 import { SharedModule } from 'src/app/shared/shared.module';
 import { adminSharedComponents } from './components';
 import { adminPipes } from './pipes';
+import { adminSharedServices } from './services';
 
 /**
  * @class
@@ -28,6 +29,9 @@ import { adminPipes } from './pipes';
     exports: [
         adminSharedComponents,
         adminPipes
+    ],
+    providers: [
+        adminSharedServices
     ]
 })
 export class AdminSharedModule { }
diff --git a/client/src/app/admin/admin-shared/components/index.ts b/client/src/app/admin/admin-shared/components/index.ts
index b60b506eac892b5c2a68e59aece5ca1e1b693c15..066af26aea537f667b2e8044cb22b5684013430b 100644
--- a/client/src/app/admin/admin-shared/components/index.ts
+++ b/client/src/app/admin/admin-shared/components/index.ts
@@ -9,8 +9,10 @@
 
 import { DeleteBtnComponent } from './delete-btn.component';
 import { PathSelectFormControlComponent } from './path-select-form-control.component';
+import { WebpageFormContentComponent } from './webpage-form-content.component';
 
 export const adminSharedComponents = [
     DeleteBtnComponent,
-    PathSelectFormControlComponent
+    PathSelectFormControlComponent,
+    WebpageFormContentComponent
 ];
diff --git a/client/src/app/admin/instance/webpage/components/webpage-form-content.component.html b/client/src/app/admin/admin-shared/components/webpage-form-content.component.html
similarity index 100%
rename from client/src/app/admin/instance/webpage/components/webpage-form-content.component.html
rename to client/src/app/admin/admin-shared/components/webpage-form-content.component.html
diff --git a/client/src/app/admin/instance/webpage/components/webpage-form-content.component.scss b/client/src/app/admin/admin-shared/components/webpage-form-content.component.scss
similarity index 100%
rename from client/src/app/admin/instance/webpage/components/webpage-form-content.component.scss
rename to client/src/app/admin/admin-shared/components/webpage-form-content.component.scss
diff --git a/client/src/app/admin/instance/webpage/components/webpage-form-content.component.ts b/client/src/app/admin/admin-shared/components/webpage-form-content.component.ts
similarity index 100%
rename from client/src/app/admin/instance/webpage/components/webpage-form-content.component.ts
rename to client/src/app/admin/admin-shared/components/webpage-form-content.component.ts
diff --git a/client/src/app/admin/admin-shared/services/index.ts b/client/src/app/admin/admin-shared/services/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b88262d29c9526bc5b0ebb1f9fe7d688d2dcae81
--- /dev/null
+++ b/client/src/app/admin/admin-shared/services/index.ts
@@ -0,0 +1,5 @@
+import { PrismService } from './prism.service';
+
+export const adminSharedServices = [
+    PrismService
+];
diff --git a/client/src/app/admin/instance/webpage/services/prism.service.ts b/client/src/app/admin/admin-shared/services/prism.service.ts
similarity index 83%
rename from client/src/app/admin/instance/webpage/services/prism.service.ts
rename to client/src/app/admin/admin-shared/services/prism.service.ts
index a99215c02dacc84a5908ebb4603d50c2d3026b74..0f1cf2ee70b7d161c10a0817017886ec34443779 100644
--- a/client/src/app/admin/instance/webpage/services/prism.service.ts
+++ b/client/src/app/admin/admin-shared/services/prism.service.ts
@@ -4,11 +4,8 @@ import 'prismjs';
 import 'prismjs/plugins/line-numbers/prism-line-numbers';
 import 'prismjs/components/prism-css';
 import 'prismjs/components/prism-javascript';
-import 'prismjs/components/prism-java';
 import 'prismjs/components/prism-markup';
 import 'prismjs/components/prism-typescript';
-import 'prismjs/components/prism-sass';
-import 'prismjs/components/prism-scss';
 
 declare var Prism: any;
 
diff --git a/client/src/app/admin/instance/webpage/components/index.ts b/client/src/app/admin/instance/webpage/components/index.ts
index 4d87cc8d121da85cefddd6b4cc40bdcadec8f43f..401f94b17e72569f4c4615a909480360b70ab631 100644
--- a/client/src/app/admin/instance/webpage/components/index.ts
+++ b/client/src/app/admin/instance/webpage/components/index.ts
@@ -13,7 +13,6 @@ import { EditWebpageFamilyComponent } from './edit-webpage-family.component';
 import { WebpageFamilyFormComponent } from './webpage-family-form.component';
 import { WebpageCardComponent } from './webpage-card.component';
 import { WebpageFormComponent } from './webpage-form.component';
-import { WebpageFormContentComponent } from './webpage-form-content.component';
 
 export const dummiesComponents = [
     WebpageButtonsComponent,
@@ -21,6 +20,5 @@ export const dummiesComponents = [
     EditWebpageFamilyComponent,
     WebpageFamilyFormComponent,
     WebpageCardComponent,
-    WebpageFormComponent,
-    WebpageFormContentComponent
+    WebpageFormComponent
 ];
diff --git a/client/src/app/admin/instance/webpage/webpage.module.ts b/client/src/app/admin/instance/webpage/webpage.module.ts
index ce08a41b8fb6868a60a152dd12e087533ea618e7..1411ce904e6f3de81601733c2755ed721847e98c 100644
--- a/client/src/app/admin/instance/webpage/webpage.module.ts
+++ b/client/src/app/admin/instance/webpage/webpage.module.ts
@@ -13,7 +13,6 @@ import { SharedModule } from 'src/app/shared/shared.module';
 import { WebpageRoutingModule, routedComponents } from './webpage-routing.module';
 import { dummiesComponents } from './components';
 import { AdminSharedModule } from '../../admin-shared/admin-shared.module';
-import { PrismService } from './services/prism.service';
 
 /**
  * @class
@@ -28,9 +27,6 @@ import { PrismService } from './services/prism.service';
     declarations: [
         routedComponents,
         dummiesComponents
-    ],
-    providers: [
-        PrismService
     ]
 })
 export class WebpageModule { }
diff --git a/client/src/app/instance/dynamic-content/components/datatable.component.html b/client/src/app/instance/dynamic-content/components/datatable.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..3c9515fd75820bb4ad6c126a645ebadc5f4fdc51
--- /dev/null
+++ b/client/src/app/instance/dynamic-content/components/datatable.component.html
@@ -0,0 +1,12 @@
+<table class="table table-striped">
+    <thead>
+        <tr>
+            <th *ngFor="let attribute of attributeList" scope="col">{{ attribute.label }}</th>
+        </tr>
+    </thead>
+    <tbody>
+        <tr *ngFor="let row of data">
+            <td *ngFor="let attribute of attributeList">{{ row[attribute.label] }}</td>
+        </tr>
+    </tbody>
+</table>
diff --git a/client/src/app/instance/dynamic-content/components/datatable.component.ts b/client/src/app/instance/dynamic-content/components/datatable.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b96564b72f7c56a3f6ee03701f6e5b1f73d173b6
--- /dev/null
+++ b/client/src/app/instance/dynamic-content/components/datatable.component.ts
@@ -0,0 +1,22 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
+
+import { Attribute } from 'src/app/metamodel/models';
+
+@Component({
+    selector: 'app-datatable',
+    templateUrl: 'datatable.component.html',
+    changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class DatatableComponent {
+    @Input() attributeList: Attribute[];
+    @Input() data: any[];
+}
diff --git a/client/src/app/instance/dynamic-content/components/index.ts b/client/src/app/instance/dynamic-content/components/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b3594ebb9a4ea93fe6a85fd9f3df57b631d27e0d
--- /dev/null
+++ b/client/src/app/instance/dynamic-content/components/index.ts
@@ -0,0 +1,14 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { DatatableComponent } from './datatable.component';
+
+export const dummiesComponents = [
+    DatatableComponent
+];
diff --git a/client/src/app/instance/dynamic-content/dynamic-components/dataset-sample.component.html b/client/src/app/instance/dynamic-content/dynamic-components/dataset-sample.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c6594b5751f2e4db358a4642f076cf538531e104
--- /dev/null
+++ b/client/src/app/instance/dynamic-content/dynamic-components/dataset-sample.component.html
@@ -0,0 +1 @@
+<app-datatable [attributeList]="attributeList | async" [data]="data | async"></app-datatable>
\ No newline at end of file
diff --git a/client/src/app/instance/webpage/hooks/components/dataset-sample.component.ts b/client/src/app/instance/dynamic-content/dynamic-components/dataset-sample.component.ts
similarity index 73%
rename from client/src/app/instance/webpage/hooks/components/dataset-sample.component.ts
rename to client/src/app/instance/dynamic-content/dynamic-components/dataset-sample.component.ts
index f5f36285a4731d357cb8774177efa4b12685f168..4e4b01386983095821da265beab0372b7d4e0ac8 100644
--- a/client/src/app/instance/webpage/hooks/components/dataset-sample.component.ts
+++ b/client/src/app/instance/dynamic-content/dynamic-components/dataset-sample.component.ts
@@ -10,6 +10,9 @@
 import { Component, OnInit, Input, ChangeDetectionStrategy } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
 
+import { Observable } from 'rxjs';
+
+import { Attribute } from 'src/app/metamodel/models';
 import { AppConfigService } from 'src/app/app-config.service';
 
 @Component({
@@ -23,10 +26,14 @@ export class DatasetSampleComponent implements OnInit {
     @Input() sortingDirection: string;
     @Input() nbItems: number;
 
+    attributeList: Observable<Attribute[]>;
+    data: Observable<any[]>;
+
     constructor(private http: HttpClient, private config: AppConfigService) { }
 
     ngOnInit() {
+        this.attributeList = this.http.get<any[]>(`${this.config.apiUrl}/dataset/${this.datasetName}/attribute`);
         const query = `${this.datasetName}?a=all&o=${this.sortingColumn}:${this.sortingDirection}&p=${this.nbItems}:1`;
-        this.http.get<any[]>(`${this.config.apiUrl}/search/${query}`).subscribe(data => console.log(data));
+        this.data = this.http.get<any[]>(`${this.config.apiUrl}/search/${query}`);
     }
 }
diff --git a/client/src/app/instance/webpage/hooks/components/dynamic-router-link.component.html b/client/src/app/instance/dynamic-content/dynamic-components/dynamic-router-link.component.html
similarity index 100%
rename from client/src/app/instance/webpage/hooks/components/dynamic-router-link.component.html
rename to client/src/app/instance/dynamic-content/dynamic-components/dynamic-router-link.component.html
diff --git a/client/src/app/instance/webpage/hooks/components/dynamic-router-link.component.scss b/client/src/app/instance/dynamic-content/dynamic-components/dynamic-router-link.component.scss
similarity index 100%
rename from client/src/app/instance/webpage/hooks/components/dynamic-router-link.component.scss
rename to client/src/app/instance/dynamic-content/dynamic-components/dynamic-router-link.component.scss
diff --git a/client/src/app/instance/webpage/hooks/components/dynamic-router-link.component.ts b/client/src/app/instance/dynamic-content/dynamic-components/dynamic-router-link.component.ts
similarity index 100%
rename from client/src/app/instance/webpage/hooks/components/dynamic-router-link.component.ts
rename to client/src/app/instance/dynamic-content/dynamic-components/dynamic-router-link.component.ts
diff --git a/client/src/app/instance/webpage/hooks/components/index.ts b/client/src/app/instance/dynamic-content/dynamic-components/index.ts
similarity index 85%
rename from client/src/app/instance/webpage/hooks/components/index.ts
rename to client/src/app/instance/dynamic-content/dynamic-components/index.ts
index cd090f23e16023e2fe3aba0226b8830e6d6ed1fc..81f64b144b7758770edc2f0a2f79810bedc1f3b0 100644
--- a/client/src/app/instance/webpage/hooks/components/index.ts
+++ b/client/src/app/instance/dynamic-content/dynamic-components/index.ts
@@ -1,7 +1,7 @@
 import { DynamicRouterLinkComponent } from './dynamic-router-link.component';
 import { DatasetSampleComponent } from './dataset-sample.component';
 
-export const hooksComponents = [
+export const DynamicComponents = [
     DynamicRouterLinkComponent,
     DatasetSampleComponent
 ];
diff --git a/client/src/app/instance/dynamic-content/dynamic-content.module.ts b/client/src/app/instance/dynamic-content/dynamic-content.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f4f27818c3c0ea4ef559d24a8a79de8f825e191
--- /dev/null
+++ b/client/src/app/instance/dynamic-content/dynamic-content.module.ts
@@ -0,0 +1,53 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { DynamicHooksModule, HookParserEntry } from 'ngx-dynamic-hooks';
+
+import { SharedModule } from 'src/app/shared/shared.module';
+import { hookParsers } from './parsers';
+import { DynamicComponents } from './dynamic-components';
+import { dummiesComponents } from './components';
+
+export const componentParsers: Array<HookParserEntry> = [
+    ...hookParsers,
+    ...DynamicComponents.map(component => {
+        return { component };
+    })
+];
+
+/**
+ * @class
+ * @classdesc Dynamic content module.
+ */
+@NgModule({
+    imports: [
+        SharedModule,
+        RouterModule,
+        DynamicHooksModule.forRoot({
+            globalParsers: componentParsers
+        }),
+    ],
+    exports: [
+        DynamicHooksModule
+    ],
+    providers: [
+        hookParsers
+    ],
+    declarations: [
+        DynamicComponents,
+        dummiesComponents
+    ],
+    entryComponents: [
+        DynamicComponents
+    ]
+})
+export class DynamicContentModule { }
diff --git a/client/src/app/instance/webpage/hooks/parsers/dynamic-router-link-parser.ts b/client/src/app/instance/dynamic-content/parsers/dynamic-router-link-parser.ts
similarity index 97%
rename from client/src/app/instance/webpage/hooks/parsers/dynamic-router-link-parser.ts
rename to client/src/app/instance/dynamic-content/parsers/dynamic-router-link-parser.ts
index cc0242d8bc7e37e7c4abfb9fe4029e5c489db115..cb543c79b8a96b1d49c935f44f88045eef4ee3d9 100644
--- a/client/src/app/instance/webpage/hooks/parsers/dynamic-router-link-parser.ts
+++ b/client/src/app/instance/dynamic-content/parsers/dynamic-router-link-parser.ts
@@ -1,7 +1,7 @@
 import { Injectable } from '@angular/core';
 import { HookParser, HookPosition, HookValue, HookComponentData, HookBindings, HookFinder } from 'ngx-dynamic-hooks';
 
-import { DynamicRouterLinkComponent } from '../components/dynamic-router-link.component';
+import { DynamicRouterLinkComponent } from '../dynamic-components/dynamic-router-link.component';
 
 @Injectable()
 export class DynamicRouterLinkParser implements HookParser {
diff --git a/client/src/app/instance/dynamic-content/parsers/index.ts b/client/src/app/instance/dynamic-content/parsers/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bac0c8f9072e6c66cbda86f139d047018dcba1ba
--- /dev/null
+++ b/client/src/app/instance/dynamic-content/parsers/index.ts
@@ -0,0 +1,5 @@
+import { DynamicRouterLinkParser } from './dynamic-router-link-parser';
+
+export const hookParsers = [
+    DynamicRouterLinkParser
+];
diff --git a/client/src/app/instance/webpage/hooks/components/dataset-sample.component.html b/client/src/app/instance/webpage/hooks/components/dataset-sample.component.html
deleted file mode 100644
index 85855148f2f8c40dc55351a0a29cd33637c79c44..0000000000000000000000000000000000000000
--- a/client/src/app/instance/webpage/hooks/components/dataset-sample.component.html
+++ /dev/null
@@ -1 +0,0 @@
-<p>Coucou</p>
\ No newline at end of file
diff --git a/client/src/app/instance/webpage/hooks/parsers/index.ts b/client/src/app/instance/webpage/hooks/parsers/index.ts
deleted file mode 100644
index 11414cc402a798b1eb99e2cf642a3f98ae30162d..0000000000000000000000000000000000000000
--- a/client/src/app/instance/webpage/hooks/parsers/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { HookParserEntry } from 'ngx-dynamic-hooks';
-
-import { DynamicRouterLinkParser } from './dynamic-router-link-parser';
-import { DatasetSampleComponent } from '../components/dataset-sample.component';
-
-export const hookParsers = [
-    DynamicRouterLinkParser
-];
-
-export const componentParsers: Array<HookParserEntry> = [
-    DynamicRouterLinkParser,
-    { component: DatasetSampleComponent }
-];
diff --git a/client/src/app/instance/webpage/webpage.module.ts b/client/src/app/instance/webpage/webpage.module.ts
index 989eb038a381f70fe09ae84988b7d79db1a54c43..5bec1e05d2e46632e45e0dc24d0b376d975504ee 100644
--- a/client/src/app/instance/webpage/webpage.module.ts
+++ b/client/src/app/instance/webpage/webpage.module.ts
@@ -9,13 +9,10 @@
 
 import { NgModule } from '@angular/core';
 
-import { DynamicHooksModule } from 'ngx-dynamic-hooks';
-
 import { SharedModule } from 'src/app/shared/shared.module';
+import { DynamicContentModule } from '../dynamic-content/dynamic-content.module';
 import { WebpageRoutingModule, routedComponents } from './webpage-routing.module';
 import { dummiesComponents } from './components';
-import { hookParsers, componentParsers } from './hooks/parsers';
-import { hooksComponents } from './hooks/components';
 
 /**
  * @class
@@ -24,21 +21,12 @@ import { hooksComponents } from './hooks/components';
 @NgModule({
     imports: [
         SharedModule,
+        DynamicContentModule,
         WebpageRoutingModule,
-        DynamicHooksModule.forRoot({
-            globalParsers: componentParsers
-        }),
     ],
     declarations: [
         routedComponents,
-        dummiesComponents,
-        hooksComponents
-    ],
-    providers: [
-        hookParsers
-    ],
-    entryComponents: [
-        hooksComponents
+        dummiesComponents
     ]
 })
 export class WebpageModule { }
diff --git a/client/src/styles.scss b/client/src/styles.scss
index 5c065f8b291f8c1ea008e12e6bbe9f927b90c75f..75f7f8c213dd545e17688225f7b7de2fe0186ea4 100644
--- a/client/src/styles.scss
+++ b/client/src/styles.scss
@@ -42,8 +42,6 @@
 /* Import prismjs styled design */
 @import "~prismjs/themes/prism-okaidia";
 // @import "~prismjs/themes/prism-tomorrow";
-// @import "~prismjs/themes/prism-solarizedlight";
-// @import "~prismjs/themes/prism";
 
 // Prism.js line numbers plugin
 .line-numbers .line-numbers-rows {
@@ -56,6 +54,7 @@
     letter-spacing: -1px;
     border-right: 1px solid rgb(179, 179, 179);
     user-select: none;
+    background-color: #272822;
 }
   
 .line-numbers-rows > span {