diff --git a/ivette/src/dome/doc/guides/application.md b/ivette/src/dome/doc/guides/application.md
index ae191b062b31701c1d63c0ba49e4ad50526d7761..484a3c959757acde19a11f3730bba6c6885e087e 100644
--- a/ivette/src/dome/doc/guides/application.md
+++ b/ivette/src/dome/doc/guides/application.md
@@ -98,15 +98,22 @@ your data flow.
   `Dome.useEvent()` hooks can be used to make your components being notified by
   events.
 
-- **Window Settings** are stored in the user's home directory but remain
-  generally unnoticed by most users, although they are responsible for a good user
-  experience.  They typically include the window's position and dimension,
-  resizable items position, fold/unfold states, presentation options, etc. Most
+- **Window Settings** are stored a local file at the root of user's project, and
+  remains generally unnoticed by most users. They typically include the window's
+  position and dimension, resizable items position, fold/unfold states,
+  presentation options, etc. Most
   **Dome** components with presentation options can be assigned a `settings` key
   to make their state persistent. Contrary to Global Settings, however, they are
   not shared across several windows. You may also access these data by using
   `Settings.setWindowSetting()` and `Settings.getWindowSetting()`, or the **React** hook
   `Settings.useWindowSetting()`. See also helpers `Dome.useXxxSettings()`.
+  It is possible, from the application main menu, to reset all the window settings to their
+  default values.
+
+- **Local Storage** are stored in the same file than window settings, although
+  they are not automatically reset to their initial values.
+  This is very convenient to store persistent user data on a per-project basis.
+  See `Settings.xxxLocalStorage()` functions for more details.
 
 - **Global Settings** are stored in the user's home directory and automatically
   saved and load with your application; they are typically modified _via_ the
diff --git a/ivette/src/dome/src/main/dome.js b/ivette/src/dome/src/main/dome.js
index 8b7d3c81195fc04ece1783978380f1034a04f2df..c53b6cf4afddce8f18d13bb8d08b7046fe77d968 100644
--- a/ivette/src/dome/src/main/dome.js
+++ b/ivette/src/dome/src/main/dome.js
@@ -107,6 +107,7 @@ function obtainGlobalSettings() {
      config: path;           // Path to config file
      frame: { x,y,w,h };     // Frame position
      settings: object;       // Current settings
+     storage: object;        // Local storage
      reload: boolean;        // Reloaded window
    }
  */
