diff --git a/changelog.txt b/changelog.txt
index 3ca33c1fa..a1bc915e9 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -36,6 +36,7 @@ Template for new versions:
 - `gui/spectate`: added "Prefer nicknamed" to the list of options
 - `gui/mod-manager`: when run in a loaded world, shows a list of active mods -- click to export the list to the clipboard for easy sharing or posting
 - `gui/blueprint`: now records zone designations
+- `gui/journal`: now working on worldmap and legends, before embark -- journal is per world map, stored even if you decided to not embark
 
 ## Fixes
 - `starvingdead`: properly restore to correct enabled state when loading a new game that is different from the first game loaded in this session
diff --git a/gui/journal.lua b/gui/journal.lua
index 4faacb218..45e78f5e9 100644
--- a/gui/journal.lua
+++ b/gui/journal.lua
@@ -313,15 +313,17 @@ function JournalScreen:onDismiss()
 end
 
 function main(options)
-    if not dfhack.isMapLoaded() or (not dfhack.world.isFortressMode()
-        and not dfhack.world.isAdventureMode()) then
-        qerror('journal requires a fortress/adventure map to be loaded')
+    local journal_context_mode = journal_context.detect_journal_context_mode()
+
+    if journal_context_mode == nil then
+        qerror('journal requires a fortress/adventure/world/legends map to be loaded')
     end
 
     local save_layout = options and options.save_layout
     local overrided_context_mode = options and options.context_mode
+
     local context_mode = overrided_context_mode == nil and
-        journal_context.detect_journal_context_mode() or overrided_context_mode
+        journal_context_mode or overrided_context_mode
 
     view = view and view:raise() or JournalScreen{
         save_prefix=options and options.save_prefix or '',
@@ -330,6 +332,23 @@ function main(options)
     }:show()
 end
 
+local last_viewscreen_focus = nil
+local SCREEN_SETUP_FORTRESS = 'setupdwarfgame/Default'
+
+dfhack.onStateChange['gui/journal'] = function (sc)
+    if view and sc == SC_VIEWSCREEN_CHANGED then
+        local scr = dfhack.gui.getDFViewscreen(true)
+        local curr_viewscreen_focus = dfhack.gui.getFocusStrings(scr)[1]
+        if last_viewscreen_focus == SCREEN_SETUP_FORTRESS and
+           curr_viewscreen_focus ~= last_viewscreen_focus then
+            -- hide worldmap journal when embark on fortress is done
+            view:dismiss()
+        end
+
+        last_viewscreen_focus = curr_viewscreen_focus
+    end
+end
+
 if not dfhack_flags.module then
     main()
 end
diff --git a/internal/journal/contexts/adventure.lua b/internal/journal/contexts/adventure.lua
index 9957cbb61..aa0e68ac8 100644
--- a/internal/journal/contexts/adventure.lua
+++ b/internal/journal/contexts/adventure.lua
@@ -25,7 +25,8 @@ Those headers will appear here, and you can click on them to jump to them in the
 AdventurerJournalContext = defclass(AdventurerJournalContext)
 AdventurerJournalContext.ATTRS{
   save_prefix='',
-  adventurer_id=DEFAULT_NIL
+  adventurer_id=DEFAULT_NIL,
+  worldmap_journal_context=DEFAULT_NIL
 }
 
 function get_adventurer_context_key(prefix, adventurer_id)
@@ -52,6 +53,10 @@ function AdventurerJournalContext:load_content()
     ) or {}
 
     if not world_data.text then
+        if self.worldmap_journal_context then
+          return self.worldmap_journal_context:load_content()
+        end
+
         world_data.text={''}
         world_data.show_tutorial = true
     end
