{
    "ready": true,
    "site": {
        "id": 0,
        "domain": "unindented.org",
        "display_name": "Unindented",
        "primary_country_code": "",
        "category_name": "Personal: Personal Sites & Homepages"
    },
    "metrics": {
        "global_rank": 8303,
        "country_rank": 4196,
        "category_rank": 35,
        "daily_pageviews_per_visitor": 3.93,
        "daily_time_on_site_seconds": 315,
        "bounce_rate": 31.68,
        "search_visits_percent": 41.3,
        "total_sites_linking_in": 3,
        "monthly_unique_visitors": 209,
        "recorded_at": "2026-03-17 07:38:08"
    },
    "audit": {
        "score": 86
    },
    "traffic_sources": {
        "direct_percent": 27.48,
        "search_percent": 35.91,
        "social_percent": 8.43,
        "referral_percent": 12.94,
        "email_percent": 6.55,
        "paid_percent": 8.69
    },
    "seo_profile": {
        "backlinks_total": 3,
        "referring_domains": 3,
        "dofollow_backlinks_percent": 66.67,
        "organic_keywords": 84,
        "indexed_pages": 59,
        "page_speed_score": 70,
        "mobile_friendliness_score": 85,
        "authority_score": 44,
        "spam_risk_score": 19
    },
    "crawl_report": {
        "robots_status": 200,
        "sitemap_status": 200,
        "sitemap_total_urls": 59,
        "crawl_blocked": false,
        "crawl_blocked_by": "",
        "crawl_blocked_reason": "",
        "notes": [],
        "created_at": "2026-03-17 07:38:08"
    },
    "keywords": [
        {
            "keyword": "Unindented",
            "position": 19,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        },
        {
            "keyword": "Unindented personal: personal sites & homepages",
            "position": 21,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        },
        {
            "keyword": "Unindented reviews",
            "position": 23,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        },
        {
            "keyword": "unindented",
            "position": 25,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        },
        {
            "keyword": "daniel",
            "position": 27,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        },
        {
            "keyword": "perez",
            "position": 29,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        },
        {
            "keyword": "alvarez",
            "position": 31,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        },
        {
            "keyword": "about",
            "position": 33,
            "search_engine": "Estimated",
            "checked_at": "2026-04-13 16:25:06",
            "is_estimated": true
        }
    ],
    "rating": {
        "overall": 64,
        "label": "Healthy",
        "breakdown": [
            {
                "label": "Technical foundation",
                "score": 17,
                "max": 18
            },
            {
                "label": "Authority & trust",
                "score": 14,
                "max": 30
            },
            {
                "label": "Reach & market presence",
                "score": 3,
                "max": 18
            },
            {
                "label": "Search visibility",
                "score": 3,
                "max": 12
            },
            {
                "label": "Engagement & retention",
                "score": 8,
                "max": 10
            },
            {
                "label": "Channels & diversification",
                "score": 4,
                "max": 6
            },
            {
                "label": "Registry stability",
                "score": 5,
                "max": 6
            },
            {
                "label": "Quality system",
                "score": 94,
                "max": 100
            },
            {
                "label": "Reputation system",
                "score": 45,
                "max": 100
            },
            {
                "label": "Safety system",
                "score": 100,
                "max": 100
            },
            {
                "label": "Evidence confidence",
                "score": 100,
                "max": 100
            }
        ],
        "authority_score": 46,
        "quality_score": 94,
        "reputation_score": 45,
        "safety_score": 100,
        "confidence_score": 100,
        "fraud_score": 3,
        "authority_signals": {
            "backlinks": 3,
            "referring_domains": 3,
            "organic_keywords": 84,
            "indexed_pages": 59,
            "monthly_visitors": 209,
            "global_rank": 8303,
            "engagement_score": 79,
            "crawl_quality_score": 100,
            "brand_completeness_score": 66,
            "link_diversity_score": 94,
            "technical_reliability_score": 81,
            "whois_score": 87,
            "whois_age_years": 19,
            "whois_stability_score": 100,
            "spam_penalty": 0
        },
        "whois_signals": {
            "age_years": 19,
            "days_to_expiry": 366,
            "days_since_last_registry_update": 30,
            "stability_score": 100,
            "registrar_changes": 0,
            "ownership_changes": 0,
            "nameserver_changes": 0,
            "status_changes": 0,
            "history_entries": 1,
            "privacy_protected": false,
            "dnssec_enabled": false,
            "has_registrant_country": false,
            "registrant_country": "",
            "nameserver_count": 3,
            "status_count": 2
        }
    },
    "authority_score": 46,
    "trust_score": 77,
    "domain_tags": {
        "primary_tag": "T",
        "primary_tag_score": 83,
        "primary_candidate": "T",
        "primary_candidate_score": 83,
        "tag_codes": "T",
        "tags": [
            {
                "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": 83,
                "score": 83,
                "match_percent": 83,
                "threshold_band": "strong"
            }
        ],
        "tag_breakdown": [
            {
                "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": 83,
                "score": 83,
                "match_percent": 83,
                "threshold_band": "strong"
            },
            {
                "code": "Infra",
                "label": "Risky infrastructure",
                "tone": "caution",
                "description": "The hosting / registrar / nameserver neighbourhood looks unusually risky.",
                "reason": "The infrastructure neighbourhood looks riskier than normal.",
                "message": "Infrastructure risk does not currently stand out.",
                "priority": 19,
                "score": 19,
                "match_percent": 19,
                "threshold_band": "none"
            },
            {
                "code": "Uncertain",
                "label": "Uncertain",
                "tone": "unknown",
                "description": "External checks stayed inconclusive, so the model avoided a harder verdict.",
                "reason": "",
                "message": "The evidence does not currently look notably uncertain.",
                "priority": 18,
                "score": 18,
                "match_percent": 18,
                "threshold_band": "none"
            },
            {
                "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"
            }
        ],
        "nsfw_score": 0,
        "trust_score": 78,
        "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": "Trusted (83% match) because low spam indicators plus strong trust, quality, registry, and stability signals were detected.",
        "external_intel": [],
        "external_decision": [],
        "signal_scores": [
            {
                "label": "Strongest tag heuristic",
                "value": "T · 83%",
                "tone": "good",
                "detail": "The highest raw tag match from the heuristic engine before visibility thresholds and manual overrides."
            },
            {
                "label": "Trust score",
                "value": "78/100",
                "tone": "good",
                "detail": "Confidence derived from authority, crawl quality, stability, and risk signals."
            },
            {
                "label": "Authority score",
                "value": "46/100",
                "tone": "caution",
                "detail": "A higher authority score usually means broader reputation and backlink confidence."
            },
            {
                "label": "Spam risk",
                "value": "0/100",
                "tone": "good",
                "detail": "Lower is better. This blends spam indicators with false-positive protections for legitimate sites."
            },
            {
                "label": "Quality score",
                "value": "89/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": "19/100",
                "tone": "good",
                "detail": "Lower is better. This reflects the IP, registrar, and nameserver neighbourhood seen by the crawler."
            },
            {
                "label": "Evidence confidence",
                "value": "100/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": "100/100",
                "tone": "good",
                "detail": "Based on age, expiry runway, and the amount of ownership / registrar churn."
            }
        ],
        "signal_sections": [
            {
                "title": "Registry & ownership",
                "items": [
                    {
                        "label": "Domain age",
                        "value": "19.0 years",
                        "tone": "good",
                        "detail": "Older domains generally carry more historical trust than very new ones."
                    },
                    {
                        "label": "Stability score",
                        "value": "100/100",
                        "tone": "good",
                        "detail": "Penalised by registrar, ownership, and nameserver churn."
                    },
                    {
                        "label": "Days to expiry",
                        "value": "366",
                        "tone": "good",
                        "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": "84",
                        "tone": "caution",
                        "detail": "Search footprint helps distinguish real sites from thin shells."
                    },
                    {
                        "label": "Indexed pages",
                        "value": "59",
                        "tone": "caution",
                        "detail": "Larger index coverage usually means more evidence to classify from."
                    },
                    {
                        "label": "Brand strength",
                        "value": "66/100",
                        "tone": "good",
                        "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,211 ms",
                        "tone": "good",
                        "detail": "Slow or broken technical signals weaken confidence."
                    },
                    {
                        "label": "Content words",
                        "value": "161",
                        "tone": "caution",
                        "detail": "Thin pages are harder to trust and easier to manipulate."
                    },
                    {
                        "label": "Schema / structure",
                        "value": "0 schema · meta · H1",
                        "tone": "caution",
                        "detail": "Structured markup and basic on-page hygiene improve quality confidence."
                    },
                    {
                        "label": "Links on page",
                        "value": "38 internal · 4 external",
                        "tone": "good",
                        "detail": "Link patterns help detect thin directories and promo pages."
                    },
                    {
                        "label": "Page speed / mobile",
                        "value": "70/100 · 85/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": [
            "Established domain age: 19.0 years.",
            "Low registrar / ownership churn with solid registry stability.",
            "Healthy crawl quality and on-page completeness."
        ],
        "risks": []
    },
    "traffic_confidence": 73,
    "whois": {
        "current": {
            "id": 16432,
            "domain": "unindented.org",
            "source_type": "rdap",
            "rdap_url": "https://rdap.publicinterestregistry.org/rdap/domain/unindented.org",
            "registrar_name": "DreamHost, LLC",
            "registrar_handle": "431",
            "registrant_name": "",
            "registrant_org": "",
            "registrant_country": "",
            "registrant_email": "",
            "abuse_email": "domain-abuse@dreamhost.com",
            "created_date": "2007-04-15 01:19:51",
            "updated_date": "2026-03-14 09:02:16",
            "expires_date": "2027-04-15 01:19:51",
            "nameservers_json": "[\"ns1.dreamhost.com\",\"ns2.dreamhost.com\",\"ns3.dreamhost.com\"]",
            "status_json": "[\"client transfer prohibited\",\"renew period\"]",
            "dnssec": "unsigned",
            "privacy_protected": 0,
            "content_hash": "9044e57c9a4427c9fa8548ecd7cbd50985563c7f188c7a78cdda2605c0603bd4",
            "history_count": 1,
            "last_checked_at": "2026-03-17 07:38:08",
            "last_changed_at": "2026-03-17 07:38:08",
            "created_at": "2026-03-17 07:38:08",
            "updated_at": "2026-03-17 07:38:08"
        },
        "history": [
            {
                "id": 16745,
                "domain": "unindented.org",
                "source_type": "rdap",
                "registrar_name": "DreamHost, LLC",
                "registrar_handle": "431",
                "registrant_name": "",
                "registrant_org": "",
                "registrant_country": "",
                "registrant_email": "",
                "abuse_email": "domain-abuse@dreamhost.com",
                "created_date": "2007-04-15 01:19:51",
                "updated_date": "2026-03-14 09:02:16",
                "expires_date": "2027-04-15 01:19:51",
                "nameservers_json": "[\"ns1.dreamhost.com\",\"ns2.dreamhost.com\",\"ns3.dreamhost.com\"]",
                "status_json": "[\"client transfer prohibited\",\"renew period\"]",
                "dnssec": "unsigned",
                "privacy_protected": 0,
                "content_hash": "9044e57c9a4427c9fa8548ecd7cbd50985563c7f188c7a78cdda2605c0603bd4",
                "checked_at": "2026-03-17 07:38:08",
                "change_summary": "Initial WHOIS snapshot captured.",
                "created_at": "2026-03-17 07:38:08"
            }
        ],
        "signals": {
            "age_years": 19,
            "days_to_expiry": 366,
            "days_since_last_registry_update": 30,
            "stability_score": 100,
            "registrar_changes": 0,
            "ownership_changes": 0,
            "nameserver_changes": 0,
            "status_changes": 0,
            "history_entries": 1,
            "privacy_protected": false,
            "dnssec_enabled": false,
            "has_registrant_country": false,
            "registrant_country": "",
            "nameserver_count": 3,
            "status_count": 2
        }
    },
    "discovered_domain": {
        "id": 68636,
        "domain": "unindented.org",
        "first_seen_at": "2026-03-15 18:57:04",
        "last_crawled_at": "2026-03-17 07:38:08",
        "last_title": "Unindented — Home of Daniel Perez Alvarez",
        "last_http_status": 200,
        "discovered_from_domain": "250kb.club",
        "depth": 0,
        "backlinks_count": 3,
        "rating_cache": 61,
        "spam_score": 28,
        "risk_label": "good",
        "category_name": "Personal: Personal Sites & Homepages",
        "primary_country_code": "",
        "internal_links_count": 38,
        "external_links_count": 4,
        "social_profiles_count": 2,
        "content_word_count": 161,
        "title_quality_score": 81,
        "has_meta_description": 1,
        "has_h1": 1,
        "language_code": "en-us",
        "response_time_ms": 1211,
        "robots_status": 200,
        "sitemap_status": 200,
        "sitemap_total_urls": 59,
        "quality_score": 89,
        "site_name": "",
        "canonical_domain": "",
        "favicon_present": 1,
        "schema_org_count": 0,
        "noindex_detected": 0,
        "feed_links_count": 1,
        "https_working": 1,
        "estimated_authority_score": 37,
        "trust_score": 98,
        "nsfw_score": 0,
        "overall_rank_estimate": 5552,
        "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": 3,
        "legitimacy_score": 50,
        "infrastructure_risk_score": 19,
        "score_confidence": 100,
        "tag_confidence": 73,
        "category_confidence": 88,
        "deep_crawl_pages": 50,
        "resolved_ip": "75.119.203.193",
        "category_candidates_json": "[{\"category\":\"Personal: Personal Sites & Homepages\",\"score\":88}]",
        "page_signals_json": "[{\"path\":\"/about\",\"status\":200,\"title\":\"About — Unindented\",\"word_count\":132,\"summary_text\":\"About — Unindented About — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelAboutAbout meI&rsquo;m Daniel Perez Alvarez, a software engineer focused on front-end web development.Currently at Snowflake. Previously at Twitter, Microsoft.Based in Seattle. Lived in London for a while. Originally from Madrid.Here&rsquo;s a list of sites I follow.Here&rsquo;s a list of stuff I use.Here&rsquo;s music and movies I like.Want to get in touch? Feel free to email me.Ab\",\"classification_terms\":[\"about\",\"about me\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/about/\",\"status\":200,\"title\":\"About — Unindented\",\"word_count\":132,\"summary_text\":\"About — Unindented About — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelAboutAbout meI&rsquo;m Daniel Perez Alvarez, a software engineer focused on front-end web development.Currently at Snowflake. Previously at Twitter, Microsoft.Based in Seattle. Lived in London for a while. Originally from Madrid.Here&rsquo;s a list of sites I follow.Here&rsquo;s a list of stuff I use.Here&rsquo;s music and movies I like.Want to get in touch? Feel free to email me.Ab\",\"classification_terms\":[\"about\",\"about me\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/blog/\",\"status\":200,\"title\":\"Blog — Unindented\",\"word_count\":112,\"summary_text\":\"Blog — Unindented Blog — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelBlogLatest articlesChange Shell to Latest Bash on macOSWednesday, January 4, 2023 — 1 minute readMacOSTerminalCreate a Bootable USB for macOS VenturaSunday, January 1, 2023 — 1 minute readMacOSInspect WebViews in Any macOS AppMonday, April 4, 2022 — 1 minute readMacOSPixel Art Scaling Comparison — Part 2Friday, April 18, 2014 — 2 minute readPixel ArtPixel Art Scaling Comparison — Par\",\"classification_terms\":[\"blog\",\"about\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/\",\"status\":200,\"title\":\"Playground — Unindented\",\"word_count\":120,\"summary_text\":\"Playground — Unindented Playground — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelPlaygroundLatest articlesQR Code GeneratorWednesday, May 17, 2023QR CodeUtilsClipboard InspectorThursday, January 5, 2023ClipboardUtilsTerminal Color PreviewThursday, May 19, 2022ColorTerminalUtilsBaby Smash!Thursday, April 28, 2022KidsMandelbrot Set with WebGLTuesday, April 19, 2022FractalMandelbrotP5.jsWebGLMandelbrot Set with AssemblyScript / WebAssemblyWednesday, April 13,\",\"classification_terms\":[\"playground\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/qr-code-generator/\",\"status\":200,\"title\":\"QR Code Generator — Unindented\",\"word_count\":91,\"summary_text\":\"QR Code Generator — Unindented QR Code Generator — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelWednesday, May 17, 2023QR CodeUtilsQR Code GeneratorWhip up a QR code that can be scanned by anyone with a smartphone or a QR code reader. All thanks to the awesome headless-qr module by Rich Harris.Input Correction Low&nbsp;(7%) Medium&nbsp;(15%) Quartile&nbsp;(25%) High&nbsp;(30%)QR codeResourcesqr.mjsSee alsoClipboard InspectorTerminal Color PreviewCompress Strings wi\",\"classification_terms\":[\"playground/qr-code-generator\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/qr-code/\",\"status\":200,\"title\":\"QR Code — Unindented\",\"word_count\":34,\"summary_text\":\"QR Code — Unindented QR Code — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelQR CodeLatest articlesQR Code GeneratorWednesday, May 17, 2023QR CodeUtilsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/qr-code\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/utils/\",\"status\":200,\"title\":\"Utils — Unindented\",\"word_count\":54,\"summary_text\":\"Utils — Unindented Utils — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelUtilsLatest articlesQR Code GeneratorWednesday, May 17, 2023QR CodeUtilsClipboard InspectorThursday, January 5, 2023ClipboardUtilsTerminal Color PreviewThursday, May 19, 2022ColorTerminalUtilsCompress Strings with lz‑stringWednesday, March 30, 2022CompressionUtilsJWT Decoder in the BrowserThursday, April 22, 2021SecurityUtilsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez\",\"classification_terms\":[\"tags/utils\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/clipboard-inspector/\",\"status\":200,\"title\":\"Clipboard Inspector — Unindented\",\"word_count\":82,\"summary_text\":\"Clipboard Inspector — Unindented Clipboard Inspector — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelThursday, January 5, 2023ClipboardUtilsClipboard InspectorSmall widget to explore the data available when you paste or drop something on a web page.Inspect your clipboard using the Clipboard API.Paste with Ctrl + V or ⌘ Cmd + V.Drop something here.Resourcesclipboard.mjsSee alsoQR Code GeneratorTerminal Color PreviewCompress Strings with lz‑stringJWT Decoder in the Brow\",\"classification_terms\":[\"playground/clipboard-inspector\",\"about\",\"api\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/clipboard/\",\"status\":200,\"title\":\"Clipboard — Unindented\",\"word_count\":30,\"summary_text\":\"Clipboard — Unindented Clipboard — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelClipboardLatest articlesClipboard InspectorThursday, January 5, 2023ClipboardUtilsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/clipboard\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/blog/change-shell-to-latest-bash-on-macos/\",\"status\":200,\"title\":\"Change Shell to Latest Bash on macOS — Unindented\",\"word_count\":310,\"summary_text\":\"Change Shell to Latest Bash on macOS — Unindented Change Shell to Latest Bash on macOS — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelWednesday, January 4, 2023 — 1 minute readMacOSTerminalChange Shell to Latest Bash on macOSStarting with macOS Catalina, Apple switched the default shell from Bash to Zsh. Also, the built-in version of Bash is horribly outdated. No bueno.Installing the latest version of BashYou may be surprised to learn that even the latest versions of macOS ship with\",\"classification_terms\":[\"blog/change-shell-to-latest-bash-on-macos\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/macos/\",\"status\":200,\"title\":\"MacOS — Unindented\",\"word_count\":64,\"summary_text\":\"MacOS — Unindented MacOS — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelMacOSLatest articlesChange Shell to Latest Bash on macOSWednesday, January 4, 2023 — 1 minute readMacOSTerminalCreate a Bootable USB for macOS VenturaSunday, January 1, 2023 — 1 minute readMacOSInspect WebViews in Any macOS AppMonday, April 4, 2022 — 1 minute readMacOSRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/macos\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/terminal/\",\"status\":200,\"title\":\"Terminal — Unindented\",\"word_count\":44,\"summary_text\":\"Terminal — Unindented Terminal — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelTerminalLatest articlesChange Shell to Latest Bash on macOSWednesday, January 4, 2023 — 1 minute readMacOSTerminalTerminal Color PreviewThursday, May 19, 2022ColorTerminalUtilsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/terminal\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/blog/create-bootable-usb-for-macos/\",\"status\":200,\"title\":\"Create a Bootable USB for macOS Ventura — Unindented\",\"word_count\":224,\"summary_text\":\"Create a Bootable USB for macOS Ventura — Unindented Create a Bootable USB for macOS Ventura — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelSunday, January 1, 2023 — 1 minute readMacOSCreate a Bootable USB for macOS VenturaI find it useful to have a bootable USB lying around, in case I need to do a clean install, or recover from catastrophic failures.Creating a bootable USBCreating a bootable USB is relatively straightforward:Download macOS Ventura from the App Store.Connect a 16GB or l\",\"classification_terms\":[\"blog/create-bootable-usb-for-macos\",\"about\",\"blog\",\"store\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/terminal-color-preview/\",\"status\":200,\"title\":\"Terminal Color Preview — Unindented\",\"word_count\":582,\"summary_text\":\"Terminal Color Preview — Unindented Terminal Color Preview — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelThursday, May 19, 2022ColorTerminalUtilsTerminal Color PreviewI&rsquo;ve been playing with terminal color schemes lately, and wanted a way of quickly previewing my changes, so I built this.Preset DraculaGruvbox (Dark - Soft Contrast)Gruvbox (Dark - Medium Contrast)Gruvbox (Dark - Hard Contrast)NordPapercolor (Dark)Solarized (Dark)Tokyo Night (Night)Tokyo Night (Stor\",\"classification_terms\":[\"playground/terminal-color-preview\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/color/\",\"status\":200,\"title\":\"Color — Unindented\",\"word_count\":31,\"summary_text\":\"Color — Unindented Color — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelColorLatest articlesTerminal Color PreviewThursday, May 19, 2022ColorTerminalUtilsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/color\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/baby-smash/\",\"status\":200,\"title\":\"Baby Smash! — Unindented\",\"word_count\":87,\"summary_text\":\"Baby Smash! — Unindented Baby Smash! — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelThursday, April 28, 2022KidsBaby Smash!My kids love Baby Smash!, a Windows app that draws letters and shapes, and plays sounds, as they smash the keyboard and mouse.This is a crude attempt to replicate it using web technologies. We can&rsquo;t capture certain key combinations and gestures, so it&rsquo;s not very baby-safe. StartResourcesaudio/a-what.mp3audio/b-abcd.mp3audio/b-\",\"classification_terms\":[\"playground/baby-smash\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/kids/\",\"status\":200,\"title\":\"Kids — Unindented\",\"word_count\":30,\"summary_text\":\"Kids — Unindented Kids — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelKidsLatest articlesBaby Smash!Thursday, April 28, 2022KidsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/kids\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/mandelbrot-set-with-webgl-shaders/\",\"status\":200,\"title\":\"Mandelbrot Set with WebGL — Unindented\",\"word_count\":325,\"summary_text\":\"Mandelbrot Set with WebGL — Unindented Mandelbrot Set with WebGL — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelTuesday, April 19, 2022FractalMandelbrotP5.jsWebGLMandelbrot Set with WebGLPlotting the Mandelbrot set with a GLSL fragment shader.I&rsquo;ve translated the code I wrote for plotting the Mandelbrot set with p5.js to a GLSL 1.0 fragment shader. The main difference is that I&rsquo;m using vec2 to represent complex numbers, which makes things a bit more concise.Gray\",\"classification_terms\":[\"playground/mandelbrot-set-with-webgl-shaders\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/fractal/\",\"status\":200,\"title\":\"Fractal — Unindented\",\"word_count\":46,\"summary_text\":\"Fractal — Unindented Fractal — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelFractalLatest articlesMandelbrot Set with WebGLTuesday, April 19, 2022FractalMandelbrotP5.jsWebGLMandelbrot Set with AssemblyScript / WebAssemblyWednesday, April 13, 2022AssemblyScriptFractalMandelbrotWebAssemblyMandelbrot Set with p5.jsThursday, April 7, 2022FractalMandelbrotP5.jsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights\",\"classification_terms\":[\"tags/fractal\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/mandelbrot/\",\"status\":200,\"title\":\"Mandelbrot — Unindented\",\"word_count\":46,\"summary_text\":\"Mandelbrot — Unindented Mandelbrot — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelMandelbrotLatest articlesMandelbrot Set with WebGLTuesday, April 19, 2022FractalMandelbrotP5.jsWebGLMandelbrot Set with AssemblyScript / WebAssemblyWednesday, April 13, 2022AssemblyScriptFractalMandelbrotWebAssemblyMandelbrot Set with p5.jsThursday, April 7, 2022FractalMandelbrotP5.jsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some\",\"classification_terms\":[\"tags/mandelbrot\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/p5.js/\",\"status\":200,\"title\":\"P5.js — Unindented\",\"word_count\":44,\"summary_text\":\"P5.js — Unindented P5.js — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelP5.jsLatest articlesMandelbrot Set with WebGLTuesday, April 19, 2022FractalMandelbrotP5.jsWebGLMandelbrot Set with p5.jsThursday, April 7, 2022FractalMandelbrotP5.jsPrime Spiral with p5.jsSunday, March 6, 2022MathP5.jsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/p5.js\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/webgl/\",\"status\":200,\"title\":\"WebGL — Unindented\",\"word_count\":32,\"summary_text\":\"WebGL — Unindented WebGL — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelWebGLLatest articlesMandelbrot Set with WebGLTuesday, April 19, 2022FractalMandelbrotP5.jsWebGLRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/webgl\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/mandelbrot-set-with-assemblyscript-wasm/\",\"status\":200,\"title\":\"Mandelbrot Set with AssemblyScript / WebAssembly — Unindented\",\"word_count\":140,\"summary_text\":\"Mandelbrot Set with AssemblyScript / WebAssembly — Unindented Mandelbrot Set with AssemblyScript / WebAssembly — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelWednesday, April 13, 2022AssemblyScriptFractalMandelbrotWebAssemblyMandelbrot Set with AssemblyScript / WebAssemblyPlotting the Mandelbrot set with AssemblyScript, a TypeScript-like language that compiles to WebAssembly bytecode.I&rsquo;ve translated the code I wrote for plotting the Mandelbrot set with p5.js to AssemblyScript, to get a fee\",\"classification_terms\":[\"playground/mandelbrot-set-with-assemblyscript-wasm\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/assemblyscript/\",\"status\":200,\"title\":\"AssemblyScript — Unindented\",\"word_count\":34,\"summary_text\":\"AssemblyScript — Unindented AssemblyScript — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelAssemblyScriptLatest articlesMandelbrot Set with AssemblyScript / WebAssemblyWednesday, April 13, 2022AssemblyScriptFractalMandelbrotWebAssemblyRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/assemblyscript\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/webassembly/\",\"status\":200,\"title\":\"WebAssembly — Unindented\",\"word_count\":34,\"summary_text\":\"WebAssembly — Unindented WebAssembly — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelWebAssemblyLatest articlesMandelbrot Set with AssemblyScript / WebAssemblyWednesday, April 13, 2022AssemblyScriptFractalMandelbrotWebAssemblyRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/webassembly\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/mandelbrot-set-with-p5/\",\"status\":200,\"title\":\"Mandelbrot Set with p5.js — Unindented\",\"word_count\":397,\"summary_text\":\"Mandelbrot Set with p5.js — Unindented Mandelbrot Set with p5.js — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelThursday, April 7, 2022FractalMandelbrotP5.jsMandelbrot Set with p5.jsThe Mandelbrot set, named after Benoit Mandelbrot, is the set of complex numbers $c$ for which the function $f_c(z)=z^2+c$ does not diverge to infinity when iterated from $z=0$.I&rsquo;m using the pseudocode from the Wikipedia article Plotting algorithms for the Mandelbrot set as base, and appl\",\"classification_terms\":[\"playground/mandelbrot-set-with-p5\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/blog/inspect-webviews-in-any-macos-app/\",\"status\":200,\"title\":\"Inspect WebViews in Any macOS App — Unindented\",\"word_count\":151,\"summary_text\":\"Inspect WebViews in Any macOS App — Unindented Inspect WebViews in Any macOS App — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelMonday, April 4, 2022 — 1 minute readMacOSInspect WebViews in Any macOS AppDid you know you can inspect any WebView on any macOS app, just by right-clicking it?The only thing you need to do is change your user defaults by running the following command:defaults write -g WebKitDeveloperExtras -bool true Once you do that, you should be able to right-click in\",\"classification_terms\":[\"blog/inspect-webviews-in-any-macos-app\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/webrtc-without-signaling-server/\",\"status\":200,\"title\":\"WebRTC without Signaling Server — Unindented\",\"word_count\":282,\"summary_text\":\"WebRTC without Signaling Server — Unindented WebRTC without Signaling Server — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelThursday, March 31, 2022WebRTCWebRTC without Signaling ServerI was reading MDN&rsquo;s article on signaling and video calling, and encountered this part:WebRTC is a fully peer-to-peer technology for the real-time exchange of audio, video, and data, with one central caveat. A form of discovery and media format negotiation must take place, as discussed elsewh\",\"classification_terms\":[\"playground/webrtc-without-signaling-server\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/webrtc/\",\"status\":200,\"title\":\"WebRTC — Unindented\",\"word_count\":32,\"summary_text\":\"WebRTC — Unindented WebRTC — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelWebRTCLatest articlesWebRTC without Signaling ServerThursday, March 31, 2022WebRTCRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/webrtc\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/lz-string/\",\"status\":200,\"title\":\"Compress Strings with lz‑string — Unindented\",\"word_count\":147,\"summary_text\":\"Compress Strings with lz‑string — Unindented Compress Strings with lz‑string — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelWednesday, March 30, 2022CompressionUtilsCompress Strings with lz‑stringI wanted to compress some large strings in JavaScript, for an experiment with WebRTC, and found the excellent lz-string by pieroxy.It&rsquo;s fast, and it weighs just a little over 4KB if you run it through something like Terser. I&rsquo;ve tweaked it ever so slightly for my needs, but\",\"classification_terms\":[\"playground/lz-string\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/compression/\",\"status\":200,\"title\":\"Compression — Unindented\",\"word_count\":32,\"summary_text\":\"Compression — Unindented Compression — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelCompressionLatest articlesCompress Strings with lz‑stringWednesday, March 30, 2022CompressionUtilsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/compression\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/prime-spiral-with-p5/\",\"status\":200,\"title\":\"Prime Spiral with p5.js — Unindented\",\"word_count\":134,\"summary_text\":\"Prime Spiral with p5.js — Unindented Prime Spiral with p5.js — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelSunday, March 6, 2022MathP5.jsPrime Spiral with p5.jsThe prime spiral, also known as Ulam spiral, is a neat visualization of prime numbers devised by mathematician Stanisław Ulam.It arranges positive integers in a square spiral, highlighting the ones that are primes: Play Pause DownloadIf you draw a bigger spiral, you&rsquo;ll notice patterns forming around some ho\",\"classification_terms\":[\"playground/prime-spiral-with-p5\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/math/\",\"status\":200,\"title\":\"Math — Unindented\",\"word_count\":59,\"summary_text\":\"Math — Unindented Math — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelMathLatest articlesPrime Spiral with p5.jsSunday, March 6, 2022MathP5.jsLorenz Attractor with JSSunday, February 16, 2014MathLorenz Attractor with CSSSaturday, February 15, 2014CSSMath3D Shapes with CSSSaturday, February 8, 2014CSSMathTrigonometry in SassFriday, February 7, 2014 — 4 minute readCSSMathRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise n\",\"classification_terms\":[\"tags/math\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/jwt-decoder/\",\"status\":200,\"title\":\"JWT Decoder in the Browser — Unindented\",\"word_count\":77,\"summary_text\":\"JWT Decoder in the Browser — Unindented JWT Decoder in the Browser — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelThursday, April 22, 2021SecurityUtilsJWT Decoder in the BrowserDecode JSON web tokens right in the browser. Nothing gets recorded, everything is done client-side.Your token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cDecoded header Decoded body Resource\",\"classification_terms\":[\"playground/jwt-decoder\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/security/\",\"status\":200,\"title\":\"Security — Unindented\",\"word_count\":33,\"summary_text\":\"Security — Unindented Security — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelSecurityLatest articlesJWT Decoder in the BrowserThursday, April 22, 2021SecurityUtilsRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/security\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/playground/colored-noise/\",\"status\":200,\"title\":\"Colored Noise — White, Pink, and Red — Unindented\",\"word_count\":125,\"summary_text\":\"Colored Noise — White, Pink, and Red — Unindented Colored Noise — White, Pink, and Red — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelMonday, November 23, 2020AudioColored Noise — White, Pink, and RedUsing the Web Audio API to generate noise of different colors. Your browser doesn't support canvas.White Pink Red You can move the sliders to adjust the gain on the white, pink, and red noise generators.Everything within the Web Audio API is based around the concept of an audio graph, wh\",\"classification_terms\":[\"playground/colored-noise\",\"about\",\"support\",\"api\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/tags/audio/\",\"status\":200,\"title\":\"Audio — Unindented\",\"word_count\":35,\"summary_text\":\"Audio — Unindented Audio — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelAudioLatest articlesColored Noise — White, Pink, and RedMonday, November 23, 2020AudioRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/audio\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/page/2/\",\"status\":200,\"title\":\"Unindented — Home of Daniel Perez Alvarez\",\"word_count\":135,\"summary_text\":\"Unindented — Home of Daniel Perez Alvarez Unindented — Home of Daniel Perez Alvarez (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelHi, I&rsquo;m Daniel —I&rsquo;m a software engineer focused on front-end web development, but I dabble in other stuff too.Latest articlesSVG Line AnimationMonday, December 1, 2014SVGPixel Art Scaling Comparison — Part 2Friday, April 18, 2014 — 2 minute readPixel ArtPixel Art Scaling Comparison — Part 1Friday, April 11, 2014 — 2 minute readPixel ArtCompare Two\",\"classification_terms\":[\"page/2\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":1},{\"path\":\"/follows/\",\"status\":200,\"title\":\"Sites I Follow — Unindented\",\"word_count\":247,\"summary_text\":\"Sites I Follow — Unindented Sites I Follow — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelSites I FollowGeneralAaron Patterson — tenderlovemaking.com RSSAmos Wenger — fasterthanli.me RSSAndrew Healey — healeycodes.com RSSAsh Furrow — ashfurrow.com RSSBartosz Ciechanowski — ciechanow.ski RSSBen Congdon — benjamincongdon.me RSSBruce Dawson — randomascii.wordpress.com RSSDan Luu — danluu.com RSSDrew DeVault — drewdevault.com RSSFabien Sanglard — fabiensanglard.net\",\"classification_terms\":[\"follows\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/uses/\",\"status\":200,\"title\":\"Stuff I Use — Unindented\",\"word_count\":675,\"summary_text\":\"Stuff I Use — Unindented Stuff I Use — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelStuff I UseHardwareComputer &mdash; MacBook Pro 16\\\" (M1 Max, 2021)Superb performance. Crazy expensive though.Monitors &mdash; Dell UltraSharp U2720Q 27\\\" (2x)Great image quality for the price. My only gripe is that they&rsquo;re USB-C, not Thunderbolt, so I can&rsquo;t daisy-chain them.Monitor arm &mdash; VIVO Dual MountI don&rsquo;t really move my monitors, so this cheap arm w\",\"classification_terms\":[\"uses\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/likes/music/\",\"status\":200,\"title\":\"Music I Like — Unindented\",\"word_count\":485,\"summary_text\":\"Music I Like — Unindented Music I Like — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelMusic I LikeHere&rsquo;s a bunch of albums I like, sorted by artist.A Tribe Called QuestThe Low End Theory (1991)Agate RollingsDiomede (2016)Amy WinehouseBack to Black (2006)Aretha FranklinI Never Loved a Man the Way I Love You (1967)BeyoncéLemonade (2016)Bob DylanHighway 61 Revisited (1965)Bob DylanBlonde on Blonde (1966)Bob DylanBlood on the Tracks (1975)Bob Seger & the Si\",\"classification_terms\":[\"likes/music\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/likes/movies/\",\"status\":200,\"title\":\"Movies I Like — Unindented\",\"word_count\":1245,\"summary_text\":\"Movies I Like — Unindented Movies I Like — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelMovies I LikeHere&rsquo;s a bunch of movies I like, sorted alphabetically.8 Mile (2002)12 Angry Men (1957)The 39 Steps (1935)The 40 Year-Old Virgin (2005)2001: A Space Odyssey (1968)The Abyss (1989)Ace Ventura: Pet Detective (1994)Ace Ventura: When Nature Calls (1995)The Addams Family (1991)Addams Family Values (1993)Akira (1988)Aladdin (1992)Alice in Wonderland (1951)Alien\",\"classification_terms\":[\"likes/movies\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/about/style-guide/\",\"status\":200,\"title\":\"Style Guide — Unindented\",\"word_count\":2588,\"summary_text\":\"Style Guide — Unindented Style Guide — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelStyle GuideThis is a guide to the styles and patterns used throughout the site.TitleThe main page header of this guide is an h1 element. Any header elements may include links.SectionsThe secondary header above is an h2 element, which may be used for any form of important page-level header. Consider using an h2 unless you need a header level of less importance, or as a sub-head\",\"classification_terms\":[\"about/style-guide\",\"about\",\"blog\",\"links\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/blog/pixel-art-scaling-comparison-part-2/\",\"status\":200,\"title\":\"Pixel Art Scaling Comparison — Part 2 — Unindented\",\"word_count\":399,\"summary_text\":\"Pixel Art Scaling Comparison — Part 2 — Unindented Pixel Art Scaling Comparison — Part 2 — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelFriday, April 18, 2014 — 2 minute readPixel ArtPixel Art Scaling Comparison — Part 2I&rsquo;ve been playing with a few other scaling algorithms in the 2dimagefilter project. They produce even more impressive results than the previous batch.Part 1 showcased the Eagle, SuperEagle, SaI, and SuperSaI algorithms. I&rsquo;m continuing here with EPX/Scale, H\",\"classification_terms\":[\"blog/pixel-art-scaling-comparison-part-2\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/tags/pixel-art/\",\"status\":200,\"title\":\"Pixel Art — Unindented\",\"word_count\":70,\"summary_text\":\"Pixel Art — Unindented Pixel Art — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelPixel ArtLatest articlesPixel Art Scaling Comparison — Part 2Friday, April 18, 2014 — 2 minute readPixel ArtPixel Art Scaling Comparison — Part 1Friday, April 11, 2014 — 2 minute readPixel ArtCompare Two Images Side-by-SideWednesday, April 9, 2014CanvasPixel ArtZoom into an ImageMonday, April 7, 2014CanvasPixel ArtRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez\",\"classification_terms\":[\"tags/pixel-art\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/blog/pixel-art-scaling-comparison-part-1/\",\"status\":200,\"title\":\"Pixel Art Scaling Comparison — Part 1 — Unindented\",\"word_count\":372,\"summary_text\":\"Pixel Art Scaling Comparison — Part 1 — Unindented Pixel Art Scaling Comparison — Part 1 — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelFriday, April 11, 2014 — 2 minute readPixel ArtPixel Art Scaling Comparison — Part 1I&rsquo;ve been playing with a few scaling algorithms in the 2dimagefilter project. They produce impressive results when fed pixel art, and the fact that emulators can run them in real-time is just mind-boggling.Here I&rsquo;ve chosen a bunch of images to showcase the\",\"classification_terms\":[\"blog/pixel-art-scaling-comparison-part-1\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/blog/trigonometry-in-sass/\",\"status\":200,\"title\":\"Trigonometry in Sass — Unindented\",\"word_count\":787,\"summary_text\":\"Trigonometry in Sass — Unindented Trigonometry in Sass — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelFriday, February 7, 2014 — 4 minute readCSSMathTrigonometry in SassHave you ever found yourself needing trigonometric functions like sine, cosine, and tangent when writing your Sass stylesheets? Ok, probably not, but the day may come, and you&rsquo;ll be glad you read this.Update 2020-01-17: Dart Sass 1.25.0 finally added trigonometric functions to the built-in sass:m\",\"classification_terms\":[\"blog/trigonometry-in-sass\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/tags/css/\",\"status\":200,\"title\":\"CSS — Unindented\",\"word_count\":58,\"summary_text\":\"CSS — Unindented CSS — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelCSSLatest articlesLorenz Attractor with CSSSaturday, February 15, 2014CSSMath3D Shapes with CSSSaturday, February 8, 2014CSSMathTrigonometry in SassFriday, February 7, 2014 — 4 minute readCSSMathGitHub Ribbon Using CSS TransformsSunday, January 12, 2014 — 4 minute readCSSGitHubRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserve\",\"classification_terms\":[\"tags/css\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/blog/github-ribbon-using-css-transforms/\",\"status\":200,\"title\":\"GitHub Ribbon Using CSS Transforms — Unindented\",\"word_count\":844,\"summary_text\":\"GitHub Ribbon Using CSS Transforms — Unindented GitHub Ribbon Using CSS Transforms — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelSunday, January 12, 2014 — 4 minute readCSSGitHubGitHub Ribbon Using CSS TransformsYou know those &lsquo;Fork me on GitHub&rsquo; ribbons that you often see on websites for open source projects? Tom Preston-Werner released them in December 2008! Gosh, I feel old.I like the idea behind the ribbon. It&rsquo;s an easy way of telling your users that this sof\",\"classification_terms\":[\"blog/github-ribbon-using-css-transforms\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2},{\"path\":\"/tags/github/\",\"status\":200,\"title\":\"GitHub — Unindented\",\"word_count\":37,\"summary_text\":\"GitHub — Unindented GitHub — Unindented (()=>{const{classList:t}=document.documentElement,n=document.querySelector('meta[name=\\\"color-scheme\\\"]'),e=localStorage.getItem(\\\"color-scheme\\\"),s=window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches,o=e===\\\"dark\\\"||!e&&s,i=t.toggle(\\\"dark\\\",o)?\\\"dark\\\":\\\"light\\\";n.setAttribute(\\\"content\\\",i)})()Skip to main contentUnindentedAboutBlogPlaygroundToggle color schemeOpen search dialogSearch Search CancelGitHubLatest articlesGitHub Ribbon Using CSS TransformsSunday, January 12, 2014 — 4 minute readCSSGitHubRSSEmailMastodonGitHubLinkedInAll content by Daniel Perez Alvarez unless otherwise noted. Some rights reserved.\",\"classification_terms\":[\"tags/github\",\"about\",\"blog\"],\"external_refs\":[],\"depth\":2}]",
        "score_reasons_json": "[]",
        "route_domain": "unindented.org",
        "display_domain": "unindented.org"
    },
    "explainability": {
        "summary": "unindented.org 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": "100/100"
            },
            {
                "label": "Traffic confidence",
                "value": "Solid confidence",
                "tone": "good",
                "detail": "73/100"
            },
            {
                "label": "Crawler access",
                "value": "Clean visibility",
                "tone": "good",
                "detail": null
            }
        ],
        "weighted_contributions": [
            {
                "label": "Quality system",
                "points": "+32.0",
                "tone": "good",
                "detail": "Technical quality, crawl depth, page structure, and implementation hygiene. Current subsystem score: 94/100."
            },
            {
                "label": "Reputation system",
                "points": "+15.3",
                "tone": "caution",
                "detail": "Authority, search visibility, reach, engagement, and registry stability. Current subsystem score: 45/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": "-15.0",
                "tone": "risk",
                "detail": "Safety thresholds capped the final score until the risk profile improves."
            }
        ],
        "evidence_cards": [
            {
                "label": "Authority and trust",
                "value": "46/100 · trust 77/100",
                "tone": "caution",
                "detail": "209 monthly visitors, 84 organic keywords, brand completeness 66/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": "19.0 years old",
                "tone": "good",
                "detail": "Stability 100/100 · age 19.0 years · registrar DreamHost, LLC · expires in 366 days."
            },
            {
                "label": "Safety and fraud posture",
                "value": "Safety 100/100 · fraud 3/100",
                "tone": "good",
                "detail": "Primary tag T · safety 100/100 · fraud 3/100."
            }
        ],
        "positives": [
            "Established domain age: 19.0 years.",
            "Low registrar / ownership churn with solid registry stability.",
            "Healthy crawl quality and on-page completeness.",
            "Registry history looks stable, which supports legitimacy and trust.",
            "The domain has been registered for years, which usually improves trust confidence.",
            "HTTPS is working, so the site clears a basic transport-security check."
        ],
        "risks": [],
        "freshness": [
            {
                "label": "Crawl evidence",
                "value": "2026-03-17 07:38:08",
                "tone": "risk",
                "detail": "Crawl and page content sample. Age: 27d ago."
            },
            {
                "label": "WHOIS snapshot",
                "value": "2026-03-17 07:38:08",
                "tone": "risk",
                "detail": "Registry profile and stability signals. Age: 27d ago."
            },
            {
                "label": "Keyword view",
                "value": "2026-04-13 16:25:06",
                "tone": "good",
                "detail": "Estimated visibility until tracked keyword snapshots exist. Age: 0s ago."
            },
            {
                "label": "Rank history",
                "value": "2026-04-13 16:25:06",
                "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": 79,
        "fraud_clamp_penalty": 15,
        "final_score": 64
    },
    "insight_snapshot": {
        "version": 1,
        "generated_at": "2026-04-13T16:25:06+00:00",
        "domain": "unindented.org",
        "display_name": "Unindented",
        "is_tracked": false,
        "is_estimated": true,
        "overall_score": 64,
        "authority_score": 46,
        "trust_score": 77,
        "safety_score": 100,
        "fraud_score": 3,
        "confidence_score": 100,
        "traffic_confidence": 73,
        "last_crawled_at": "2026-03-17 07:38:08",
        "crawl_blocked": false,
        "summary": "unindented.org 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": "100/100"
            },
            {
                "label": "Traffic confidence",
                "value": "Solid confidence",
                "tone": "good",
                "detail": "73/100"
            },
            {
                "label": "Crawler access",
                "value": "Clean visibility",
                "tone": "good",
                "detail": null
            }
        ],
        "top_positive_signals": [
            "Established domain age: 19.0 years.",
            "Low registrar / ownership churn with solid registry stability.",
            "Healthy crawl quality and on-page completeness.",
            "Registry history looks stable, which supports legitimacy and trust.",
            "The domain has been registered for years, which usually improves trust confidence."
        ],
        "top_risk_signals": [],
        "freshness": [
            {
                "label": "Crawl evidence",
                "value": "2026-03-17 07:38:08",
                "tone": "risk",
                "detail": "Crawl and page content sample. Age: 27d ago."
            },
            {
                "label": "WHOIS snapshot",
                "value": "2026-03-17 07:38:08",
                "tone": "risk",
                "detail": "Registry profile and stability signals. Age: 27d ago."
            },
            {
                "label": "Keyword view",
                "value": "2026-04-13 16:25:06",
                "tone": "good",
                "detail": "Estimated visibility until tracked keyword snapshots exist. Age: 0s ago."
            },
            {
                "label": "Rank history",
                "value": "2026-04-13 16:25:06",
                "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": "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-13T17:53:49+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/unindented.org/refresh",
        "isGuestCooldown": false,
        "cooldownSeconds": 0
    },
    "urlscan_report": {
        "domain": "unindented.org",
        "status": "idle",
        "submitted_at": null,
        "completed_at": null,
        "last_checked_at": null,
        "last_error": "",
        "submitted_url": "https://unindented.org/",
        "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
    }
}