diff --git a/src/Gargantext/Components/App.purs b/src/Gargantext/Components/App.purs
index 5fee8d67c418793cd2b8cd0d68860d02a66bee6c..77f463822ca29715b06b878a932ea08a9cba4913 100644
--- a/src/Gargantext/Components/App.purs
+++ b/src/Gargantext/Components/App.purs
@@ -31,5 +31,8 @@ appCpt = here.component "app" cpt where
     tasksReductor <- GAT.useTasks boxes.reloadRoot boxes.reloadForest
     R.useEffectOnce' $ do
       T.write (Just tasksReductor) tasks
+    R.useEffectOnce' $ do
+      R2.loadLocalStorageState R2.openNodesKey boxes.forestOpen
+      T.listen (R2.listenLocalStorageState R2.openNodesKey) boxes.forestOpen
     useHashRouter Router.router boxes.route -- Install router to window
     pure $ router { boxes, tasks }          -- Render router component
diff --git a/src/Gargantext/Components/Forest.purs b/src/Gargantext/Components/Forest.purs
index bef82ff7b3991a7a137bfb8ba40b544a23aa7d71..8c6d91e71d57ef21026aa89be56926fc6e903f10 100644
--- a/src/Gargantext/Components/Forest.purs
+++ b/src/Gargantext/Components/Forest.purs
@@ -5,7 +5,7 @@ module Gargantext.Components.Forest
   , forestLayoutMain
   , forestLayoutRaw
   , Common
-  , LayoutProps
+  , Props
   ) where
 
 import Data.Array as A
@@ -41,18 +41,15 @@ type Common =
   , tasks        :: T.Box (Maybe GAT.Reductor)
   )
 
-type LayoutProps =
+type Props =
   ( backend      :: T.Box (Maybe Backend)
+  , forestOpen   :: T.Box OpenNodes
   , reloadForest :: T.Box T2.Reload
   , sessions     :: T.Box Sessions
   , showLogin    :: T.Box Boolean
   | Common 
   )
 
