Summary

Add menu support to the Content First module, allowing site menus to be viewed and exported as Markdown for use in AI workflows, documentation tools, and Obsidian-style knowledge bases.

Problem / motivation

The Content First module currently supports nodes only. Site menus represent important structural content — navigation hierarchies, link labels, descriptions — that AI assistants and content editors need access to in plain-text format. There is no way to inspect or export a menu as Markdown through the existing UI or Drush command.

Proposed resolution

Add a Content First tab to the menu administration interface at /admin/structure/menu/manage/{menu}/content-first that renders the full menu tree as a Markdown list, with Copy and Download buttons.
Extend the content-first:export Drush command to support menus via --entity=menu, exporting one menu-{langcode}-{name}.md file per language per menu.
Change the default value of --entity from node to all, so a bare drush content-first:export exports all supported entity types.
Add --rewrite-links and --assets-base-url options to convert internal paths to local filenames and make asset URLs absolute, enabling full Obsidian vault import.

UI changes

A new Content First local task tab appears on every menu edit page (requires the Administer menus and menu links permission). The tab renders the menu tree as a fenced Markdown block with:

Nested list items following standard Markdown indentation.
Title for linked items; plain Title for items.
Optional ": description" appended when a description is set.
"(disabled)" suffix on disabled menu links.
Copy-to-clipboard and Download-as-file buttons above the content block.

Drush command changes

New --entity values: node (nodes only), menu (menus only), all (both, new default).

New and updated options:

--bundles — for menus, accepts menu machine names (e.g. main,footer).
--status — for menus: 1 = enabled items only, 0 = disabled items only, omit = all (disabled items marked with "(disabled)").
--rewrite-links — converts internal page link paths to local filenames matching the exported node filename pattern (e.g. /en/about → en_about). Images and document files are excluded.
--assets-base-url= — makes internal asset URLs (images and documents such as PDF, DOCX, ZIP) absolute by prepending the given domain. Can be used independently of --rewrite-links.
Output filename convention for menus: menu-{langcode}-{menu-machine-name}.md

Usage examples

drush content-first:export
Export everything (nodes + menus, all languages).

drush content-first:export --entity=node
Export nodes only.

drush content-first:export --entity=menu
Export menus only.

drush content-first:export --entity=menu --bundles=main,footer
Export specific menus.

drush content-first:export --rewrite-links --assets-base-url=https://example.com
Full Obsidian import: page links as filenames, assets as absolute URLs.

Technical notes

Menu tree loading uses MenuLinkTreeInterface::load() with MenuTreeParameters::setMaxDepth(9) and the default sort manipulator.
Multilingual titles and descriptions are resolved by loading the underlying menu_link_content entity and calling getTranslation($langcode), avoiding any global language context switch.
The menu route uses _permission: 'administer menu' and the entity:menu parameter converter, consistent with all other routes under entity.menu.*.
Asset detection for --assets-base-url is extension-based (pathinfo PATHINFO_EXTENSION), covering common image and document formats.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

gedur created an issue. See original summary.

gedur’s picture

Status: Active » Needs review

Ready to review

eduardo morales alberti made their first commit to this issue’s fork.

eduardo morales alberti’s picture

Waiting for tests

eduardo morales alberti’s picture

Status: Needs review » Fixed

Fixed!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.