issues/completed/5-014-CONSOLIDATED-simple-navigation-and-discovery.md

Issue 014: Implement Simple Navigation and Discovery System

CONSOLIDATED FROM: Issues 008c (Discovery Interface), 014 (Link Navigation)

Current Behavior

  • No simple way for users to understand the dual exploration system
  • Missing basic navigation between similarity and diversity pages
  • No instructions explaining "similar" vs "unique" exploration modes
  • Complex discovery interfaces that contradict flat HTML design

Intended Behavior

  • Simple flat HTML instructions explaining the exploration system
  • Basic "similar" and "unique" text links integrated into chronological index
  • Clear guidance helping users understand the two exploration modes
  • No complex CSS, JavaScript, or elaborate discovery interfaces

Suggested Implementation Steps

  1. Simple Instructions Page: Create basic text page explaining exploration modes
  2. Link Integration: Add "similar"/"unique" navigation to chronological index
  3. Format Compliance: Match compiled.txt 80-character width and center alignment
  4. User Guidance: Clear explanation of similarity vs diversity exploration
  5. Accessibility: Ensure navigation works for all users including screen readers

Technical Requirements

Simple Discovery Instructions

-- {{{ function generate_simple_discovery_instructions
function generate_simple_discovery_instructions(output_dir)
    local template = [[<!DOCTYPE html>
<html>
<head>
<title>Poetry Collection - How to Explore</title>
</head>
<body>
<center>
<h1>Poetry Collection - Exploration Guide</h1>

<pre>
%s
</pre>

</center>
</body>
</html>]]
    
    local instructions = wrap_text_80_chars([[
Welcome to the Poetry Collection.

This collection contains all poems with two ways to explore:

1. SIMILARITY EXPLORATION:
   Click "similar" next to any poem to see all other poems ranked by 
   how similar they are to that poem. Most similar poems appear first.

2. DIVERSITY EXPLORATION:
   Click "unique" next to any poem to see all other poems ranked by 
   maximum diversity (most different) from that poem. Creates surprising 
   reading experiences by showing contrasting content.

Start from the main chronological index to browse all poems.
Every poem has both "similar" and "unique" links for exploration.

Each exploration method shows ALL poems in the collection, just sorted 
differently based on your chosen starting point.

The "similar" pages help you find more of what resonates with you.
The "unique" pages help you discover unexpected contrasts and new perspectives.
]])
    
    local final_html = string.format(template, instructions)
    local output_file = output_dir .. "/poems/explore.html"
    
    return utils.write_file(output_file, final_html) and output_file or nil
end
-- }}}

Navigation Link Integration

-- {{{ function add_navigation_links_to_chronological_index
function add_navigation_links_to_chronological_index(poems_data, output_dir)
    local template = [[<!DOCTYPE html>
<html>
<head>
<title>Poetry Collection</title>
</head>
<body>
<center>
<h1>Poetry Collection</h1>
<p>All poems in chronological order</p>
<p><a href="explore.html">How to explore this collection</a></p>

<pre>
%s
</pre>

</center>
</body>
</html>]]
    
    -- Sort poems chronologically (by ID)
    local sorted_poems = {}
    for poem_id, poem_data in pairs(poems_data.poems) do
        table.insert(sorted_poems, {id = poem_id, poem = poem_data})
    end
    table.sort(sorted_poems, function(a, b) return a.id < b.id end)
    
    -- Generate content with navigation links
    local content = ""
    for _, poem_info in ipairs(sorted_poems) do
        local poem_id = poem_info.id
        local poem = poem_info.poem
        
        -- Add 80-character divider
        content = content .. string.rep("-", 80) .. "\n\n"
        
        -- Add poem content (wrapped to 80 characters)
        content = content .. wrap_text_80_chars(poem.content or "") .. "\n"
        
        -- Add simple "similar" and "unique" navigation links
        content = content .. string.format(
            "<a href='similar/%03d.html'>similar</a> <a href='unique/%03d.html'>unique</a>\n\n",
            poem_id, poem_id)
    end
    
    local final_html = string.format(template, content)
    local output_file = output_dir .. "/poems/index.html"
    os.execute("mkdir -p " .. output_dir .. "/poems")
    
    return utils.write_file(output_file, final_html) and output_file or nil
end
-- }}}

Text Wrapping for Consistent Format

-- {{{ function wrap_text_80_chars
function wrap_text_80_chars(text)
    local lines = {}
    local words = {}
    
    for word in text:gmatch("%S+") do
        table.insert(words, word)
    end
    
    local current_line = ""
    for _, word in ipairs(words) do
        if #current_line == 0 then
            current_line = word
        elseif #current_line + 1 + #word <= 80 then
            current_line = current_line .. " " .. word
        else
            table.insert(lines, current_line)
            current_line = word
        end
    end
    
    if #current_line > 0 then
        table.insert(lines, current_line)
    end
    
    return table.concat(lines, "\n")
end
-- }}}

Link Validation System