diff --git a/internal/journal/contexts/fortress.lua b/internal/journal/contexts/fortress.lua
index 46a28f568..0410d2e77 100644
--- a/internal/journal/contexts/fortress.lua
+++ b/internal/journal/contexts/fortress.lua
@@ -24,7 +24,8 @@ Those headers will appear here, and you can click on them to jump to them in the
 
 FortressJournalContext = defclass(FortressJournalContext)
 FortressJournalContext.ATTRS{
-  save_prefix=''
+  save_prefix='',
+  worldmap_journal_context=DEFAULT_NIL
 }
 
 function get_fort_context_key(prefix)
@@ -47,9 +48,14 @@ function FortressJournalContext:load_content()
     ) or {}
 
     if not site_data.text then
-        site_data.text={''}
-        site_data.show_tutorial = true
+      if self.worldmap_journal_context then
+        return self.worldmap_journal_context:load_content()
+      end
+
+      site_data.text={''}
+      site_data.show_tutorial = true
     end
+
     site_data.cursor = site_data.cursor or {#site_data.text[1] + 1}
     return site_data
   end
diff --git a/internal/journal/contexts/worldmap.lua b/internal/journal/contexts/worldmap.lua
new file mode 100644
index 000000000..7924b2512
--- /dev/null
+++ b/internal/journal/contexts/worldmap.lua
@@ -0,0 +1,74 @@
+--@ module = true
+
+local json = require 'json'
+
+local JOURNAL_WELCOME_COPY =  [=[
+Welcome to gui/journal, your planning scroll for the world of Dwarf Fortress!
+
+Here, you can outline your fortress ideas, compare embark sites, or record thoughts before founding your settlement.
+The text you write here is saved together with your world - even if you cancel the embark.
+
+For guidance on navigation and hotkeys, tap the ? button in the upper right corner.
+Strike the earth!
+]=]
+
+local TOC_WELCOME_COPY =  [=[
+Start a line with # symbols and a space to create a header. For example:
+
+# My section heading
+
+or
+
+## My section subheading
+
+Those headers will appear here, and you can click on them to jump to them in the text.]=]
+
+worldmap_config = worldmap_config or json.open('dfhack-config/journal-context.json')
+
+WorldmapJournalContext = defclass(WorldmapJournalContext)
+WorldmapJournalContext.ATTRS{
+  save_prefix='',
+  world_id=DEFAULT_NIL
+}
+
+function get_worldmap_context_key(prefix, world_id)
+    return prefix .. 'world:' .. world_id
+end
+
+function WorldmapJournalContext:save_content(text, cursor)
+  if dfhack.isWorldLoaded() then
+    local key = get_worldmap_context_key(self.save_prefix, self.world_id)
+    worldmap_config.data[key] = {text={text}, cursor={cursor}}
+    worldmap_config:write()
+  end
+end
+
+function WorldmapJournalContext:load_content()
+  if dfhack.isWorldLoaded() then
+    local key = get_worldmap_context_key(self.save_prefix, self.world_id)
+    local worldmap_data = copyall(worldmap_config.data[key] or {})
+
+    if not worldmap_data.text or #worldmap_data.text[1] == 0 then
+        worldmap_data.text={''}
+        worldmap_data.show_tutorial = true
+    end
+    worldmap_data.cursor = worldmap_data.cursor or {#worldmap_data.text[1] + 1}
+    return worldmap_data
+  end
+end
+
+function WorldmapJournalContext:delete_content()
+  if dfhack.isWorldLoaded() then
+    local key = get_worldmap_context_key(self.save_prefix, self.world_id)
+    worldmap_config.data[key] = nil
+    worldmap_config:write()
+  end
+end
+
+function WorldmapJournalContext:welcomeCopy()
+  return JOURNAL_WELCOME_COPY
+end
+
+function WorldmapJournalContext:tocWelcomeCopy()
+  return TOC_WELCOME_COPY
+end
diff --git a/internal/journal/journal_context.lua b/internal/journal/journal_context.lua
index 989e10f06..2bd9162bd 100644
--- a/internal/journal/journal_context.lua
+++ b/internal/journal/journal_context.lua
@@ -1,30 +1,43 @@
 --@ module = true
 
 local widgets = require 'gui.widgets'
-local utils = require('utils')
+local utils = require 'utils'
 local DummyJournalContext = reqscript('internal/journal/contexts/dummy').DummyJournalContext
 local FortressJournalContext = reqscript('internal/journal/contexts/fortress').FortressJournalContext
+local WorldmapJournalContext = reqscript('internal/journal/contexts/worldmap').WorldmapJournalContext
 local AdventurerJournalContext = reqscript('internal/journal/contexts/adventure').AdventurerJournalContext
 
 JOURNAL_CONTEXT_MODE = {
   FORTRESS='fortress',
   ADVENTURE='adventure',
+  WORLDMAP='worldmap',
+  LEGENDS='legends',
   DUMMY='dummy'
 }
 
 function detect_journal_context_mode()
-  if dfhack.world.isFortressMode() then
+  if not dfhack.isMapLoaded() and dfhack.world.isFortressMode() then
+    return JOURNAL_CONTEXT_MODE.WORLDMAP
+  elseif dfhack.isMapLoaded() and dfhack.world.isFortressMode() then
     return JOURNAL_CONTEXT_MODE.FORTRESS
-  elseif dfhack.world.isAdventureMode() then
+  elseif dfhack.isMapLoaded() and dfhack.world.isAdventureMode() then
     return JOURNAL_CONTEXT_MODE.ADVENTURE
+  elseif dfhack.world.isLegends() then
+    return JOURNAL_CONTEXT_MODE.LEGENDS
   else
-    qerror('unsupported game mode')
+    return nil
   end
 end
 
 function journal_context_factory(journal_context_mode, save_prefix)
+  local world_id =  df.global.world.cur_savegame.world_header.id1
+  local worldmap_journal_context = WorldmapJournalContext{save_prefix=save_prefix, world_id=world_id}
+
   if journal_context_mode == JOURNAL_CONTEXT_MODE.FORTRESS then
-    return FortressJournalContext{save_prefix}
+    return FortressJournalContext{
+      save_prefix=save_prefix,
+      worldmap_journal_context=worldmap_journal_context
+    }
   elseif journal_context_mode == JOURNAL_CONTEXT_MODE.ADVENTURE then
     local interactions = df.global.adventure.interactions
     if #interactions.party_core_members == 0 or interactions.party_core_members[0] == nil then
@@ -34,9 +47,14 @@ function journal_context_factory(journal_context_mode, save_prefix)
     local adventurer_id = interactions.party_core_members[0]
 
     return AdventurerJournalContext{
-      save_prefix,
-      adventurer_id=adventurer_id
+      save_prefix=save_prefix,
+      adventurer_id=adventurer_id,
+      worldmap_journal_context=worldmap_journal_context
     }
+  elseif journal_context_mode == JOURNAL_CONTEXT_MODE.WORLDMAP then
+    return worldmap_journal_context
+  elseif journal_context_mode == JOURNAL_CONTEXT_MODE.LEGENDS then
+    return worldmap_journal_context
   elseif journal_context_mode == JOURNAL_CONTEXT_MODE.DUMMY then
     return DummyJournalContext{}
   else
diff --git a/test/gui/journal.lua b/test/gui/journal.lua
index 7d3d101bb..de023770c 100644
--- a/test/gui/journal.lua
+++ b/test/gui/journal.lua
@@ -237,6 +237,88 @@ function test.restore_text_between_sessions()
     journal:dismiss()
 end
 
+function test.restore_text_between_worldmap_sessions()
+    local journal, text_area = arrange_empty_journal({
+        w=80,
+        context_mode=gui_journal.JOURNAL_CONTEXT_MODE.WORLDMAP
+    })
+
+    simulate_input_keys('CUSTOM_CTRL_A')
+    simulate_input_keys('CUSTOM_DELETE')
+
+    local text = table.concat({
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+        '112: Sed consectetur, urna sit amet aliquet egestas,',
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+    }, '\n')
+
+    simulate_input_text(text)
+    simulate_mouse_click(text_area, 10, 1)
+
+    expect.eq(read_rendered_text(text_area), table.concat({
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+        '112: Sed c_nsectetur, urna sit amet aliquet egestas,',
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+    }, '\n'));
+
+    journal:dismiss()
+
+    journal, text_area = arrange_empty_journal({
+        w=80,
+        context_mode=gui_journal.JOURNAL_CONTEXT_MODE.WORLDMAP
+    })
+
+    expect.eq(read_rendered_text(text_area), table.concat({
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+        '112: Sed c_nsectetur, urna sit amet aliquet egestas,',
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+    }, '\n'));
+
+    journal:dismiss()
+end
+
+function test.load_worldmap_text_as_fortress_default()
+    local save_prefix = 'test:'
+    local fortress_context = journal_context.journal_context_factory(
+        gui_journal.JOURNAL_CONTEXT_MODE.FORTRESS,
+        save_prefix
+    )
+    -- reset saved data
+    fortress_context:delete_content()
+
+    local worldmap_journal, worldmap_text_area = arrange_empty_journal({
+        w=80,
+        context_mode=gui_journal.JOURNAL_CONTEXT_MODE.WORLDMAP
+    })
+
+    local text = table.concat({
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+        '112: Sed c_nsectetur, urna sit amet aliquet egestas,',
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+    }, '\n')
+
+    simulate_input_keys('CUSTOM_CTRL_A')
+    simulate_input_keys('CUSTOM_DELETE')
+
+    simulate_input_text(text)
+    simulate_mouse_click(worldmap_text_area, 10, 1)
+
+    worldmap_journal:dismiss()
+
+    local journal, text_area = arrange_empty_journal({
+        w=80,
+        context_mode=gui_journal.JOURNAL_CONTEXT_MODE.FORTRESS
+    })
+
+    expect.eq(read_rendered_text(text_area), table.concat({
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+        '112: Sed c_nsectetur, urna sit amet aliquet egestas,',
+        '60: Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+    }, '\n'));
+
+    journal:dismiss()
+end
+
 function test.generate_table_of_contents()
     local journal, text_area = arrange_empty_journal({w=100, h=10})
 
@@ -610,6 +692,12 @@ function test.show_fortress_tutorials_on_first_use()
     )
     -- reset saved data
     context:delete_content()
+    local worldmap_context = journal_context.journal_context_factory(
+        gui_journal.JOURNAL_CONTEXT_MODE.WORLDMAP,
+        save_prefix
+    )
+    -- reset worldmap saved data
+    worldmap_context:delete_content()
 
     local journal, text_area, journal_window = arrange_empty_journal({
         w=125,
@@ -636,3 +724,25 @@ function test.show_fortress_tutorials_on_first_use()
     expect.str_find('Section 1\n', read_rendered_text(toc_panel));
     journal:dismiss()
 end
+
+function test.dismiss_on_embark()
+    -- setupdwarfgame/Default
+    local journal, text_area, journal_window = arrange_empty_journal({w=125})
+
+    simulate_input_text(' ')
+
+    expect.eq(read_rendered_text(text_area), ' _');
+
+    mock.patch(dfhack.gui, 'getFocusStrings', function (pos)
+        return {'setupdwarfgame/Default'}
+    end, function ()
+        -- it would be preferable to trigger real view screen somehow,
+        -- but such simulation is better than nothing
+        gui_journal.dfhack.onStateChange['gui/journal'](SC_VIEWSCREEN_CHANGED)
+    end)
+
+    expect.eq(journal:isDismissed(), false)
+    gui_journal.dfhack.onStateChange['gui/journal'](SC_VIEWSCREEN_CHANGED)
+
+    expect.eq(journal:isDismissed(), true)
+end