/// Landing Page Handler /// /// Generates HTML landing page for the Nostr relay. use crate::config::Config; /// Get the software version string (version + optional git commit) fn get_version() -> String { let version = env!("CARGO_PKG_VERSION"); match option_env!("GIT_COMMIT_SHORT") { Some(commit) if !commit.is_empty() => format!("v{}-{}", version, commit), _ => format!("v{}", version), } } /// Generate the footer JavaScript that sets the domain dynamically fn get_footer_script() -> &'static str { r#""# } /// Generate the common base CSS used across all pages fn get_base_css() -> &'static str { r#":root { --brand: #4434FF; --brand-light: #6b5fff; --bg: #0a0a0f; --surface: #12121a; --border: #1e1e2e; --text: #e4e4eb; --text-muted: #a8a8bd; --error: #ff4444; --success: #22c55e; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', sans-serif; line-height: 1.6; background: var(--bg); color: var(--text); min-height: 100vh; } a { color: var(--brand-light); text-decoration: none; } a:hover { text-decoration: underline; } code { background: var(--border); padding: 4px 8px; border-radius: 4px; font-family: 'SF Mono', 'Consolas', monospace; font-size: 0.875rem; color: var(--brand-light); } .footer { margin-top: 48px; padding-top: 24px; border-top: 1px solid var(--border); text-align: center; color: var(--text-muted); font-size: 0.875rem; } .footer-separator { margin: 0 0.5em; opacity: 0.5; } .software-box { display: flex; align-items: flex-start; gap: 16px; text-align: left; } .software-logo { width: 48px; height: 48px; flex-shrink: 0; } .software-content { flex: 1; } .software-heading { font-size: 1.125rem; font-weight: 500; margin-bottom: 8px; color: var(--text-muted); } .software-heading a { color: var(--brand-light); } .software-heading a:hover { text-decoration: underline; } .software-desc { color: var(--text-muted); font-size: 0.9rem; line-height: 1.5; }"# } /// Generate the software-box HTML component fn get_software_box_html() -> &'static str { r##"

Grasp Server Powered by ngit-grasp

Git hosting distributed across relays using Nostr for authorization. Find out more...

"## } /// Generate the HTML landing page pub fn get_html(config: &Config) -> String { // Curation matches NIP-11 document - currently None for this relay let curation = "None".to_string(); format!( include_str!("../../templates/landing.html"), base_css = get_base_css(), relay_name = config.relay_name, relay_description = config.relay_description, version = get_version(), curation = curation, ) } /// Generate a generic 404 page for unknown paths /// /// Used for any path that doesn't match a known route pub fn get_generic_404_html(config: &Config, path: &str) -> String { format!( r##" Not Found - {relay_name}
404

Page Not Found

The page you're looking for doesn't exist.

Requested Path
{path}
← Back to {relay_name}
{footer_script} "##, base_css = get_base_css(), relay_name = config.relay_name, path = path, version = get_version(), footer_script = get_footer_script(), ) } /// Generate a 404 page for a non-existent repository /// /// GRASP-01: "...and a 404 page for repositories it doesn't host" pub fn get_404_html(config: &Config, npub: &str, identifier: &str) -> String { format!( r##" Repository Not Found - {relay_name}
404

Repository Not Found

This repository doesn't exist on this GRASP server.

Owner {npub}
Repository {identifier}
The repository may not have been announced to this server, or the URL may be incorrect.
← Back to {relay_name}
{footer_script} "##, base_css = get_base_css(), relay_name = config.relay_name, npub = npub, identifier = identifier, version = get_version(), footer_script = get_footer_script(), ) } /// Generate a webpage for an existing repository /// /// GRASP-01: "SHOULD serve a webpage at the same endpoint linking to git nostr client(s) /// to browse the repository" pub fn get_repo_html(config: &Config, npub: &str, identifier: &str) -> String { format!( r##" {identifier} - {relay_name}

{identifier}

by {npub}

Git repository hosted using the Grasp Protocol

Browse Repository on GitWorkshop.dev →
Clone
curl -Ls https://ngit.dev/install.sh | bash
git clone nostr://{{npub}}//{{identifier}}
"##, base_css = get_base_css(), relay_name = config.relay_name, npub = npub, identifier = identifier, version = get_version(), ) }