@@ -114,18 +115,20 @@ function obtainGlobalSettings() {
 const WindowHandles = {}; // Indexed by *webContents* id
 
 function saveWindowConfig(handle) {
-  const settings = {
+  const configData = {
     frame: handle.frame,
     settings: handle.settings,
+    storage: handle.storage,
     devtools: handle.devtools
   };
-  saveSettings( handle.config, settings );
+  saveSettings( handle.config, configData );
 }
 
 function windowSyncSettings(event) {
   const handle = WindowHandles[event.sender.id];
   event.returnValue = {
     globals: obtainGlobalSettings(),
+    storage: handle && handle.storage,
     settings: handle && handle.settings
   };
 }
@@ -154,6 +157,14 @@ function applyWindowSettings(event,args) {
   }
 }
 
+function applyStorageSettings(event,args) {
+  const handle = WindowHandles[event.sender.id];
+  if (handle) {
+    applyPatches( handle.storage, args );
+    if (DEVEL) saveWindowConfig( handle );
+  }
+}
+
 function applyGlobalSettings(event,args) {
   applyPatches( obtainGlobalSettings(), args );
   BrowserWindow.getAllWindows().forEach((w) => {
@@ -166,6 +177,7 @@ function applyGlobalSettings(event,args) {
 
 ipcMain.on('dome.ipc.settings.window', applyWindowSettings );
 ipcMain.on('dome.ipc.settings.global', applyGlobalSettings );
+ipcMain.on('dome.ipc.settings.storage', applyStorageSettings );
 
 // --------------------------------------------------------------------------
 // --- Renderer-Process Communication
@@ -294,7 +306,7 @@ function createBrowserWindow( config, argv, wdir )
   const configFile = isAppWindow ? lookupConfig( wdir ) : PATH_WINDOW_SETTINGS ;
   const configData = loadSettings( configFile );
 
-  const { frame, devtools, settings={} } = configData;
+  const { frame, devtools, settings={}, storage={} } = configData;
   if (frame) {
     const getInt = (v) => v && _.toSafeInteger(v);
     options.x = getInt(frame.x);
@@ -309,7 +321,7 @@ function createBrowserWindow( config, argv, wdir )
   const handle = {
     window: theWindow,
     config: configFile,
-    frame, settings, devtools,
+    frame, settings, storage, devtools,
     reload: false
   };
 
diff --git a/ivette/src/dome/src/renderer/data/settings.ts b/ivette/src/dome/src/renderer/data/settings.ts
index 6caf4ee61109c181fc0aa69b899803ee8298610b..c0aeb7b61a25c9f1b9c0dde5096076bb991dc4a8 100644
--- a/ivette/src/dome/src/renderer/data/settings.ts
+++ b/ivette/src/dome/src/renderer/data/settings.ts
@@ -117,21 +117,24 @@ export class GObject<A extends JSON.json> extends GlobalSettings<A> {
 
 type store = { [key: string]: JSON.json };
 type patch = { key: string; value: JSON.json };
-type driver = { evt: string; ipc: string; broadcast: boolean };
+type driver = {
+  evt: string;
+  ipc: string;
+  globals: boolean; // Global Settings (all windows share the same)
+  defaults: boolean; // Restore defaults on demand
+};
 
 class Driver {
 
-  readonly evt: string; // broadcast event
-  readonly broadcast: boolean; // settings broadcast
+  readonly evt: string; // Global Update Event
   readonly store: Map<string, JSON.json> = new Map();
   readonly diffs: Map<string, JSON.json> = new Map();
-  readonly fire: (() => void) & { flush: () => void; cancel: () => void };
+  readonly commit: (() => void) & { flush: () => void; cancel: () => void };
 
-  constructor({ evt, ipc, broadcast }: driver) {
+  constructor({ evt, ipc, defaults, globals }: driver) {
     this.evt = evt;
-    this.broadcast = broadcast;
     // --- Update Events
-    this.fire = debounce(() => {
+    this.commit = debounce(() => {
       const m = this.diffs;
       if (m.size > 0) {
         const patches: patch[] = [];
@@ -143,14 +146,16 @@ class Driver {
       }
     }, 100);
     // --- Restore Defaults Events
-    ipcRenderer.on('dome.ipc.settings.defaults', () => {
-      this.fire.cancel();
-      this.store.clear();
-      this.diffs.clear();
-      SysEmitter.emit(this.evt);
-    });
+    if (defaults) {
+      ipcRenderer.on('dome.ipc.settings.defaults', () => {
+        this.commit.cancel();
+        this.store.clear();
+        this.diffs.clear();
+        SysEmitter.emit(this.evt);
+      });
+    }
     // --- Broadcast Events
-    if (this.broadcast) {
+    if (globals) {
       ipcRenderer.on(
         'dome.ipc.settings.broadcast',
         (_sender, updates: patch[]) => {
@@ -171,15 +176,15 @@ class Driver {
     }
     // --- Closing Events
     ipcRenderer.on('dome.ipc.closing', () => {
-      this.fire();
-      this.fire.flush();
+      this.commit();
+      this.commit.flush();
     });
   }
 
   // --- Initial Data
 
   sync(data: store) {
-    this.fire.cancel();
+    this.commit.cancel();
     this.store.clear();
     this.diffs.clear();
     const m = this.store;
@@ -204,8 +209,8 @@ class Driver {
       this.store.set(key, data);
       this.diffs.set(key, data);
     }
-    if (this.broadcast) SysEmitter.emit(this.evt);
-    this.fire();
+    SysEmitter.emit(this.evt);
+    this.commit();
   }
 
 }
@@ -225,7 +230,7 @@ function useSettings<A>(
   );
   // Local state
   const [value, setValue] = React.useState<A>(loader);
-  // Broadcast
+  // Emit update event
   React.useEffect(() => {
     const event = D.evt;
     const callback = () => setValue(loader());
@@ -249,7 +254,8 @@ function useSettings<A>(
 const WindowSettingsDriver = new Driver({
   evt: 'dome.settings.window',
   ipc: 'dome.ipc.settings.window',
-  broadcast: false,
+  globals: false,
+  defaults: true,
 });
 
 /**
@@ -330,6 +336,78 @@ export function offWindowSettings(callback: () => void) {
   SysEmitter.off(evt, callback);
 }
 
+// --------------------------------------------------------------------------
+// --- Local Storage
+// --------------------------------------------------------------------------
+
+const LocalStorageDriver = new Driver({
+  evt: 'dome.settings.storage',
+  ipc: 'dome.ipc.settings.storage',
+  globals: false,
+  defaults: false,
+});
+
+/**
+   Returns the current value of the settings (default for undefined key).
+ */
+export function getLocalStorage<A>(
+  key: string | undefined,
+  decoder: JSON.Loose<A>,
+  defaultValue: A,
+): A {
+  return key ?
+    JSON.jCatch(decoder, defaultValue)(LocalStorageDriver.load(key))
+    : defaultValue;
+}
+
+/**
+   Updates the current value of the settings (on defined key).
+   Most settings are subtypes of `JSON` and do not require any specific
+   encoder. If you have some, simply use it before updating the settings.
+   See [[useLocalStorage]] and [[useWindowsettingsdata]].
+ */
+export function setLocalStorage(
+  key: string | undefined,
+  value: JSON.json,
+) {
+  if (key) LocalStorageDriver.save(key, value);
+}
+
+export function useLocalStorage<A extends JSON.json>(
+  key: string | undefined,
+  decoder: JSON.Loose<A>,
+  defaultValue: A,
+) {
+  return useSettings({
+    decoder,
+    encoder: JSON.identity,
+    defaultValue,
+  }, LocalStorageDriver, key);
+}
+
+/** Same as [[useLocalStorage]] with a specific encoder. */
+export function useLocalStorageData<A>(
+  key: string | undefined,
+  decoder: JSON.Loose<A>,
+  encoder: JSON.Encoder<A>,
+  defaultValue: A,
+) {
+  return useSettings({
+    decoder,
+    encoder,
+    defaultValue,
+  }, LocalStorageDriver, key);
+}
+
+/** Call the callback function on window settings events. */
+export function useLocalStorageEvent(callback: () => void) {
+  React.useEffect(() => {
+    const { evt } = LocalStorageDriver;
+    SysEmitter.on(evt, callback);
+    return () => { SysEmitter.off(evt, callback); };
+  });
+}
+
 // --------------------------------------------------------------------------
 // --- Global Settings
 // --------------------------------------------------------------------------
@@ -337,7 +415,8 @@ export function offWindowSettings(callback: () => void) {
 const GlobalSettingsDriver = new Driver({
   evt: 'dome.settings.global',
   ipc: 'dome.ipc.settings.global',
-  broadcast: true,
+  globals: true,
+  defaults: true,
 });
 
 /**
@@ -371,9 +450,11 @@ export const global = GlobalSettingsDriver.evt;
 /* @ internal */
 export function synchronize() {
   const data = ipcRenderer.sendSync('dome.ipc.settings.sync');
-  const globals: store = data.store ?? {};
-  GlobalSettingsDriver.sync(globals);
+  const storage: store = data.storage ?? {};
+  const globals: store = data.globals ?? {};
   const settings: store = data.settings ?? {};
+  LocalStorageDriver.sync(storage);
+  GlobalSettingsDriver.sync(globals);
   WindowSettingsDriver.sync(settings);
 }