{
    "ready": true,
    "site": {
        "id": 0,
        "domain": "geek.nz",
        "display_name": "Adrian Lyall Cochrane",
        "primary_country_code": "NZ",
        "category_name": "Developer Tools: APIs & Documentation"
    },
    "metrics": {
        "global_rank": 35792,
        "country_rank": 61,
        "category_rank": 80,
        "daily_pageviews_per_visitor": 3.68,
        "daily_time_on_site_seconds": 347,
        "bounce_rate": 30.62,
        "search_visits_percent": 37.85,
        "total_sites_linking_in": 3,
        "monthly_unique_visitors": 104,
        "recorded_at": "2026-03-17 07:39:59"
    },
    "audit": {
        "score": 65
    },
    "traffic_sources": {
        "direct_percent": 27.43,
        "search_percent": 35.83,
        "social_percent": 3.04,
        "referral_percent": 20.02,
        "email_percent": 6.08,
        "paid_percent": 7.6
    },
    "seo_profile": {
        "backlinks_total": 3,
        "referring_domains": 3,
        "dofollow_backlinks_percent": 66.67,
        "organic_keywords": 60,
        "indexed_pages": 10,
        "page_speed_score": 69,
        "mobile_friendliness_score": 64,
        "authority_score": 23,
        "spam_risk_score": 12
    },
    "crawl_report": {
        "robots_status": 200,
        "sitemap_status": 200,
        "sitemap_total_urls": 10,
        "crawl_blocked": false,
        "crawl_blocked_by": "",
        "crawl_blocked_reason": "",
        "notes": [
            "Meta description is missing."
        ],
        "created_at": "2026-03-17 07:39:59"
    },
    "keywords": [
        {
            "keyword": "Adrian Lyall Cochrane",
            "position": 25,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        },
        {
            "keyword": "Adrian Lyall Cochrane developer tools: apis & documentation",
            "position": 27,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        },
        {
            "keyword": "Adrian Lyall Cochrane reviews",
            "position": 29,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        },
        {
            "keyword": "adrian",
            "position": 31,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        },
        {
            "keyword": "lyall",
            "position": 33,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        },
        {
            "keyword": "cochrane",
            "position": 35,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        },
        {
            "keyword": "geek",
            "position": 37,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        },
        {
            "keyword": "docs",
            "position": 39,
            "search_engine": "Estimated",
            "checked_at": "2026-04-17 11:49:23",
            "is_estimated": true
        }
    ],
    "rating": {
        "overall": 64,
        "label": "Healthy",
        "breakdown": [
            {
                "label": "Technical foundation",
                "score": 14,
                "max": 18
            },
            {
                "label": "Authority & trust",
                "score": 7,
                "max": 30
            },
            {
                "label": "Reach & market presence",
                "score": 3,
                "max": 18
            },
            {
                "label": "Search visibility",
                "score": 3,
                "max": 12
            },
            {
                "label": "Engagement & retention",
                "score": 9,
                "max": 10
            },
            {
                "label": "Channels & diversification",
                "score": 4,
                "max": 6
            },
            {
                "label": "Registry stability",
                "score": 0,
                "max": 6
            },
            {
                "label": "Quality system",
                "score": 78,
                "max": 100
            },
            {
                "label": "Reputation system",
                "score": 32,
                "max": 100
            },
            {
                "label": "Safety system",
                "score": 100,
                "max": 100
            },
            {
                "label": "Evidence confidence",
                "score": 99,
                "max": 100
            }
        ],
        "authority_score": 23,
        "quality_score": 78,
        "reputation_score": 32,
        "safety_score": 100,
        "confidence_score": 99,
        "fraud_score": 0,
        "authority_signals": {
            "backlinks": 3,
            "referring_domains": 3,
            "organic_keywords": 60,
            "indexed_pages": 10,
            "monthly_visitors": 104,
            "global_rank": 35792,
            "engagement_score": 79,
            "crawl_quality_score": 82,
            "brand_completeness_score": 41,
            "link_diversity_score": 94,
            "technical_reliability_score": 73,
            "whois_score": 0,
            "whois_age_years": 0,
            "whois_stability_score": 0,
            "spam_penalty": 0
        },
        "whois_signals": []
    },
    "authority_score": 23,
    "trust_score": 36,
    "domain_tags": {
        "primary_tag": "Uncertain",
        "primary_tag_score": 68,
        "primary_candidate": "Uncertain",
        "primary_candidate_score": 68,
        "tag_codes": "Uncertain,T",
        "tags": [
            {
                "code": "Uncertain",
                "label": "Uncertain",
                "tone": "unknown",
                "description": "External checks stayed inconclusive, so the model avoided a harder verdict.",
                "reason": "The evidence is mixed or only partially corroborated, so the system avoided a harder automated verdict.",
                "message": "The evidence is materially mixed or partially corroborated, so the model is avoiding a harder verdict.",
                "priority": 68,
                "score": 68,
                "match_percent": 68,
                "threshold_band": "strong"
            },
            {
                "code": "T",
                "label": "Trusted",
                "tone": "good",
                "description": "Strong trust, stability, and low-risk signals were detected.",
                "reason": "Low spam indicators plus strong trust, quality, registry, and stability signals were detected.",
                "message": "The site shows a reasonably trustworthy and stable profile.",
                "priority": 65,
                "score": 65,
                "match_percent": 65,
                "threshold_band": "strong"
            }
        ],
        "tag_breakdown": [
            {
                "code": "Uncertain",
                "label": "Uncertain",
                "tone": "unknown",
                "description": "External checks stayed inconclusive, so the model avoided a harder verdict.",
                "reason": "The evidence is mixed or only partially corroborated, so the system avoided a harder automated verdict.",
                "message": "The evidence is materially mixed or partially corroborated, so the model is avoiding a harder verdict.",
                "priority": 68,
                "score": 68,
                "match_percent": 68,
                "threshold_band": "strong"
            },
            {
                "code": "T",
                "label": "Trusted",
                "tone": "good",
                "description": "Strong trust, stability, and low-risk signals were detected.",
                "reason": "Low spam indicators plus strong trust, quality, registry, and stability signals were detected.",
                "message": "The site shows a reasonably trustworthy and stable profile.",
                "priority": 65,
                "score": 65,
                "match_percent": 65,
                "threshold_band": "strong"
            },
            {
                "code": "C",
                "label": "Caution",
                "tone": "caution",
                "description": "Signals are mixed or weak, so this domain should be treated carefully.",
                "reason": "Review carefully: mixed trust signals.",
                "message": "The current crawl does not show a meaningful caution match.",
                "priority": 0,
                "score": 0,
                "match_percent": 0,
                "threshold_band": "none"
            },
            {
                "code": "Crypto",
                "label": "Crypto drainer risk",
                "tone": "toxic",
                "description": "Wallet-connect or seed-phrase theft patterns were detected.",
                "reason": "Wallet-connect or seed-phrase theft patterns were detected.",
                "message": "No meaningful crypto-drainer signals were detected.",
                "priority": 0,
                "score": 0,
                "match_percent": 0,
                "threshold_band": "none"
            },
            {
                "code": "D",
                "label": "Dangerous",
                "tone": "toxic",
                "description": "Strong signs of phishing, malware, or other harmful behaviour were detected.",
                "reason": "Multiple high-risk signals pushed this domain into the dangerous range.",
                "message": "No meaningful dangerous-signal match was detected.",
                "priority": 0,
                "score": 0,
                "match_percent": 0,
                "threshold_band": "none"
            }
        ],
        "nsfw_score": 0,
        "trust_score": 36,
        "manual": {
            "has_changes": false,
            "verified_status": "",
            "tag_codes": "",
            "rating_delta": 0,
            "authority_delta": 0,
            "trust_delta": 0,
            "note": "",
            "adjusted_by": 0,
            "adjusted_at": "",
            "lock_scores": false,
            "lock_flags": false
        },
        "summary": "Uncertain (68% match) because the evidence is mixed or only partially corroborated, so the system avoided a harder automated verdict.",
        "external_intel": [],
        "external_decision": [],
        "signal_scores": [
            {
                "label": "Strongest tag heuristic",
                "value": "Uncertain · 68%",
                "tone": "unknown",
                "detail": "The highest raw tag match from the heuristic engine before visibility thresholds and manual overrides."
            },
            {
                "label": "Trust score",
                "value": "36/100",
                "tone": "spam",
                "detail": "Confidence derived from authority, crawl quality, stability, and risk signals."
            },
            {
                "label": "Authority score",
                "value": "23/100",
                "tone": "spam",
                "detail": "A higher authority score usually means broader reputation and backlink confidence."
            },
            {
                "label": "Spam risk",
                "value": "6/100",
                "tone": "good",
                "detail": "Lower is better. This blends spam indicators with false-positive protections for legitimate sites."
            },
            {
                "label": "Quality score",
                "value": "68/100",
                "tone": "good",
                "detail": "Based on crawl quality, content completeness, and technical evidence."
            },
            {
                "label": "Safety score",
                "value": "100/100",
                "tone": "good",
                "detail": "Higher is safer. Direct fraud signals can heavily cap this even when SEO signals look strong."
            },
            {
                "label": "Fraud score",
                "value": "0/100",
                "tone": "good",
                "detail": "Lower is better. This reflects phishing, drainer, fake-support, fake-shop, and malware signals."
            },
            {
                "label": "Infrastructure risk",
                "value": "0/100",
                "tone": "good",
                "detail": "Lower is better. This reflects the IP, registrar, and nameserver neighbourhood seen by the crawler."
            },
            {
                "label": "Evidence confidence",
                "value": "87/100",
                "tone": "good",
                "detail": "Higher means the crawler had enough pages and registry evidence to make a stronger call."
            },
            {
                "label": "External evidence",
                "value": "Low",
                "tone": "unknown",
                "detail": "Quality of the structured search and review evidence cluster."
            },
            {
                "label": "External decision",
                "value": "Inconclusive",
                "tone": "unknown",
                "detail": "How third-party evidence compares with the current candidate tag."
            },
            {
                "label": "NSFW score",
                "value": "0/100",
                "tone": "good",
                "detail": "Context-aware adult-content detection with medical / educational false-positive reduction."
            },
            {
                "label": "Registry stability",
                "value": "0/100",
                "tone": "unknown",
                "detail": "Based on age, expiry runway, and the amount of ownership / registrar churn."
            }
        ],
        "signal_sections": [
            {
                "title": "Registry & ownership",
                "items": [
                    {
                        "label": "Domain age",
                        "value": "—",
                        "tone": "unknown",
                        "detail": "Older domains generally carry more historical trust than very new ones."
                    },
                    {
                        "label": "Stability score",
                        "value": "—",
                        "tone": "unknown",
                        "detail": "Penalised by registrar, ownership, and nameserver churn."
                    },
                    {
                        "label": "Days to expiry",
                        "value": "—",
                        "tone": "unknown",
                        "detail": "Very short renewal windows can be a weak trust signal."
                    },
                    {
                        "label": "Registrar / ownership changes",
                        "value": "0 / 0",
                        "tone": "good",
                        "detail": "Frequent ownership churn can weaken trust."
                    },
                    {
                        "label": "Nameserver changes",
                        "value": "0",
                        "tone": "good",
                        "detail": "Repeated infrastructure changes can indicate instability."
                    },
                    {
                        "label": "DNSSEC / privacy",
                        "value": "DNSSEC off · privacy off",
                        "tone": "caution",
                        "detail": "DNSSEC strengthens DNS trust; privacy is neutral on its own."
                    }
                ]
            },
            {
                "title": "Reputation & search evidence",
                "items": [
                    {
                        "label": "Backlinks",
                        "value": "3",
                        "tone": "unknown",
                        "detail": "Broader backlink evidence usually improves confidence."
                    },
                    {
                        "label": "Referring domains",
                        "value": "3",
                        "tone": "unknown",
                        "detail": "Unique linking domains are more useful than raw link volume."
                    },
                    {
                        "label": "Organic keywords",
                        "value": "60",
                        "tone": "caution",
                        "detail": "Search footprint helps distinguish real sites from thin shells."
                    },
                    {
                        "label": "Indexed pages",
                        "value": "10",
                        "tone": "caution",
                        "detail": "Larger index coverage usually means more evidence to classify from."
                    },
                    {
                        "label": "Brand strength",
                        "value": "41/100",
                        "tone": "caution",
                        "detail": "Stronger brand signals reduce false positives for legitimate sites."
                    },
                    {
                        "label": "Risk label",
                        "value": "GOOD",
                        "tone": "unknown",
                        "detail": "This is the raw crawl / heuristic risk label feeding the tag model."
                    }
                ]
            },
            {
                "title": "Crawl, content & technicals",
                "items": [
                    {
                        "label": "HTTP status",
                        "value": "200",
                        "tone": "good",
                        "detail": "Healthy responses make classification more reliable."
                    },
                    {
                        "label": "HTTPS / speed",
                        "value": "HTTPS OK · 1,148 ms",
                        "tone": "good",
                        "detail": "Slow or broken technical signals weaken confidence."
                    },
                    {
                        "label": "Content words",
                        "value": "215",
                        "tone": "caution",
                        "detail": "Thin pages are harder to trust and easier to manipulate."
                    },
                    {
                        "label": "Schema / structure",
                        "value": "0 schema · no meta · H1",
                        "tone": "caution",
                        "detail": "Structured markup and basic on-page hygiene improve quality confidence."
                    },
                    {
                        "label": "Links on page",
                        "value": "6 internal · 6 external",
                        "tone": "good",
                        "detail": "Link patterns help detect thin directories and promo pages."
                    },
                    {
                        "label": "Page speed / mobile",
                        "value": "69/100 · 64/100",
                        "tone": "good",
                        "detail": "Better technical quality generally reduces low-effort site patterns."
                    },
                    {
                        "label": "Crawl access",
                        "value": "Open",
                        "tone": "good",
                        "detail": "The crawler reached the site without an anti-bot challenge."
                    }
                ]
            },
            {
                "title": "External evidence & explainability",
                "items": [
                    {
                        "label": "Decision state",
                        "value": "Inconclusive",
                        "tone": "unknown",
                        "detail": "Structured third-party evidence is still too thin, mixed, or unqualified to force a harder verdict."
                    },
                    {
                        "label": "Evidence quality",
                        "value": "Low",
                        "tone": "unknown",
                        "detail": "Blends source trust, domain matching, evidence diversity, and freshness."
                    },
                    {
                        "label": "Support vs contradiction",
                        "value": "0 / 0",
                        "tone": "unknown",
                        "detail": "Compares how much structured external evidence supports the candidate tag against evidence that contradicts it."
                    },
                    {
                        "label": "Qualified risk sources",
                        "value": "No",
                        "tone": "good",
                        "detail": "Risk tags only promote from external evidence when source diversity or source trust thresholds are met."
                    },
                    {
                        "label": "Uncertainty buffer",
                        "value": "Clear",
                        "tone": "good",
                        "detail": "Prevents thin or mixed external evidence from forcing a stronger tag than the evidence can justify."
                    }
                ]
            }
        ],
        "positives": [
            "Healthy crawl quality and on-page completeness."
        ],
        "risks": []
    },
    "traffic_confidence": 39,
    "whois": {
        "current": null,
        "history": [],
        "signals": []
    },
    "discovered_domain": {
        "id": 75178,
        "domain": "geek.nz",
        "first_seen_at": "2026-03-15 19:50:51",
        "last_crawled_at": "2026-03-17 07:39:59",
        "last_title": "Adrian Lyall Cochrane",
        "last_http_status": 200,
        "discovered_from_domain": "tombrandis.uk",
        "depth": 0,
        "backlinks_count": 2,
        "rating_cache": 49,
        "spam_score": 24,
        "risk_label": "good",
        "category_name": "Developer Tools: APIs & Documentation",
        "primary_country_code": "NZ",
        "internal_links_count": 6,
        "external_links_count": 6,
        "social_profiles_count": 0,
        "content_word_count": 215,
        "title_quality_score": 93,
        "has_meta_description": 0,
        "has_h1": 1,
        "language_code": "",
        "response_time_ms": 1148,
        "robots_status": 200,
        "sitemap_status": 200,
        "sitemap_total_urls": 10,
        "quality_score": 68,
        "site_name": "",
        "canonical_domain": "",
        "favicon_present": 0,
        "schema_org_count": 0,
        "noindex_detected": 0,
        "feed_links_count": 0,
        "https_working": 1,
        "estimated_authority_score": 20,
        "trust_score": 73,
        "nsfw_score": 0,
        "overall_rank_estimate": 11501,
        "primary_tag": "",
        "tag_codes": "",
        "manual_verified_status": "",
        "manual_tag_codes": "",
        "manual_rating_delta": 0,
        "manual_authority_delta": 0,
        "manual_trust_delta": 0,
        "manual_note": null,
        "manual_adjusted_by": null,
        "manual_adjusted_at": null,
        "manual_lock_scores": 0,
        "manual_lock_flags": 0,
        "crawl_blocked": 0,
        "crawl_blocked_by": "",
        "crawl_blocked_reason": null,
        "safety_score": 100,
        "fraud_score": 0,
        "legitimacy_score": 47,
        "infrastructure_risk_score": 0,
        "score_confidence": 99,
        "tag_confidence": 71,
        "category_confidence": 18,
        "deep_crawl_pages": 50,
        "resolved_ip": "103.224.131.53",
        "category_candidates_json": "[{\"category\":\"Developer Tools: APIs & Documentation\",\"score\":6},{\"category\":\"Technology: Hardware & Electronics\",\"score\":6}]",
        "page_signals_json": "[{\"path\":\"/docs\",\"status\":200,\"title\":\"\\\"How does this software work?\\\" by Adrian Cochrane\",\"word_count\":600,\"summary_text\":\"\\\"How does this software work?\\\" by Adrian Cochrane \\\"How does this software work?\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} How does this software work? One of the vital freedoms of software freedom is that of studying the software you use. I enjoy exercising this freedom, learning the bigger-picture of my software works and gaining more confidence it's not\",\"classification_terms\":[\"docs\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/docs.html\",\"status\":200,\"title\":\"\\\"How does this software work?\\\" by Adrian Cochrane\",\"word_count\":600,\"summary_text\":\"\\\"How does this software work?\\\" by Adrian Cochrane \\\"How does this software work?\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} How does this software work? One of the vital freedoms of software freedom is that of studying the software you use. I enjoy exercising this freedom, learning the bigger-picture of my software works and gaining more confidence it's not\",\"classification_terms\":[\"docs.html\",\"docs\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/from-scratch\",\"status\":200,\"title\":\"\\\"Computing From Scratch\\\" by Adrian Cochrane\",\"word_count\":1766,\"summary_text\":\"\\\"Computing From Scratch\\\" by Adrian Cochrane \\\"Computing From Scratch\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 10 July 2025 Adrian Cochrane Computing From Scratch These hypotheticals hope to teach the fundamentals of computing. They are not real projects I actually want to build, but I do enjoy toying with these ideas. Audio Basics Quick tour of what’\",\"classification_terms\":[\"from-scratch\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/movies.html\",\"status\":200,\"title\":\"Movie/Shows Recommendations\",\"word_count\":104,\"summary_text\":\"Movie/Shows Recommendations Movie/Shows Recommendations DRM-Free Movie/Shows Recommendations This is a list of high-quality fictional movies and (audio) shows you're free to download to enjoy whenever, wherever, & however you want. I've personally enjoyed every single one of these, and I hope you do too! Other lists Andrew Roach's public domain list Reel House distributes a wide range of (mostly) DRM-free movies. Pixel's audio show list Please check copyright licenses before redistributing these too widely. Recommend Me a Show! Title Official site Other comments? Distribution Digital download(s), possibly paywalled, viewable in any media player RSS/Atom podcast Both What is the Red Panda's Secret Identity? (anti-spam) Add Webmention\",\"classification_terms\":[\"movies.html\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/fossbros\",\"status\":200,\"title\":\"\\\"On FOSSBros\\\" by Adrian Cochrane\",\"word_count\":852,\"summary_text\":\"\\\"On FOSSBros\\\" by Adrian Cochrane \\\"On FOSSBros\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} On FOSSBros Free and OpenSource Software (FOSS) has by now become a bigtent ideology, filled with different perspectives on what it means. Which I think is great, it’s a component of success! However I think some of the more vocal subcommunities are tox\",\"classification_terms\":[\"fossbros\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/adrian@openwork.nz-(0x69AD51EB9FB61E99)-public.asc\",\"status\":200,\"title\":\"\",\"word_count\":48,\"summary_text\":\"-----BEGIN PGP PUBLIC KEY BLOCK----- xsDNBGNwN/0BDAC9MVXGstsm+/Zzf1jtZVNSfIsUjAwwbQyXNoTDxqjF6URfvfmx 4+30v07z0lve2SODBA5CtkeJCY+owxqTI9t8Oecg3y6xmjV76YrJJOn9p03OA5tm YQOVlW29VuudD5Zp9jvZVnzdAR/RUprGfe9XFwlQOYgnOJV2xvh14ekR2Q2rfkd3 s6vZGV+ReA3hi0W76ABEc/0AvZSqTAuumheelSlyhH0ha/x1I5HcmyywKw7u1o8H J1TWS4uy9UjqNljWk5WZi9Xtpt/4O6nsYylg/upE4oMYVLZdwfinXmG6WxqlT6Fi jSn4SWREWNKm/CiKupHQ9UUxv4xCziXRn0W5wgs9PLd86IrepYca7AxeFi2rSOs0 L18si4KLFv7w7WK64I4MQ3dBgyusW5Qnq2NrkDGm/RNxNqvuVs3bjgEdhNmw7Hye nntpxoyliieR5P3HhILZmZb/3nKvjVUCVJOGsLWwrDycUwahPkfCceHBWhOyYCwl 4AjX5Uxnr7JPbuUAEQEAAc0qQWRyaWFuIEx5YWxsIENvY2hyYW5lIDxhZHJpYW5A b3Blbndvcmsubno+wsENBBMBCAA3FiEEF3N15YeAqNn6d6fTaa1R65+2HpkFAmNw N/8FCQWjmoACGwMECwkIBwUVCAkKCwUWAgMBAAAKCRBprVHrn7Yemdh5DACtFq6D KJzJhwQaMEMFU/eDlqIT/lBjBTU5kL6GEaqjzj1QAh2kgK0t\",\"classification_terms\":[\"adrian@openwork.nz-(0x69AD51EB9FB61E99)-public.asc\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/docs.atom\",\"status\":200,\"title\":\"How Does This Software Work?\",\"word_count\":5886,\"summary_text\":\"How Does This Software Work? How Does This Software Work? Sat, 01 Nov 2025 12:16:03 +1300 Adrian Cochrane alcinnz@lavabit.com GNU LibC (Core Libraries) Wed, 19 Jan 2022 12:48:27 +1300 GNU LibC, following the POSIX standards, are the most fundamental libraries on most UNIX-like systems today. Allowing for I/O, memory allocation, filesystem manipulation, etc. Put simply, it’s primary job is to abstract away the datastructures exposed by both Linux, central config files, GCC, &amp; the underlying CPU. Formatting Commands Tue, 30 Aug 2022 20:58:58 +1200 Some of UNIX’s core commands serve to reformat text, and other data, into something nicer to work with. These tend to involve more computational logic of their own. Encoding Commands Wed, 04 Jan 2023 08:17:02 +1300 Encoding refers to all the numerous arbitrary decisions re\",\"classification_terms\":[\"docs.atom\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/appstream.html\",\"status\":200,\"title\":\"\\\"AppStream & libappstream\\\" by Adrian Cochrane\",\"word_count\":359,\"summary_text\":\"\\\"AppStream & libappstream\\\" by Adrian Cochrane \\\"AppStream &amp; libappstream\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane AppStream &amp; libappstream NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. AppStream is a new standard from FreeDesktop.Org for an offline XML/YAML\",\"classification_terms\":[\"docs/appstream.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/certificates-gcr.html\",\"status\":200,\"title\":\"\\\"Cryptographic certificates in WebKit & GCR\\\" by Adrian Cochrane\",\"word_count\":470,\"summary_text\":\"\\\"Cryptographic certificates in WebKit & GCR\\\" by Adrian Cochrane \\\"Cryptographic certificates in WebKit &amp; GCR\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} Cryptographic certificates in WebKit &amp; GCR One important security feature of a web browser is to allow you to review the cryptographic certificates of the pages you visit. So tonight I will be describing how WebKit\",\"classification_terms\":[\"docs/certificates-gcr.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/cmusphinx.html\",\"status\":200,\"title\":\"\\\"CMU Sphinx\\\" by Adrian Cochrane\",\"word_count\":1792,\"summary_text\":\"\\\"CMU Sphinx\\\" by Adrian Cochrane \\\"CMU Sphinx\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} CMU Sphinx Tonight I wish to start studying how CMU Sphinx works in reference to their hello world app from their getting started tutorial. Specifically I’ll describe PocketSphinx’s cmd_ln_init &amp; cmd_ln_free_r functions, leaving the 5 other PocketSph\",\"classification_terms\":[\"docs/cmusphinx.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/dvd.html\",\"status\":200,\"title\":\"\\\"DVDs & CDs\\\" by Adrian Cochrane\",\"word_count\":1749,\"summary_text\":\"\\\"DVDs & CDs\\\" by Adrian Cochrane \\\"DVDs &amp; CDs\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 29 May 2022 Adrian Cochrane DVDs &amp; CDs CDs CDs are hand-sized disks storing digital audio in their physical microscopic structure (caveats later), aiming to be resilient to scratches and other ways routine handling can damage their data. Here I’l\",\"classification_terms\":[\"docs/dvd.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/computing.html\",\"status\":200,\"title\":\"\\\"Fundamentals of Computers & Programming\\\" by Adrian Cochrane\",\"word_count\":3756,\"summary_text\":\"\\\"Fundamentals of Computers & Programming\\\" by Adrian Cochrane \\\"Fundamentals of Computers &amp; Programming\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 05 June 2022 Adrian Cochrane Fundamentals of Computers &amp; Programming This morning I’m tempted to describe the basic theory of how computers run programs, but first what is a program or a computer? They are instruction\",\"classification_terms\":[\"docs/computing.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/espeak.html\",\"status\":200,\"title\":\"\\\"eSpeak\\\" by Adrian Cochrane\",\"word_count\":495,\"summary_text\":\"\\\"eSpeak\\\" by Adrian Cochrane \\\"eSpeak\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} eSpeak I’ve been studying eSpeak NG (in preparation for building a browser around it (and later Julius). eSpeak is a commandline tool and C library for converting text to speech, either outputting wavefiles or playing them through your speakers. I certainly\",\"classification_terms\":[\"docs/espeak.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/html-xml-utils.html\",\"status\":200,\"title\":\"\\\"hx-wls & HTML-XML-Utils\\\" by Adrian Cochrane\",\"word_count\":266,\"summary_text\":\"\\\"hx-wls & HTML-XML-Utils\\\" by Adrian Cochrane \\\"hx-wls &amp; HTML-XML-Utils\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane hx-wls &amp; HTML-XML-Utils NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. The first thing Odysseus does in order to autodiscover any webfeeds on the\",\"classification_terms\":[\"docs/html-xml-utils.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/jekyll.html\",\"status\":200,\"title\":\"\\\"Jekyll static site generator\\\" by Adrian Cochrane\",\"word_count\":1716,\"summary_text\":\"\\\"Jekyll static site generator\\\" by Adrian Cochrane \\\"Jekyll static site generator\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 16 April 2021 Adrian Cochrane Jekyll static site generator Static Site Generators (SSGs), which have arguably been popularised by Github’s integration of Jekyll into Github Pages, have become dominant over the past decade. I continued u\",\"classification_terms\":[\"docs/jekyll.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/json-glib.html\",\"status\":200,\"title\":\"\\\"json-glib\\\" by Adrian Cochrane\",\"word_count\":421,\"summary_text\":\"\\\"json-glib\\\" by Adrian Cochrane \\\"json-glib\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} json-glib This morning I described libxml2 which Odysseus uses to parse webfeeds, via a needed abstraction (to handle RSS’s slight messiness and Atom’s power) binding it to Odysseus’s templating language. This evening I’ll cover the other parser I’ve impl\",\"classification_terms\":[\"docs/json-glib.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/libsoup.html\",\"status\":200,\"title\":\"\\\"libsoup: GNOME's HTTP library\\\" by Adrian Cochrane\",\"word_count\":252,\"summary_text\":\"\\\"libsoup: GNOME's HTTP library\\\" by Adrian Cochrane \\\"libsoup: GNOME&apos;s HTTP library\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane libsoup: GNOME&apos;s HTTP library NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. LibSoup is the HTTP library which integrates into the GLib ma\",\"classification_terms\":[\"docs/libsoup.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/libxml2.html\",\"status\":200,\"title\":\"\\\"libxml2\\\" by Adrian Cochrane\",\"word_count\":351,\"summary_text\":\"\\\"libxml2\\\" by Adrian Cochrane \\\"libxml2\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} libxml2 Recently I’ve been describing the APIs I call (possibly via Vala’s syntactic sugar) to implement the core of Odysseus’s templating language. Now I want to describe some of the parsers I wrap around it’s datamodel. So for the sake of rendering webfee\",\"classification_terms\":[\"docs/libxml2.html\",\"docs\",\"api\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/odysseus-templating.html\",\"status\":200,\"title\":\"\\\"Odysseus \\\"Prosody\\\" templating\\\" by Adrian Cochrane\",\"word_count\":1178,\"summary_text\":\"\\\"Odysseus \\\"Prosody\\\" templating\\\" by Adrian Cochrane \\\"Odysseus &quot;Prosody&quot; templating\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} Odysseus &quot;Prosody&quot; templating While usually I focus on describing code written by other people that I call, today I’m tempted to describe how some of my own software works. For Odysseus I implemented my own very pow\",\"classification_terms\":[\"docs/odysseus-templating.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/readability.html\",\"status\":200,\"title\":\"\\\"Mozilla Readability\\\" by Adrian Cochrane\",\"word_count\":516,\"summary_text\":\"\\\"Mozilla Readability\\\" by Adrian Cochrane \\\"Mozilla Readability\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} Mozilla Readability Thanks to @bleakgrey@mastodon.social (and I think I recall someone else being involved), a new Odysseus release is coming out soon support a “reader mode”. I find it rediculous I feel need to support this feature, it’s saying\",\"classification_terms\":[\"docs/readability.html\",\"support\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/sqlite3-fts5.html\",\"status\":200,\"title\":\"\\\"SQLite3 Full Text Search 5\\\" by Adrian Cochrane\",\"word_count\":605,\"summary_text\":\"\\\"SQLite3 Full Text Search 5\\\" by Adrian Cochrane \\\"SQLite3 Full Text Search 5\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane SQLite3 Full Text Search 5 NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. You can free-text search your Odysseus browser history using a simple form on\",\"classification_terms\":[\"docs/sqlite3-fts5.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/sqlite3-ngqp.html\",\"status\":200,\"title\":\"\\\"SQLite3 Next Generation Query Planner\\\" by Adrian Cochrane\",\"word_count\":383,\"summary_text\":\"\\\"SQLite3 Next Generation Query Planner\\\" by Adrian Cochrane \\\"SQLite3 Next Generation Query Planner\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane SQLite3 Next Generation Query Planner NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. To make it faster to query on certain columns SQLite3 a\",\"classification_terms\":[\"docs/sqlite3-ngqp.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/sqlite3.html\",\"status\":200,\"title\":\"\\\"SQLite3\\\" by Adrian Cochrane\",\"word_count\":1031,\"summary_text\":\"\\\"SQLite3\\\" by Adrian Cochrane \\\"SQLite3\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane SQLite3 NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. SQLite3, possibly the most widely deployed database, is used by Odysseus to persist all your browser data. It is al\",\"classification_terms\":[\"docs/sqlite3.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/voice2json.html\",\"status\":200,\"title\":\"\\\"Voice2JSON\\\" by Adrian Cochrane\",\"word_count\":2586,\"summary_text\":\"\\\"Voice2JSON\\\" by Adrian Cochrane \\\"Voice2JSON\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 11 June 2021 Adrian Cochrane Voice2JSON My Rhapsode auditory web browser relies upon Voice2JSON for a high-level voice-to-speech recognition engine. This page describes how Voice2JSON &amp; several of it’s underlying tools works. While Voice2JSON shares\",\"classification_terms\":[\"docs/voice2json.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/varvara.html\",\"status\":200,\"title\":\"\\\"Hypothetical UXN & Varvara Hardware\\\" by Adrian Cochrane\",\"word_count\":1236,\"summary_text\":\"\\\"Hypothetical UXN & Varvara Hardware\\\" by Adrian Cochrane \\\"Hypothetical UXN &amp; Varvara Hardware\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 29 May 2022 Adrian Cochrane Hypothetical UXN &amp; Varvara Hardware I know that 100 Rabbits specifically says there’s no intention to design bespoke hardware for UXN or Varvara, but I’ll design hypothetical hardware for it. U\",\"classification_terms\":[\"docs/varvara.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/docs/web-cpu-hypothetical.html\",\"status\":200,\"title\":\"\\\"Hypothetical Special-purpose Web Processors\\\" by Adrian Cochrane\",\"word_count\":3389,\"summary_text\":\"\\\"Hypothetical Special-purpose Web Processors\\\" by Adrian Cochrane \\\"Hypothetical Special-purpose Web Processors\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 02 June 2022 Adrian Cochrane Hypothetical Special-purpose Web Processors A thought experiment I find interesting is: How would I design special-purpose hardware specifically to run web browsers like the ones I’m implement\",\"classification_terms\":[\"docs/web-cpu-hypothetical.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/DBus.html\",\"status\":200,\"title\":\"\\\"DBus on GNOME\\\" by Adrian Cochrane\",\"word_count\":814,\"summary_text\":\"\\\"DBus on GNOME\\\" by Adrian Cochrane \\\"DBus on GNOME\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} DBus on GNOME GIO/GLib (client) Odysseus uses the DBus IPC/RPC protocol to add a progress bar to it’s dock icon (on the Pantheon or the late Unity desktops), issue notifications, and possibly open links (though that can be done through commandline arg\",\"classification_terms\":[\"gtk_stack_docs/DBus.html\",\"docs\",\"links\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/GMarkup.html\",\"status\":200,\"title\":\"\\\"GLib GMarkup\\\" by Adrian Cochrane\",\"word_count\":152,\"summary_text\":\"\\\"GLib GMarkup\\\" by Adrian Cochrane \\\"GLib GMarkup\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane GLib GMarkup NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. GLib provides it’s own bare bones XML parser, that Odysseus uses to titles and attached file types out of\",\"classification_terms\":[\"gtk_stack_docs/GMarkup.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/GtkLabel.html\",\"status\":200,\"title\":\"\\\"GtkLabel\\\" by Adrian Cochrane\",\"word_count\":271,\"summary_text\":\"\\\"GtkLabel\\\" by Adrian Cochrane \\\"GtkLabel\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GtkLabel Within Odysseus’s addressbar popups I make extensive use of (styled) GtkLabel widgets, and GTK’s tooltips and menu options also uses it for much of their rendering. So this morning I’ll discuss how GtkLabel works in GTK3, though it’ll mostly hand\",\"classification_terms\":[\"gtk_stack_docs/GtkLabel.html\",\"address\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/application-mainloop.html\",\"status\":200,\"title\":\"\\\"GIO GApplication & GLib GMainloop\\\" by Adrian Cochrane\",\"word_count\":177,\"summary_text\":\"\\\"GIO GApplication & GLib GMainloop\\\" by Adrian Cochrane \\\"GIO GApplication &amp; GLib GMainloop\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane GIO GApplication &amp; GLib GMainloop NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. GIO’s GApplication is basically a wrapper around GLib’s\",\"classification_terms\":[\"gtk_stack_docs/application-mainloop.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/css.html\",\"status\":200,\"title\":\"\\\"CSS\\\" by Adrian Cochrane\",\"word_count\":780,\"summary_text\":\"\\\"CSS\\\" by Adrian Cochrane \\\"CSS\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} CSS aside {border-left: thick dashed #f90; padding: 20px} Gtk’s CSS engine is dispatched to to render nearly all of an app’s UI, but Odysseus only calls it directly to make it’s “status buttons” look like they’re inside the rightside “addressbar”. These status\",\"classification_terms\":[\"gtk_stack_docs/css.html\",\"address\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/desktop-entry-lookup.html\",\"status\":200,\"title\":\"\\\"GIO app lookup\\\" by Adrian Cochrane\",\"word_count\":309,\"summary_text\":\"\\\"GIO app lookup\\\" by Adrian Cochrane \\\"GIO app lookup\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane GIO app lookup NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. This is how Odysseus finds all your installed feedreaders, or opens your non-HTTP URIs and non-HTML d\",\"classification_terms\":[\"gtk_stack_docs/desktop-entry-lookup.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/focus.html\",\"status\":200,\"title\":\"\\\"keyboard focus in GTK & WebKit\\\" by Adrian Cochrane\",\"word_count\":200,\"summary_text\":\"\\\"keyboard focus in GTK & WebKit\\\" by Adrian Cochrane \\\"keyboard focus in GTK &amp; WebKit\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane keyboard focus in GTK &amp; WebKit NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. The concept of a keyboard-focused widget is little more than\",\"classification_terms\":[\"gtk_stack_docs/focus.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gdkpixbuf-rsvg.html\",\"status\":200,\"title\":\"\\\"GDK Pixbuf & librsvg\\\" by Adrian Cochrane\",\"word_count\":230,\"summary_text\":\"\\\"GDK Pixbuf & librsvg\\\" by Adrian Cochrane \\\"GDK Pixbuf &amp; librsvg\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane GDK Pixbuf &amp; librsvg NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. GDK Pixbuf serves to dispatch parsing image files (in chunks) to various underlyi\",\"classification_terms\":[\"gtk_stack_docs/gdkpixbuf-rsvg.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gerror-gtask.html\",\"status\":200,\"title\":\"\\\"GLib GError & GIO GTask\\\" by Adrian Cochrane\",\"word_count\":639,\"summary_text\":\"\\\"GLib GError & GIO GTask\\\" by Adrian Cochrane \\\"GLib GError &amp; GIO GTask\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GLib GError &amp; GIO GTask GLib GError Odysseus uses GLib’s GError to report syntax errors for it’s templates before rendering it via a different template (which yes, means I need to error handle my error handling). It’s a simple C stru\",\"classification_terms\":[\"gtk_stack_docs/gerror-gtask.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gio-gcontenttype.html\",\"status\":200,\"title\":\"\\\"GIO GContentType\\\" by Adrian Cochrane\",\"word_count\":454,\"summary_text\":\"\\\"GIO GContentType\\\" by Adrian Cochrane \\\"GIO GContentType\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GIO GContentType When downloading a file in Odysseus, it shows you an icon for the server-specified MIMEtype with a tooltip showing it’s human readable name. This is looked up from an XML database maintained by FreeDesktop.Org with patches optional\",\"classification_terms\":[\"gtk_stack_docs/gio-gcontenttype.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/glib-utils.html\",\"status\":200,\"title\":\"\\\"Simple GLib utils\\\" by Adrian Cochrane\",\"word_count\":167,\"summary_text\":\"\\\"Simple GLib utils\\\" by Adrian Cochrane \\\"Simple GLib utils\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} Simple GLib utils GRandom I show a random “tip” in the footer of Odysseus’s homepage, in order to teach people how to use Odysseus better. So this morning I’ll describe the GLib’s pseudorandom number generator. I don’t really understand this, but\",\"classification_terms\":[\"gtk_stack_docs/glib-utils.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gobject-methods.html\",\"status\":200,\"title\":\"\\\"GObject method calls\\\" by Adrian Cochrane\",\"word_count\":310,\"summary_text\":\"\\\"GObject method calls\\\" by Adrian Cochrane \\\"GObject method calls\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GObject method calls Last night I described how I used Gee.HashMap to dispatch to the correct parser for Odysseus’s templating language. This morning I’ll describe how I use GObject’s interfaces to dispatch to the correct method. I also use it\",\"classification_terms\":[\"gtk_stack_docs/gobject-methods.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gresource.html\",\"status\":200,\"title\":\"\\\"GResource\\\" by Adrian Cochrane\",\"word_count\":578,\"summary_text\":\"\\\"GResource\\\" by Adrian Cochrane \\\"GResource\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GResource GResource is a tool that compiles files (external to the source code) into your app’s executable. By doing so it significantly cuts down on kernel calls, merging it all into the same mmap operations performed by exec(). Swapping it in from the f\",\"classification_terms\":[\"gtk_stack_docs/gresource.html\",\"docs\",\"source code\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtk-buttons.html\",\"status\":200,\"title\":\"\\\"Buttons, Images, & Tooltips\\\" by Adrian Cochrane\",\"word_count\":283,\"summary_text\":\"\\\"Buttons, Images, & Tooltips\\\" by Adrian Cochrane \\\"Buttons, Images, &amp; Tooltips\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} Buttons, Images, &amp; Tooltips The dominant items in a toolbar/headerbar are the buttons, and this is no different for Odysseus. These are rendered as images which you can click, or you can hover over it to be told what it does. All\",\"classification_terms\":[\"gtk_stack_docs/gtk-buttons.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtk-headerbar.html\",\"status\":200,\"title\":\"\\\"HeaderBars & layout\\\" by Adrian Cochrane\",\"word_count\":324,\"summary_text\":\"\\\"HeaderBars & layout\\\" by Adrian Cochrane \\\"HeaderBars &amp; layout\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane HeaderBars &amp; layout NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. Most browsers, as well as just about any GNOME3 or elementary app, have moved to co\",\"classification_terms\":[\"gtk_stack_docs/gtk-headerbar.html\",\"about\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtk-menus.html\",\"status\":200,\"title\":\"\\\"Menus\\\" by Adrian Cochrane\",\"word_count\":271,\"summary_text\":\"\\\"Menus\\\" by Adrian Cochrane \\\"Menus\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} Menus Odysseus’s headerbar includes dropdown menus triggered by holdclick or rightclick on any toolbar button, thereby making this combined toolbar/titlebar also a menubar. Though the “application menu” also shows this menu on left click, to show lesser used\",\"classification_terms\":[\"gtk_stack_docs/gtk-menus.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtk-windows.html\",\"status\":200,\"title\":\"\\\"GTK Overview & Windowing\\\" by Adrian Cochrane\",\"word_count\":567,\"summary_text\":\"\\\"GTK Overview & Windowing\\\" by Adrian Cochrane \\\"GTK Overview &amp; Windowing\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GTK Overview &amp; Windowing For the last chunk describing how Odysseus’s dependencies work, I’ll cover how it’s basic UI is built up around WebKit2GTK. And to start I’ll cover how GTK renders a window onscreen. Please note that’ll be d\",\"classification_terms\":[\"gtk_stack_docs/gtk-windows.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtkentry.html\",\"status\":200,\"title\":\"\\\"GtkEntry\\\" by Adrian Cochrane\",\"word_count\":380,\"summary_text\":\"\\\"GtkEntry\\\" by Adrian Cochrane \\\"GtkEntry\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GtkEntry The main component in Odysseus’s “headerbar” the “addressbar”, which is basically just a GtkEntry. This afternoon I want to describe how it works. GtkEntry does include a few “CSS gadgets” I make good use of in Odysseus, including a background pro\",\"classification_terms\":[\"gtk_stack_docs/gtkentry.html\",\"address\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtkflowbox.html\",\"status\":200,\"title\":\"\\\"GtkFlowBox\\\" by Adrian Cochrane\",\"word_count\":205,\"summary_text\":\"\\\"GtkFlowBox\\\" by Adrian Cochrane \\\"GtkFlowBox\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GtkFlowBox Odysseus renders it’s downloads, when present, along the bottom of it’s window, wrapping them as to as many lines as needed. This is achieved using a GtkFlowBox, which I’ll be describing this morning. Much of the code strongly resembles GtkLis\",\"classification_terms\":[\"gtk_stack_docs/gtkflowbox.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtkgrid.html\",\"status\":200,\"title\":\"\\\"GtkGrid\\\" by Adrian Cochrane\",\"word_count\":349,\"summary_text\":\"\\\"GtkGrid\\\" by Adrian Cochrane \\\"GtkGrid\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GtkGrid GTK’s main layout component is the GtkGrid widget, which roughly corresponds to CSS grids &amp; flexboxes (for the latter Gtk used to have GtkBox, but they found GtkGrid filled the need). And I got a fair bit of interest when a mentioned this the ot\",\"classification_terms\":[\"gtk_stack_docs/gtkgrid.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtklistbox.html\",\"status\":200,\"title\":\"\\\"GtkListBox\\\" by Adrian Cochrane\",\"word_count\":283,\"summary_text\":\"\\\"GtkListBox\\\" by Adrian Cochrane \\\"GtkListBox\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GtkListBox When you type something in Odysseus’s addressbar, it will autocomplete to a web address. By implying https:// and querying your browser history or maybe DuckDuckGo. GTK does have a built in autocompletion widget, but I find myself needing to i\",\"classification_terms\":[\"gtk_stack_docs/gtklistbox.html\",\"address\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/gtkpopover.html\",\"status\":200,\"title\":\"\\\"GtkPopover\\\" by Adrian Cochrane\",\"word_count\":233,\"summary_text\":\"\\\"GtkPopover\\\" by Adrian Cochrane \\\"GtkPopover\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} GtkPopover Odysseus’s “status icons” are all associated with a popover, even if that popover just displays what was going to show up in it’s tooltip. And forthermore I use a popover to autocomplete whatever you type in the addressbar. (Yes GTK has a widg\",\"classification_terms\":[\"gtk_stack_docs/gtkpopover.html\",\"address\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/icon-theme.html\",\"status\":200,\"title\":\"\\\"GTK Icon Themes\\\" by Adrian Cochrane\",\"word_count\":251,\"summary_text\":\"\\\"GTK Icon Themes\\\" by Adrian Cochrane \\\"GTK Icon Themes\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} 01 November 2025 Adrian Cochrane GTK Icon Themes NOTE: This page is a recollection of what I've written previously. I do not guarantee it's accuracy. While GIO does provide a means of referencing icons for the sake of filetypes and apps, it’s GTK wh\",\"classification_terms\":[\"gtk_stack_docs/icon-theme.html\",\"docs\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/gtk_stack_docs/libgee.html\",\"status\":200,\"title\":\"\\\"Vala's LibGee\\\" by Adrian Cochrane\",\"word_count\":359,\"summary_text\":\"\\\"Vala's LibGee\\\" by Adrian Cochrane \\\"Vala&apos;s LibGee\\\" by Adrian Cochrane @import url('/solarized-light.css'); body {font-family: sans-serif; color: #111; background: white;} h1, h2, h3, h4, h5, h6 { border-top: thin dashed #ddd; color: #b50; clear: both; } a:link {color: #b50; font-weight: bold;} body > main {max-width: 800px; margin: 0 auto;} hr {border: none; border-top: thin dashed #aaa;} aside {float: right; color: #888;} dt {margin-top: 8px;} img {float: left; max-width: 25%} figure {float: left; max-width: 25%} figure img {float: none; max-width: 100%} .right {float: right} Vala&apos;s LibGee Tonight I want to cover Vala’s collections library “libgee”. Like just about any non-trivial code I make good use of this to parse Odysseus’s templates, and sometimes to underly it’s data model. It’s pretty much CompSci 102, so\",\"classification_terms\":[\"gtk_stack_docs/libgee.html\",\"about\",\"docs\"],\"external_refs\":[],\"depth\":2}]",
        "score_reasons_json": "[]",
        "route_domain": "geek.nz",
        "display_domain": "geek.nz"
    },
    "explainability": {
        "summary": "geek.nz currently scores 64/100. The score is being shaped by a mixed signal profile rather than one dominant factor. Evidence confidence is strong enough for a relatively stable read. This is an estimated profile rather than a manually tracked one. Crawler access looks clean.",
        "badges": [
            {
                "label": "Profile",
                "value": "Estimated profile",
                "tone": "unknown",
                "detail": null
            },
            {
                "label": "Evidence confidence",
                "value": "High confidence",
                "tone": "good",
                "detail": "99/100"
            },
            {
                "label": "Traffic confidence",
                "value": "Low confidence",
                "tone": "risk",
                "detail": "39/100"
            },
            {
                "label": "Crawler access",
                "value": "Clean visibility",
                "tone": "good",
                "detail": null
            }
        ],
        "weighted_contributions": [
            {
                "label": "Quality system",
                "points": "+26.5",
                "tone": "good",
                "detail": "Technical quality, crawl depth, page structure, and implementation hygiene. Current subsystem score: 78/100."
            },
            {
                "label": "Reputation system",
                "points": "+10.9",
                "tone": "risk",
                "detail": "Authority, search visibility, reach, engagement, and registry stability. Current subsystem score: 32/100."
            },
            {
                "label": "Safety system",
                "points": "+32.0",
                "tone": "good",
                "detail": "Fraud, spam, and trust signals from infrastructure, crawl, and registry evidence. Current subsystem score: 100/100."
            },
            {
                "label": "Risk clamp",
                "points": "-5.0",
                "tone": "risk",
                "detail": "Safety thresholds capped the final score until the risk profile improves."
            }
        ],
        "evidence_cards": [
            {
                "label": "Authority and trust",
                "value": "23/100 · trust 36/100",
                "tone": "risk",
                "detail": "104 monthly visitors, 60 organic keywords, brand completeness 41/100, engagement 79/100."
            },
            {
                "label": "Backlink and search evidence",
                "value": "3 referring domains",
                "tone": "good",
                "detail": "3 backlinks across 3 referring domains. Diversity 94/100; spam penalty 0."
            },
            {
                "label": "Registry and domain stability",
                "value": "0.0 years old",
                "tone": "risk",
                "detail": "Stability 0/100 · age 0.0 years."
            },
            {
                "label": "Safety and fraud posture",
                "value": "Safety 100/100 · fraud 0/100",
                "tone": "good",
                "detail": "Primary tag Uncertain · safety 100/100 · fraud 0/100."
            }
        ],
        "positives": [
            "Healthy crawl quality and on-page completeness.",
            "HTTPS is working, so the site clears a basic transport-security check.",
            "Backlink diversity looks broad enough to strengthen authority confidence."
        ],
        "risks": [
            "Traffic and reach estimates are still low confidence, so commercial scale signals may move after more evidence is collected."
        ],
        "freshness": [
            {
                "label": "Crawl evidence",
                "value": "2026-03-17 07:39:59",
                "tone": "risk",
                "detail": "Crawl and page content sample. Age: 1mo ago."
            },
            {
                "label": "WHOIS snapshot",
                "value": "Not captured yet",
                "tone": "unknown",
                "detail": "Registry profile and stability signals."
            },
            {
                "label": "Keyword view",
                "value": "2026-04-17 11:49:23",
                "tone": "good",
                "detail": "Estimated visibility until tracked keyword snapshots exist. Age: 0s ago."
            },
            {
                "label": "Rank history",
                "value": "2026-04-17 11:49:23",
                "tone": "good",
                "detail": "Estimated trend derived from current profile and crawl signals. Age: 0s ago."
            },
            {
                "label": "Audience geography",
                "value": "Not captured yet",
                "tone": "unknown",
                "detail": "Audience mix is estimated from available signals rather than first-party audience logs."
            }
        ],
        "section_notes": {
            "audience": "Audience geography is estimated from category, country, traffic mix, and brand signals until first-party audience data is collected.",
            "keywords": "Top keywords are estimated from crawl language, brand, category, and visibility signals until tracked keyword snapshots are stored.",
            "history": "Rank history is estimated from the current profile because no stored history exists for this domain yet."
        },
        "base_weighted_score": 69,
        "fraud_clamp_penalty": 5,
        "final_score": 64
    },
    "insight_snapshot": {
        "version": 1,
        "generated_at": "2026-04-17T11:49:23+00:00",
        "domain": "geek.nz",
        "display_name": "Adrian Lyall Cochrane",
        "is_tracked": false,
        "is_estimated": true,
        "overall_score": 64,
        "authority_score": 23,
        "trust_score": 36,
        "safety_score": 100,
        "fraud_score": 0,
        "confidence_score": 99,
        "traffic_confidence": 39,
        "last_crawled_at": "2026-03-17 07:39:59",
        "crawl_blocked": false,
        "summary": "geek.nz currently scores 64/100. The score is being shaped by a mixed signal profile rather than one dominant factor. Evidence confidence is strong enough for a relatively stable read. This is an estimated profile rather than a manually tracked one. Crawler access looks clean.",
        "badges": [
            {
                "label": "Profile",
                "value": "Estimated profile",
                "tone": "unknown",
                "detail": null
            },
            {
                "label": "Evidence confidence",
                "value": "High confidence",
                "tone": "good",
                "detail": "99/100"
            },
            {
                "label": "Traffic confidence",
                "value": "Low confidence",
                "tone": "risk",
                "detail": "39/100"
            },
            {
                "label": "Crawler access",
                "value": "Clean visibility",
                "tone": "good",
                "detail": null
            }
        ],
        "top_positive_signals": [
            "Healthy crawl quality and on-page completeness.",
            "HTTPS is working, so the site clears a basic transport-security check.",
            "Backlink diversity looks broad enough to strengthen authority confidence."
        ],
        "top_risk_signals": [
            "Traffic and reach estimates are still low confidence, so commercial scale signals may move after more evidence is collected."
        ],
        "freshness": [
            {
                "label": "Crawl evidence",
                "value": "2026-03-17 07:39:59",
                "tone": "risk",
                "detail": "Crawl and page content sample. Age: 1mo ago."
            },
            {
                "label": "WHOIS snapshot",
                "value": "Not captured yet",
                "tone": "unknown",
                "detail": "Registry profile and stability signals."
            },
            {
                "label": "Keyword view",
                "value": "2026-04-17 11:49:23",
                "tone": "good",
                "detail": "Estimated visibility until tracked keyword snapshots exist. Age: 0s ago."
            },
            {
                "label": "Rank history",
                "value": "2026-04-17 11:49:23",
                "tone": "good",
                "detail": "Estimated trend derived from current profile and crawl signals. Age: 0s ago."
            },
            {
                "label": "Audience geography",
                "value": "Not captured yet",
                "tone": "unknown",
                "detail": "Audience mix is estimated from available signals rather than first-party audience logs."
            }
        ],
        "top_tags": [
            {
                "code": "Uncertain",
                "label": "Uncertain",
                "tone": "unknown"
            },
            {
                "code": "T",
                "label": "Trusted",
                "tone": "good"
            }
        ]
    },
    "is_tracked": false,
    "is_estimated": true,
    "live_state": {
        "status": "processing",
        "status_label": "Cache build running",
        "message": "The refreshed page cache is still being built for this domain.",
        "updated_at": "2026-04-19T10:56:26+00:00"
    },
    "refresh_state": {
        "canRequest": false,
        "queued": true,
        "processing": true,
        "stageKey": "cache-queued",
        "stageLabel": "Cache build running",
        "cooldownUntil": null,
        "message": "The refreshed page cache is still being built for this domain.",
        "action": "/domain/geek.nz/refresh",
        "isGuestCooldown": false,
        "cooldownSeconds": 0
    },
    "urlscan_report": {
        "domain": "geek.nz",
        "status": "idle",
        "submitted_at": null,
        "completed_at": null,
        "last_checked_at": null,
        "last_error": "",
        "submitted_url": "https://geek.nz/",
        "uuid": "",
        "result_url": "",
        "api_result_url": "",
        "visibility": "public",
        "summary": "No urlscan.io report has been requested for this domain yet.",
        "report": [],
        "report_summary": [],
        "is_fresh": false,
        "can_retry": true,
        "poll_after_seconds": 20
    }
}