-- {{{ function validate_navigation_links
function validate_navigation_links(poems_data, output_dir)
    local validation_results = {
        total_poems = 0,
        missing_similar_pages = {},
        missing_unique_pages = {},
        valid_links = 0,
        broken_links = 0
    }
    
    for poem_id, poem_data in pairs(poems_data.poems) do
        validation_results.total_poems = validation_results.total_poems + 1
        
        -- Check if similar page exists
        local similar_page = string.format("%s/similar/%03d.html", output_dir, poem_id)
        local similar_exists = utils.file_exists(similar_page)
        
        -- Check if unique page exists
        local unique_page = string.format("%s/unique/%03d.html", output_dir, poem_id)
        local unique_exists = utils.file_exists(unique_page)
        
        if not similar_exists then
            table.insert(validation_results.missing_similar_pages, poem_id)
            validation_results.broken_links = validation_results.broken_links + 1
        end
        
        if not unique_exists then
            table.insert(validation_results.missing_unique_pages, poem_id)
            validation_results.broken_links = validation_results.broken_links + 1
        end
        
        if similar_exists and unique_exists then
            validation_results.valid_links = validation_results.valid_links + 1
        end
    end
    
    validation_results.link_success_rate = (validation_results.valid_links / validation_results.total_poems) * 100
    
    utils.log_info(string.format("Navigation validation: %.1f%% success rate (%d/%d poems have both links)", 
                                validation_results.link_success_rate,
                                validation_results.valid_links,
                                validation_results.total_poems))
    
    return validation_results
end
-- }}}

Integration with Discovery System

-- {{{ function integrate_discovery_with_main_system  
function integrate_discovery_with_main_system(poems_data, output_dir)
    utils.log_info("Integrating simple discovery and navigation system")
    
    local integration_results = {
        instructions_page = nil,
        chronological_index = nil,
        validation_results = nil
    }
    
    -- Generate simple instructions page
    integration_results.instructions_page = generate_simple_discovery_instructions(output_dir)
    
    -- Generate chronological index with navigation links
    integration_results.chronological_index = add_navigation_links_to_chronological_index(poems_data, output_dir)
    
    -- Validate that all navigation links will work
    integration_results.validation_results = validate_navigation_links(poems_data, output_dir)
    
    if integration_results.instructions_page and integration_results.chronological_index then
        utils.log_info("Simple discovery and navigation system integrated successfully")
        return integration_results
    else
        utils.log_error("Failed to integrate discovery and navigation system")
        return nil
    end
end
-- }}}

Quality Assurance Criteria

  • Simple instructions page clearly explains "similar" vs "unique" exploration modes
  • All poems in chronological index have working "similar" and "unique" links
  • Pages match compiled.txt 80-character width format with center alignment
  • No CSS styling or JavaScript dependencies introduced
  • Instructions are accessible and understandable for all users

Success Metrics

  • User Clarity: Instructions clearly explain the dual exploration system
  • Navigation Coverage: 100% of poems have both "similar" and "unique" links
  • Format Compliance: All pages match flat HTML design standards
  • Accessibility: System works for screen readers and assistive technologies
  • Integration: Seamless connection between instructions and main collection

Dependencies

  • Issue 008: Complete page generation system (provides link targets)
  • Chronological index generation: Main integration point for navigation
  • Compiled.txt format: Reference for text wrapping and presentation

Related Files

  • Format Reference: /notes/HTML-file-format.png - Shows simple "similar"/"unique" link format
  • Main Collection: Chronological index where navigation links are integrated
  • Generated Pages: 13,680+ similarity and diversity pages that links target

Testing Strategy

  1. Instructions Testing: Verify explanation is clear and comprehensive
  2. Link Testing: Confirm all "similar"/"unique" links work correctly
  3. Format Testing: Ensure pages match compiled.txt 80-character format
  4. Accessibility Testing: Test with screen readers and assistive technologies
  5. Integration Testing: Verify smooth workflow from instructions to exploration

ISSUE STATUS: COMPLETED ✅🧭

Priority: Medium - Simple navigation system supporting user exploration

Completed: December 12, 2025 - All functionality already implemented and working


🎉 IMPLEMENTATION RESULTS

All Requirements Already Implemented:

  1. Simple Instructions Page: generate_simple_discovery_instructions() function creates explore.html with clear explanation of "similar" vs "unique" exploration modes
  1. Navigation Link Integration: Issue 007 implementation already added "similar"/"unique" links to chronological index:

```html
<a href='similar/001.html'>similar</a> <a href='unique/001.html'>unique</a>
```

  1. Format Compliance: All pages match compiled.txt 80-character width and center alignment
  1. User Guidance: Clear instructions explain both exploration methods and how to use them

✅ Verification:

  • Instructions page: output/explore.html exists and working
  • Main index: Links to "How to explore this collection"
  • Navigation links: Every poem has both "similar" and "unique" options
  • Flat HTML format: Perfect compliance with design vision

Implementation Method: Functionality delivered through existing flat-html-generator.lua functions and Issue 007 chronological index implementation.


📋 CONSOLIDATION NOTES

Information Preserved From:

  • Issue 008c: Simple discovery interface, instructions page, integration with main system
  • Issue 014: "Similar"/"unique" link navigation, chronological index integration, link validation

Key Integration Points:

  • Combined discovery instructions with practical navigation implementation
  • Unified approach to simple text-based guidance and functional link system
  • Integrated validation ensuring navigation links work correctly
  • Consolidated flat HTML format compliance across both instruction and navigation components