Navigation system overhaul: replace hardcoded nav/footer with CMS-managed models #32
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The site's navigation (header nav, footer nav, footer branding/socials, copyright text) is almost entirely hardcoded in Django templates (
nav.html,footer.html). This causes several issues:show_in_menusfield is not used; nav links are static HTML.The only dynamic footer element is legal pages via
{% get_legal_pages %}, which correctly queriesLegalPage.objects.live().filter(show_in_footer=True).Current State
nav.htmllines 14-16, 36-38nav.htmllines 17, 39-47nav.htmllines 5-9,footer.htmlline 5footer.htmllines 6-9footer.htmllines 14-16footer.htmllines 17-20get_legal_pagestagfooter.htmllines 27-37footer.htmllines 42-43SiteSettingsmodelapps/core/models.pyProposed Solution
1. Extend
SiteSettingsmodelAdd CMS-editable branding/footer fields:
site_name(CharField, default "NO HYPE AI")tagline(CharField, default "Honest AI tool reviews for developers.")footer_description(TextField — the paragraph under the logo in footer)copyright_text(CharField, default "No Hype AI. All rights reserved.")2. Create
SocialMediaLinkorderable onSiteSettingsInline model so editors can add/remove/reorder social links:
platform_name(CharField)url(URLField)icon(CharField with choices mapping to SVG icon includes)sort_order(via Wagtail'sOrderable)3. Create
NavigationMenuItemorderable onSiteSettingsInline model for header/footer nav links:
link_page(ForeignKey to Page, optional) — uses page URL/title, only renders if page is livelink_url(URLField, optional) — for external/custom linkslink_title(CharField, optional) — override display textopen_in_new_tab(BooleanField)show_in_header/show_in_footer(BooleanField)sort_order(viaOrderable)Key behaviour: If
link_pageis set but the page is unpublished/deleted, the link is automatically excluded from rendering. This solves the dead link problem.4. New template tags
{% get_nav_items "header" %}— menu items filtered byshow_in_header=True, excluding dead pages{% get_nav_items "footer" %}— same for footer{% get_social_links %}— social link orderables5. Update templates
nav.html: Replace hardcoded links with{% get_nav_items "header" %}loop + dynamic site namefooter.html: Replace hardcoded links, branding, socials with template tag loops6. Data migration
Populate new fields with current hardcoded values so the site looks identical after deployment.
Testing Strategy
Unit Tests
NavigationMenuItemwith live page → renders; unpublished page → excludedNavigationMenuItemwith external URL → renders correctlySocialMediaLinkordering respectedSiteSettingsbranding fields have correct defaultsget_nav_items("header")/get_nav_items("footer")return correct filtered setsget_social_linksreturns ordered linksE2E Tests (Playwright)
Regression
Notes
{% get_legal_pages %}unchanged — it works well and legal pages have their ownshow_in_footerfield.SiteSettings.components/icons/{platform}.html), not raw SVG in the DB.