-type Props = (
-    forestOpen :: T.Box OpenNodes
-  | LayoutProps )
-  
 type TreeExtra = (
     forestOpen :: T.Box OpenNodes
   , session :: Session
@@ -129,10 +126,10 @@ plus handed showLogin backend = H.div { className: "row" }
       "btn btn-primary col-5 " <> switchHanded "ml-1 mr-auto" "mr-1 ml-auto" handed
 
 
-forestLayout :: R2.Component LayoutProps
+forestLayout :: R2.Component Props
 forestLayout = R.createElement forestLayoutCpt
 
-forestLayoutCpt :: R.Component LayoutProps
+forestLayoutCpt :: R.Component Props
 forestLayoutCpt = here.component "forestLayout" cpt where
   cpt props@{ handed } children =
     pure $ R.fragment
@@ -141,10 +138,10 @@ forestLayoutCpt = here.component "forestLayout" cpt where
 
 -- Renders its first child component in the top bar and the rest in
 -- the main view.
-forestLayoutWithTopBar :: R2.Component LayoutProps
+forestLayoutWithTopBar :: R2.Component Props
 forestLayoutWithTopBar = R.createElement forestLayoutWithTopBarCpt
 
-forestLayoutWithTopBarCpt :: R.Component LayoutProps
+forestLayoutWithTopBarCpt :: R.Component Props
 forestLayoutWithTopBarCpt = here.component "forestLayoutWithTopBar" cpt where
   cpt props@{ handed } children = do
     let { head: topBarChild, tail: mainChildren } =
@@ -153,19 +150,20 @@ forestLayoutWithTopBarCpt = here.component "forestLayoutWithTopBar" cpt where
       [ topBar { handed } [ topBarChild ]
       , forestLayoutMain props mainChildren ]
 
-forestLayoutMain :: R2.Component LayoutProps
+forestLayoutMain :: R2.Component Props
 forestLayoutMain = R.createElement forestLayoutMainCpt
 
-forestLayoutMainCpt :: R.Component LayoutProps
+forestLayoutMainCpt :: R.Component Props
 forestLayoutMainCpt = here.component "forestLayoutMain" cpt where
   cpt props children = pure $ forestLayoutRaw props [ mainPage {} children ]
 
-forestLayoutRaw :: R2.Component LayoutProps
+forestLayoutRaw :: R2.Component Props
 forestLayoutRaw = R.createElement forestLayoutRawCpt
 
-forestLayoutRawCpt :: R.Component LayoutProps
+forestLayoutRawCpt :: R.Component Props
 forestLayoutRawCpt = here.component "forestLayoutRaw" cpt where
   cpt p@{ backend
+        , forestOpen
         , frontends
         , reloadForest
         , reloadRoot
@@ -174,15 +172,14 @@ forestLayoutRawCpt = here.component "forestLayoutRaw" cpt where
         , showLogin
         , tasks } children = do
     handed' <- T.useLive T.unequal p.handed
-    forestOpen <- T.useBox $ Set.empty
 
     pure $ R2.row $ reverseHanded
       ([ H.div { className: "col-md-2 forest-layout-raw-tree" }
-         [ forest' p.handed forestOpen ]
+         [ forest' p.handed ]
        ] <> children
       ) handed'
       where
-        forest' handed forestOpen =
+        forest' handed =
           forest { backend
                  , frontends
                  , forestOpen
diff --git a/src/Gargantext/Components/Nodes/Lists.purs b/src/Gargantext/Components/Nodes/Lists.purs
index 919088b70335bf452f9ad73e031385f9bb59ff70..57854ea57fc3dbda5692d77ed7df2217a7070879 100644
--- a/src/Gargantext/Components/Nodes/Lists.purs
+++ b/src/Gargantext/Components/Nodes/Lists.purs
@@ -34,7 +34,7 @@ here :: R2.Here
 here = R2.here "Gargantext.Components.Nodes.Lists"
 
 type ListsWithForest =
-  ( forestProps :: Record Forest.LayoutProps
+  ( forestProps :: Record Forest.Props
   , listsProps  :: Record CommonProps
   )
 
diff --git a/src/Gargantext/Components/Nodes/Texts.purs b/src/Gargantext/Components/Nodes/Texts.purs
index 5f846ef61654b696c63e27ff8eb5a56d984a7c34..954ea563bc99054ee80a6568c2dcf991e2e2ebd4 100644
--- a/src/Gargantext/Components/Nodes/Texts.purs
+++ b/src/Gargantext/Components/Nodes/Texts.purs
@@ -41,7 +41,7 @@ here = R2.here "Gargantext.Components.Nodes.Texts"
 
 --------------------------------------------------------
 type TextsWithForest = (
-    forestProps :: Record Forest.LayoutProps
+    forestProps :: Record Forest.Props
   , textsProps  :: Record CommonProps
   )
 
diff --git a/src/Gargantext/Components/Router.purs b/src/Gargantext/Components/Router.purs
index 833ec7b639171e262b2c09b0a9225e58caf5771b..7bb0fad31beb327b987ecc799878cfa866d2058e 100644
--- a/src/Gargantext/Components/Router.purs
+++ b/src/Gargantext/Components/Router.purs
@@ -92,8 +92,16 @@ forested = R.createElement forestedCpt
 forestedCpt :: R.Component Props
 forestedCpt = here.component "forested" cpt
   where
-    cpt { boxes: { backend, handed, reloadForest, reloadRoot, route, sessions, showLogin }, tasks } children = do
+    cpt { boxes: { backend
+                 , forestOpen
+                 , handed
+                 , reloadForest
+                 , reloadRoot
+                 , route
+                 , sessions
+                 , showLogin }, tasks } children = do
       pure $ forestLayout { backend
+                          , forestOpen
                           , frontends: defaultFrontends
                           , handed
                           , reloadForest
@@ -189,12 +197,13 @@ lists = R.createElement listsCpt
 listsCpt :: R.Component SessionNodeProps
 listsCpt = here.component "lists" cpt where
   cpt props@{ boxes: { backend
-                       , handed
-                       , reloadForest
-                       , reloadRoot
-                       , route
-                       , sessions
-                       , showLogin }
+                     , forestOpen
+                     , handed
+                     , reloadForest
+                     , reloadRoot
+                     , route
+                     , sessions
+                     , showLogin }
             , nodeId
             , session
             , sessionId
@@ -204,6 +213,7 @@ listsCpt = here.component "lists" cpt where
     pure $ authed sessionProps $
       Lists.listsWithForest
       { forestProps: { backend
+                     , forestOpen
                      , frontends
                      , handed
                      , reloadForest
@@ -291,12 +301,13 @@ textsCpt :: R.Component SessionNodeProps
 textsCpt = here.component "texts" cpt
   where
     cpt props@{ boxes: { backend
-                         , handed
-                         , reloadForest
-                         , reloadRoot
-                         , route
-                         , sessions
-                         , showLogin }
+                       , forestOpen
+                       , handed
+                       , reloadForest
+                       , reloadRoot
+                       , route
+                       , sessions
+                       , showLogin }
               , nodeId
               , session
               , sessionId
@@ -306,6 +317,7 @@ textsCpt = here.component "texts" cpt
       pure $ authed sessionProps $
         Texts.textsWithForest
         { forestProps: { backend
+                       , forestOpen
                        , frontends
                        , handed
                        , route
diff --git a/src/Gargantext/Utils/Reactix.purs b/src/Gargantext/Utils/Reactix.purs
index 0d12bef0df3e571123f701c76f4c23b3087468b2..0fb2a8a727b9dc44af51782383060341e8a72284 100644
--- a/src/Gargantext/Utils/Reactix.purs
+++ b/src/Gargantext/Utils/Reactix.purs
@@ -35,6 +35,7 @@ import Reactix.DOM.HTML as H
 import Reactix.React (react)
 import Reactix.SyntheticEvent as RE
 import Reactix.Utils (currySecond, hook, tuple)
+import Toestand as T
 import Unsafe.Coerce (unsafeCoerce)
 import Web.File.Blob (Blob)
 import Web.File.File as WF
@@ -327,24 +328,21 @@ openNodesKey = "garg-open-nodes"
 
 type LocalStorageKey = String
 
-useLocalStorageState :: forall s. Argonaut.DecodeJson s => Argonaut.EncodeJson s => LocalStorageKey -> s -> R.Hooks (R.State s)
-useLocalStorageState key s = do
-  -- we need to synchronously get the initial state from local storage
-  Tuple state setState' <- R.useState \_ -> unsafePerformEffect do
-    item :: Maybe String <- getItem key =<< getls
-    let json = hush <<< Argonaut.jsonParser =<< item
-    let parsed = hush <<< Argonaut.decodeJson =<< json
-    pure $ fromMaybe s parsed
-
-  let
-    setState update = do
-      let new = update state
-      setState' (\_ -> new)
-      let json = Json.stringify $ Argonaut.encodeJson new
-      storage <- getls
-      setItem key json storage
-
-  pure (Tuple state setState)
+loadLocalStorageState :: forall s. Argonaut.DecodeJson s => LocalStorageKey -> T.Box s -> Effect Unit
+loadLocalStorageState key cell = do
+  storage <- getls
+  item :: Maybe String <- getItem key storage
+  let json = hush <<< Argonaut.jsonParser =<< item
+  let parsed = hush <<< Argonaut.decodeJson =<< json
+  case parsed of
+    Nothing -> pure unit
+    Just p  -> void $ T.write p cell
+
+listenLocalStorageState :: forall s. Argonaut.EncodeJson s => LocalStorageKey -> T.Change s -> Effect Unit
+listenLocalStorageState key { old, new } = do
+  let json = Json.stringify $ Argonaut.encodeJson new
+  storage <- getls
+  setItem key json storage
 
 getMessageDataStr :: DE.MessageEvent -> String
 getMessageDataStr = getMessageData