Overview
This document describes the internal architecture of modBrowse, including file organization, component relationships, data flow, and extension points.
File Organization
modBrowse/ R/ app-ui.R # modBrowseUI() - main UI function app-server.R # modBrowseServer() + artDisplayCard() app-run.R # run_app() - standalone launcher mod-enhancedStats.R # enhancedStatsUI/Server - stats boxes mod-collectionInfo.R # collectionInfoUI/Server - summary panel utils-badges.R # createCollectionLabelBadge() theme.R # modBrowse_theme() modBrowse-package.R # Package documentation + .onLoad() inst/ css/ # CSS stylesheets modbrowse-assets/ # Badge fallback images vignettes/ # This documentation tests/testthat/ # Unit tests
Component Hierarchy
modBrowseUI/Server coordinates: - Collection Selector (shinyNextUI select_input) - Collection Stats (8 enhancedStats instances) - Artwork Controls (filters + sort) - Artwork Cards Grid (artDisplayCard instances)
Each artDisplayCard contains: - shinyNextUI card component - New badge (conditional) - Variants badge (conditional) - NFT badge (conditional)
Data Flow
Initialization: 1. Parent app sets r 2. Parent calls artutils::get_appdata() to populate r 3. modBrowseServer extracts artDT and collections 4. UI renders collection selector with counts 5. Stats boxes initialize (empty/dash) 6. User selects collection, stats update 7. Artwork cards render for selected collection
User Interaction: - Collection selection triggers stats refresh and card grid update - Filter selection applies AND conditions to card grid - Sort selection reorders cards - Card click updates r (parent handles navigation)
Internal Functions
Within modBrowseServer: - filterData(DT, filters) - Apply filter columns as AND conditions - fmt_num(x, round_to_whole, zero_as_dash) - Format numeric with commas - fmt_count(x, zero_as_dash) - Format integer counts
Badge Helpers (internal, not exported): - addBadgeVariants(count) - Variant count overlay - addBadgeNFT() - NFT badge with CDN fallback
Filter Synchronization
Desktop checkbox buttons and mobile multi-select dropdown sync bidirectionally. A syncing flag prevents infinite update loops. See app-server.R lines 321-403.
Key points: - ignoreNULL = FALSE handles deselection - syncing flag prevents update loop - session() resets flag after Shiny flush
Badge Asset Fallback
The .onLoad() function registers local badge assets as fallback when CDN fails. addBadgeNFT() tries artutils::path_image_asset() first, falls back to local. Client-side onerror handler provides additional fallback.
Extension Points
Adding New Filters: 1. Add filter column to artDT in r_artDT() 2. Add choice to desktop filters 3. Add to mobile filters
Adding New Sort Options: 1. Add case to switch statement in output 2. Add select item to sort dropdown
Adding New Statistics: 1. Add enhancedStatsUI() call in stats_ui 2. Add corresponding enhancedStatsServer() call 3. Add computation to r_collect_stats()
Adding Card Badges: 1. Create internal badge function 2. Add to overlay logic in artDisplayCard() 3. Add parameter and update documentation
CSS Architecture
modBrowse uses Bootstrap 5 CSS variables for theming. Key classes: - .modbrowse-app - Root container - .artwork-card - Card component - .artwork-card-overlay - Badge overlays - .enhanced-stats-box - Stats value boxes - .filter-buttons-desktop / .filter-select-mobile - Responsive filters
Design Decisions
Why shinyNextUI for Cards? - Modern styling with hover effects and pressable interaction - React-based components work with shiny.react - Consistent with modGallery card styling
Why Dual Filter Controls? - Desktop users expect inline checkbox buttons - Mobile users need full-width select for touch - Sync complexity justified by improved UX
Why Internal Badge Functions? - Tightly coupled to card layout - CDN fallback is implementation detail - artDisplayCard() provides stable public API
Future Considerations
TODO items: 1. Naming Convention: Standardize to camelCase for Shiny functions 2. Badge Export: Consider if custom card layouts become common 3. Virtual Scrolling: For artists with 100+ artworks 4. Pagination: Alternative to virtual scrolling
Next Steps
- Developer Guide - Integration workflow
- Get Started - Quick overview
- Function Reference - Complete API
