diff --git a/ivette/src/frama-c/plugins/dive/index.tsx b/ivette/src/frama-c/plugins/dive/index.tsx
index 607b5065878ebe9b83a71a982d0c0c6b32bfc9cf..0cedc34e0e35f2c9c44d625c24ef0e051e5aee3b 100644
--- a/ivette/src/frama-c/plugins/dive/index.tsx
+++ b/ivette/src/frama-c/plugins/dive/index.tsx
@@ -412,7 +412,7 @@ class Dive {
         });
         break;
       default: /* This is useless and impossible if the program is correctly
-        typed, but the linter wants it */
+                  typed, but the linter wants it */
     }
   }
 
@@ -607,7 +607,7 @@ function GraphView() {
 
 Ivette.registerComponent({
   id: 'frama-c.plugins.dive',
-  label: 'Data-flow graph',
+  label: 'Dive Dataflow',
   group: 'frama-c.plugins',
   rank: 2,
   title:
@@ -616,4 +616,14 @@ Ivette.registerComponent({
   children: <GraphView />,
 });
 
+Ivette.registerView({
+  id: 'dive',
+  label: 'Dive Dataflow',
+  rank: 2,
+  layout: [
+    ['frama-c.astview', 'frama-c.plugins.dive', 'frama-c.locations'],
+    ['frama-c.properties', 'frama-c.console'],
+  ],
+});
+
 // --------------------------------------------------------------------------
diff --git a/ivette/src/frama-c/plugins/eva/index.tsx b/ivette/src/frama-c/plugins/eva/index.tsx
index 91c24dfae8e4033152c3f41962251cf5aa8e81b8..1cb699bc9420603632e6345de57c86aef1b84b75 100644
--- a/ivette/src/frama-c/plugins/eva/index.tsx
+++ b/ivette/src/frama-c/plugins/eva/index.tsx
@@ -62,9 +62,20 @@ function ValuesComponent() {
 Ivette.registerComponent({
   id: 'frama-c.plugins.values',
   group: 'frama-c.plugins',
+  rank: 1,
   label: 'Eva Values',
   title: 'Values inferred by the Eva analysis',
   children: <ValuesComponent />,
 });
 
+Ivette.registerView({
+  id: 'values',
+  rank: 1,
+  label: 'Eva Values',
+  layout: [
+    ['frama-c.astview', 'frama-c.plugins.values'],
+    'frama-c.properties',
+  ],
+});
+
 // --------------------------------------------------------------------------
diff --git a/ivette/src/ivette/index.tsx b/ivette/src/ivette/index.tsx
index 707edca49c2ab160a43fb06f233a0e1b15de2a11..31e1de1d501dddf5cb66e6964969eac47100b8e5 100644
--- a/ivette/src/ivette/index.tsx
+++ b/ivette/src/ivette/index.tsx
@@ -14,67 +14,6 @@ import { GridItem, GridHbox, GridVbox } from 'dome/layout/grids';
 import * as Lab from 'ivette@lab';
 import * as Ext from 'ivette@ext';
 
-/* --------------------------------------------------------------------------*/
-/* --- Fragments                                                          ---*/
-/* --------------------------------------------------------------------------*/
-
-let PKG = 0;
-let RANK = 0;
-let ORDER: number[] = [];
-
-/** @internal */
-export function newPackage() {
-  RANK = ++PKG;
-  ORDER = [];
-}
-
-/** @internal */
-export function nextOrder() {
-  return [...ORDER, ++RANK];
-}
-
-/**
-   Use implicit rank ordering for each element register
-   during the continuation passed in argument.
- */
-export function registerFragment(job: () => void) {
-  const STACK = ORDER;
-  const SRANK = ++RANK;
-  try {
-    ORDER = [...ORDER, SRANK];
-    RANK = 0;
-    job();
-  } finally {
-    ORDER = STACK;
-    RANK = SRANK;
-  }
-}
-
-export interface FragmentProps {
-  group?: string;
-  rank?: number;
-  children?: React.ReactNode;
-}
-
-/**
-   Ordered collection of LabView Components.
-   Otherwise, elements are ordered by `rank` and `id`.
-   @deprecated Use [[registerComponent]] with `rank` property.
- */
-export function Fragment(props: FragmentProps) {
-  const { group, rank, children } = props;
-  const context = Lab.useGroupContext();
-  const base = context.order ?? [];
-  return (
-    <Lab.Rankify
-      group={group ?? context.group}
-      order={rank === undefined ? base : [...base, rank]}
-    >
-      {children}
-    </Lab.Rankify>
-  );
-}
-
 /* --------------------------------------------------------------------------*/
 /* --- Items                                                              ---*/
 /* --------------------------------------------------------------------------*/
@@ -110,7 +49,7 @@ let GROUP: string | undefined;
    during the continuation.
  */
 export function registerGroup(group: ItemProps, job?: () => void) {
-  Lab.addLibraryItem('groups', undefined, nextOrder(), group);
+  Lab.addLibraryItem('groups', undefined, [], group);
   if (job) {
     const STACK = GROUP;
     try {
@@ -122,61 +61,31 @@ export function registerGroup(group: ItemProps, job?: () => void) {
   }
 }
 
-/**
-   Defines a group of components. The components rendered
-   _inside_ its content are implicitely affected to this group,
-   unless specified. The group content are also rendered
-   in their specified order. For nested collections of components,
-   use `<Fragment/>` instead of `<React.Fragment/>` to specify order.
-   @deprecated Use [[registerGroup]] instead.
- */
-export function Group(props: ContentProps) {
-  const { children, ...group } = props;
-  const context = Lab.useLibraryItem('groups', group);
-  return (
-    <Lab.Rankify
-      group={props.id}
-      order={context.order ?? []}
-    >
-      {children}
-    </Lab.Rankify>
-  );
-}
-
 /* --------------------------------------------------------------------------*/
 /* --- View Layout                                                        ---*/
 /* --------------------------------------------------------------------------*/
 
-export type Layout = string | { hsplit: Layout[] } | { vsplit: Layout[] };
-
-function isHsplit(ly: Layout): ly is { hsplit: Layout[] } {
-  return (ly as any).hsplit !== undefined;
-}
-
-function isVsplit(ly: Layout): ly is { vsplit: Layout[] } {
-  return (ly as any).vsplit !== undefined;
-}
+/**
+   Alternating V-split and H-split layouts.
+ */
+export type Layout = string | Layout[];
 
-function makeLayout(ly: Layout) {
+function makeLayout(ly: Layout, hsplit = false) {
   if (typeof (ly) === 'string') return <GridItem id={ly} />;
-  if (isHsplit(ly)) return (
-    <GridHbox>
-      {React.Children.toArray(ly.hsplit.map(makeLayout))}
-    </GridHbox>
-  );
-  if (isVsplit(ly)) return (
+  if (!ly) return null;
+  if (hsplit) {
+    return (
+      <GridHbox>
+        {React.Children.toArray(ly.map((l) => makeLayout(l, false)))}
+      </GridHbox>
+    );
+  }
+  return (
     <GridVbox>
-      {React.Children.toArray(ly.vsplit.map(makeLayout))}
+      {React.Children.toArray(ly.map((l) => makeLayout(l, true)))}
     </GridVbox>
   );
-  return null;
-}
 
-function makeRootLayout(ly: Layout) {
-  if (isVsplit(ly)) return (
-    React.Children.toArray(ly.vsplit.map(makeLayout))
-  );
-  return makeLayout(ly);
 }
 
 export interface ViewLayoutProps extends ItemProps {
@@ -188,45 +97,13 @@ export interface ViewLayoutProps extends ItemProps {
 
 /** Register a new View. */
 export function registerView(view: ViewLayoutProps) {
-  const { id, label, title, defaultView, layout } = view;
-  Lab.addLibraryItem('view', undefined, nextOrder(), {
-    id,
-    label,
-    title,
-    defaultView,
-    children: makeRootLayout(layout),
+  const { layout, ...viewprops } = view;
+  Lab.addLibraryItem('views', undefined, [], {
+    ...viewprops,
+    children: makeLayout(layout),
   });
 }
 
-/* --------------------------------------------------------------------------*/
-/* --- Deprecated View                                                    ---*/
-/* --------------------------------------------------------------------------*/
-
-export interface ViewProps extends ContentProps {
-  /** Use this view by default. */
-  defaultView?: boolean;
-}
-
-/**
-   Layout of LabView Components.
-   Defines a predefined layout of components. The view is organized
-   into a GridContent, which must _only_ consists of:
-   - `<GridHbox>…</GridHbox>` an horizontal grid of `GridContent` elements;
-   - `<GridVbox>…</GridVbox>` a vertical grid of `GridContent` elements;
-   - `<GridItem id=…>` a single component.
-
-   These grid content components must be imported from the `dome/layout/grids`
-   module:
-   ```
-   import { GridItem, GridHbox, GridVbox } from 'dome/layout/grids';
-   ```
-   @deprecated Use [[registerView]] instead.
- */
-export function View(props: ViewProps) {
-  Lab.useLibraryItem('views', props);
-  return null;
-}
-
 /* --------------------------------------------------------------------------*/
 /* --- Components                                                         ---*/
 /* --------------------------------------------------------------------------*/
@@ -241,20 +118,7 @@ export interface ComponentProps extends ContentProps {
    Components are sorted by rank and identifier among each group.
  */
 export function registerComponent(props: ComponentProps) {
-  Lab.addLibraryItem('components', GROUP, nextOrder(), props);
-}
-
-/**
-   LabView Component.
-   Defines a component and its content when incorporated inside a view.
-   Unless specified, the component will be implicitely attached
-   to the current enclosing group. The `rank` property can be used
-   for adjusting component ordering (see also `<Fragment/>` and `<Group/>`).
-   @deprecated Use [[registerComponent]] instead.
- */
-export function Component(props: ComponentProps) {
-  Lab.useLibraryItem('components', props);
-  return null;
+  Lab.addLibraryItem('components', GROUP, [], props);
 }
 
 export interface TitleBarProps {
diff --git a/ivette/src/renderer/Application.tsx b/ivette/src/renderer/Application.tsx
index 7da66a8b13affd622e546ad5f65ef11d597bbca4..abd682bc507fe60805e005460478aab7f0dbe6d1 100644
--- a/ivette/src/renderer/Application.tsx
+++ b/ivette/src/renderer/Application.tsx
@@ -10,11 +10,9 @@ import { Vfill } from 'dome/layout/boxes';
 import { LSplit } from 'dome/layout/splitters';
 import * as Toolbar from 'dome/frame/toolbars';
 import * as Sidebar from 'dome/frame/sidebars';
-import { GridHbox, GridItem } from 'dome/layout/grids';
-import { View } from 'ivette';
 import * as Controller from './Controller';
 import * as Extensions from './Extensions';
-import * as Laboratory from './LabView';
+import * as Laboratory from './Laboratory';
 import './PackageLoader';
 
 // --------------------------------------------------------------------------
@@ -65,29 +63,7 @@ export default (() => {
         <Laboratory.LabView
           customize={viewbar}
           settings="frama-c.labview"
-        >
-          <View id="console" label="Console" defaultView>
-            <GridItem id="frama-c.console" />
-          </View>
-          <View id="values" label="Values">
-            <GridHbox>
-              <GridItem id="frama-c.astview" />
-              <GridItem id="frama-c.plugins.values" />
-            </GridHbox>
-            <GridItem id="frama-c.properties" />
-          </View>
-          <View id="dive" label="Dive">
-            <GridHbox>
-              <GridItem id="frama-c.astview" />
-              <GridItem id="frama-c.plugins.dive" />
-              <GridItem id="frama-c.locations" />
-            </GridHbox>
-            <GridHbox>
-              <GridItem id="frama-c.properties" />
-              <GridItem id="frama-c.console" />
-            </GridHbox>
-          </View>
-        </Laboratory.LabView>
+        />
       </LSplit>
       <Toolbar.ToolBar>
         <Controller.Status />
diff --git a/ivette/src/renderer/Controller.tsx b/ivette/src/renderer/Controller.tsx
index bfbc957317e2edf787c034938548d04fb007d8bc..04c9d5c9d883b5ef896fbd4f7170322b51697fad 100644
--- a/ivette/src/renderer/Controller.tsx
+++ b/ivette/src/renderer/Controller.tsx
@@ -13,8 +13,8 @@ import { Label, Code } from 'dome/controls/labels';
 import { RichTextBuffer } from 'dome/text/buffers';
 import { Text } from 'dome/text/editors';
 
+import * as Ivette from 'ivette';
 import * as Server from 'frama-c/server';
-import { registerComponent, TitleBar } from 'ivette';
 
 import 'codemirror/theme/ambiance.css';
 
@@ -251,7 +251,7 @@ const RenderConsole = () => {
 
   return (
     <>
-      <TitleBar label={edited ? 'Command line' : 'Console'}>
+      <Ivette.TitleBar label={edited ? 'Command line' : 'Console'}>
         <IconButton
           icon="TRASH"
           display={edited}
@@ -300,7 +300,7 @@ const RenderConsole = () => {
           onClick={doSwitch}
           title="Toggle command line editing"
         />
-      </TitleBar>
+      </Ivette.TitleBar>
       <Text
         buffer={edited ? editor : Server.buffer}
         mode="text"
@@ -311,7 +311,7 @@ const RenderConsole = () => {
   );
 };
 
-registerComponent({
+Ivette.registerComponent({
   id: 'frama-c.console',
   group: 'frama-c.kernel',
   label: 'Console',
@@ -320,6 +320,14 @@ registerComponent({
   children: <RenderConsole />,
 });
 
+Ivette.registerView({
+  id: 'console',
+  rank: -1,
+  label: 'Console',
+  defaultView: true,
+  layout: 'frama-c.console',
+});
+
 // --------------------------------------------------------------------------
 // --- Status
 // --------------------------------------------------------------------------
diff --git a/ivette/src/renderer/LabView.tsx b/ivette/src/renderer/Laboratory.tsx
similarity index 100%
rename from ivette/src/renderer/LabView.tsx
rename to ivette/src/renderer/Laboratory.tsx
diff --git a/ivette/tsconfig.json b/ivette/tsconfig.json
index 18d3712820451a6faccb73551300ae54a49da76f..143f87202b1e26dd1891190fabceeffc018ab922 100644
--- a/ivette/tsconfig.json
+++ b/ivette/tsconfig.json
@@ -44,7 +44,7 @@
     "baseUrl": ".",                           /* Base directory to resolve non-absolute module names. */
     "paths": {                                /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
       "ivette@ext": [ "src/renderer/Extensions.tsx" ],
-      "ivette@lab": [ "src/renderer/LabView.tsx" ],
+      "ivette@lab": [ "src/renderer/Laboratory.tsx" ],
       "ivette": [ "src/ivette/index.tsx" ],
       "ivette/*": [ "src/ivette/*" ],
       "frama-c/api/*": [ "src/frama-c/api/generated/*" ],
diff --git a/ivette/webpack.renderer.js b/ivette/webpack.renderer.js
index 6bd133984c3f5e87d989a3c565b05e3685e92381..3f9bea9ec9b4d3ded76373b66839a38f0ec386e6 100644
--- a/ivette/webpack.renderer.js
+++ b/ivette/webpack.renderer.js
@@ -30,7 +30,7 @@ module.exports = {
       'frama-c/api':  path.resolve( __dirname , 'src/frama-c/api/generated' ),
       'frama-c':      path.resolve( __dirname , 'src/frama-c' ),
       'ivette@ext':   path.resolve( __dirname , 'src/renderer/Extensions' ),
-      'ivette@lab':   path.resolve( __dirname , 'src/renderer/LabView' ),
+      'ivette@lab':   path.resolve( __dirname , 'src/renderer/Laboratory' ),
       'ivette':       path.resolve( __dirname , 'src/ivette' ),
       'dome/misc':    path.resolve( DOME , 'misc' ),
       'dome/system':  path.resolve( DOME , 'misc/system.ts' ),