The code and data behind xeiaso.net
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(index): replace GitHub sponsor iframe with styled sponsor card

Replace the embedded GitHub Sponsors iframe on the homepage with a
custom card component linking to Patreon, GitHub Sponsors, and the
Sponsor Panel. Card styling uses the Gruvbox palette with a gradient
accent line inspired by the sponsor-panel app.

Assisted-by: Claude Opus 4.6 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>

Xe Iaso 6b5d46d1 8b951603

+131 -65
+131 -65
lume/src/index.jsx
··· 1 1 export const layout = "base.njk"; 2 2 export const date = "2012-12-21"; 3 3 4 + const GitHubIconSmall = () => ( 5 + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> 6 + <path stroke="none" d="M0 0h24v24H0z" fill="none" /> 7 + <path d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" /> 8 + </svg> 9 + ); 10 + 11 + const PatreonIconSmall = () => ( 12 + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> 13 + <path stroke="none" d="M0 0h24v24H0z" fill="none" /> 14 + <path d="M20 8.408c-.003 -2.299 -1.746 -4.182 -3.79 -4.862c-2.54 -.844 -5.888 -.722 -8.312 .453c-2.939 1.425 -3.862 4.545 -3.896 7.656c-.028 2.559 .22 9.297 3.92 9.345c2.75 .036 3.159 -3.603 4.43 -5.356c.906 -1.247 2.071 -1.599 3.506 -1.963c2.465 -.627 4.146 -2.626 4.142 -5.273z" /> 15 + </svg> 16 + ); 17 + 18 + const StarIconSmall = () => ( 19 + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> 20 + <path stroke="none" d="M0 0h24v24H0z" fill="none" /> 21 + <path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873z" /> 22 + </svg> 23 + ); 24 + 25 + const SponsorCard = () => ( 26 + <div className="relative my-6 mx-auto max-w-xl overflow-hidden rounded-md border border-solid border-fg-4 shadow-sm dark:border-fgDark-4 bg-bg-2 dark:bg-bgDark-2"> 27 + <div className="h-[2px] w-full dark:hidden" style={{ background: "linear-gradient(90deg, #d65d0e, #b16286)" }} /> 28 + <div className="hidden h-[2px] w-full dark:block" style={{ background: "linear-gradient(90deg, #fe8019, #d3869b)" }} /> 29 + <div className="px-6 py-5 text-center"> 30 + <h3 className="mb-2 text-xl font-semibold font-serif text-fg-0 dark:text-fgDark-0"> 31 + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="inline-block align-text-bottom mr-1"> 32 + <path stroke="none" d="M0 0h24v24H0z" fill="none" /> 33 + <path d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" /> 34 + </svg> 35 + Support My Work 36 + </h3> 37 + <p className="mb-4 text-sm text-fg-3 dark:text-fgDark-1"> 38 + Help me keep creating technical content and open source software. 39 + </p> 40 + <div className="flex flex-wrap items-center justify-center gap-3"> 41 + <a 42 + href="https://patreon.com/cadey" 43 + target="_blank" 44 + rel="noopener noreferrer" 45 + className="inline-flex items-center gap-2 rounded-xl border-0 bg-orange-light px-4 py-2 text-sm font-medium text-white no-underline shadow-sm transition-all duration-200 hover:-translate-y-px hover:bg-orange-dark hover:text-white hover:no-underline hover:shadow-md visited:text-white visited:hover:bg-orange-dark visited:hover:text-white dark:bg-orangeDark-light dark:hover:bg-orangeDark-dark" 46 + > 47 + <PatreonIconSmall /> Patreon 48 + </a> 49 + <a 50 + href="https://github.com/sponsors/Xe" 51 + target="_blank" 52 + rel="noopener noreferrer" 53 + className="inline-flex items-center gap-2 rounded-xl border-0 bg-fg-0 px-4 py-2 text-sm font-medium text-white no-underline shadow-sm transition-all duration-200 hover:-translate-y-px hover:bg-fg-1 hover:text-white hover:no-underline hover:shadow-md visited:text-white visited:hover:bg-fg-1 visited:hover:text-white dark:bg-purpleDark-light dark:hover:bg-purpleDark-dark" 54 + > 55 + <GitHubIconSmall /> GitHub Sponsors 56 + </a> 57 + <a 58 + href="https://sponsors.xeiaso.net" 59 + target="_blank" 60 + rel="noopener noreferrer" 61 + className="inline-flex items-center gap-2 rounded-xl border-0 bg-purple-light px-4 py-2 text-sm font-medium text-white no-underline shadow-sm transition-all duration-200 hover:-translate-y-px hover:bg-purple-dark hover:text-white hover:no-underline hover:shadow-md visited:text-white visited:hover:bg-purple-dark visited:hover:text-white dark:bg-blueDark-light dark:hover:bg-blueDark-dark" 62 + > 63 + <StarIconSmall /> Sponsor Panel 64 + </a> 65 + </div> 66 + </div> 67 + </div> 68 + ); 69 + 4 70 export default ({ search, resume, notableProjects, contactLinks }, { date }) => { 5 - const dateOptions = { year: "numeric", month: "2-digit", day: "2-digit" }; 71 + const dateOptions = { year: "numeric", month: "2-digit", day: "2-digit" }; 6 72 7 - return ( 8 - <> 9 - <h1 class="text-3xl mb-4">{resume.name}</h1> 10 - <p class="text-xl mb-4">{resume.tagline} - {resume.location.city}, {resume.location.country}</p> 11 - <div className="my-4 flex space-x-4 rounded-md border border-solid border-fg-4 bg-bg-2 p-3 dark:border-fgDark-4 dark:bg-bgDark-2 max-w-full min-h-fit"> 12 - <div className="flex max-h-16 shrink-0 items-center justify-center self-center"> 13 - <img 14 - style="max-height:6rem" 15 - alt="A pink haired orca character" 16 - loading="lazy" 17 - src="/static/img/avatar.png" 18 - /> 19 - </div> 20 - <div className="convsnippet min-w-0 self-center"> 21 - <p className=""> 22 - I'm Xe Iaso, I'm a technical educator, <a href="/talks/">conference speaker</a>, <a href="https://twitch.tv/princessxen">twitch streamer</a>, vtuber, and philosopher that focuses on ways to help make technology easier to understand and do cursed things in the process. I live in {resume.location.city} with my husband and I do developer relations professionally. I am an avid writer for my <a href="/blog">blog</a>, where I have over 400 articles. I regularly experiment with new technologies and find ways to mash them up with old technologies for my own amusement. 23 - </p> 24 - </div> 25 - </div> 73 + return ( 74 + <> 75 + <h1 class="text-3xl mb-4">{resume.name}</h1> 76 + <p class="text-xl mb-4">{resume.tagline} - {resume.location.city}, {resume.location.country}</p> 77 + <div className="my-4 flex space-x-4 rounded-md border border-solid border-fg-4 p-3 dark:border-fgDark-4 bg-bg-2 dark:bg-bgDark-2 max-w-full min-h-fit"> 78 + <div className="flex max-h-16 shrink-0 items-center justify-center self-center"> 79 + <img 80 + style="max-height:6rem" 81 + alt="A pink haired orca character" 82 + loading="lazy" 83 + src="/static/img/avatar.png" 84 + /> 85 + </div> 86 + <div className="convsnippet min-w-0 self-center"> 87 + <p className=""> 88 + I'm Xe Iaso, I'm a technical educator, <a href="/talks/">conference speaker</a>, <a href="https://twitch.tv/princessxen">twitch streamer</a>, vtuber, and philosopher that focuses on ways to help make technology easier to understand and do cursed things in the process. I live in {resume.location.city} with my husband and I do developer relations professionally. I am an avid writer for my <a href="/blog">blog</a>, where I have over 400 articles. I regularly experiment with new technologies and find ways to mash them up with old technologies for my own amusement. 89 + </p> 90 + </div> 91 + </div> 26 92 27 - <h2 class="text-2xl mb-4">Recent Articles</h2> 28 - <ul class="list-disc ml-4 mb-4"> 29 - {search.pages("index=true", "order date=desc", 8).map((post) => { 30 - const url = post.redirect_to ? post.redirect_to : post.url; 31 - return ( 32 - <li> 33 - <time datetime={date(post.date)} className="font-mono">{post.date.toLocaleDateString("en-US", dateOptions)}</time> -{" "} 34 - <a href={url}>{post.title}</a> 35 - </li> 36 - ); 37 - })} 38 - </ul> 93 + <h2 class="text-2xl mb-4">Recent Articles</h2> 94 + <ul class="list-disc ml-4 mb-4"> 95 + {search.pages("index=true", "order date=desc", 8).map((post) => { 96 + const url = post.redirect_to ? post.redirect_to : post.url; 97 + return ( 98 + <li> 99 + <time datetime={date(post.date)} className="font-mono">{post.date.toLocaleDateString("en-US", dateOptions)}</time> -{" "} 100 + <a href={url}>{post.title}</a> 101 + </li> 102 + ); 103 + })} 104 + </ul> 39 105 40 - <iframe src="https://github.com/sponsors/Xe/card" title="Sponsor Xe" height="225" width="600" style="border: 0;" className="mx-auto" /> 106 + <SponsorCard /> 41 107 42 - <h2 class="text-2xl mb-4">Notable Publications</h2> 43 - <ul class="list-disc ml-4 mb-4"> 44 - {resume.notablePublications.map((publication) => ( 45 - <li> 46 - <a href={publication.url}>{publication.title}</a><br />{publication.description} 47 - </li> 48 - ))} 49 - </ul> 108 + <h2 class="text-2xl mb-4">Notable Publications</h2> 109 + <ul class="list-disc ml-4 mb-4"> 110 + {resume.notablePublications.map((publication) => ( 111 + <li> 112 + <a href={publication.url}>{publication.title}</a><br />{publication.description} 113 + </li> 114 + ))} 115 + </ul> 50 116 51 - <h2 class="text-2xl mb-4">Highlighted Projects</h2> 52 - <ul class="list-disc ml-4 mb-4"> 53 - {notableProjects.map((project) => ( 54 - <li> 55 - <a href={project.url}>{project.title}</a> - {project.description} 56 - </li> 57 - ))} 58 - </ul> 117 + <h2 class="text-2xl mb-4">Highlighted Projects</h2> 118 + <ul class="list-disc ml-4 mb-4"> 119 + {notableProjects.map((project) => ( 120 + <li> 121 + <a href={project.url}>{project.title}</a> - {project.description} 122 + </li> 123 + ))} 124 + </ul> 59 125 60 - <h2 class="text-2xl mb-4">Quick Links</h2> 61 - <ul class="list-disc ml-4 mb-4"> 62 - {contactLinks.map((link) => ( 63 - <li> 64 - <a rel="me" target="_blank" href={link.url}>{link.title}</a> 65 - </li> 66 - ))} 67 - </ul> 126 + <h2 class="text-2xl mb-4">Quick Links</h2> 127 + <ul class="list-disc ml-4 mb-4"> 128 + {contactLinks.map((link) => ( 129 + <li> 130 + <a rel="me" target="_blank" href={link.url}>{link.title}</a> 131 + </li> 132 + ))} 133 + </ul> 68 134 69 - <p class="mb-4">Looking for someone for your team? Check <a href="/signalboost">here</a>.</p> 135 + <p class="mb-4">Looking for someone for your team? Check <a href="/signalboost">here</a>.</p> 70 136 71 - <div class="flex flex-wrap items-start justify-center p-5"> 72 - {resume.buzzwords.map((buzzword) => ( 73 - <span class="m-2 p-2 text-sm bg-bg-1 dark:bg-bgDark-1 text-fg-1 dark:text-fgDark-1 rounded-lg">{buzzword}</span> 74 - ))} 75 - </div> 76 - </> 77 - ); 137 + <div class="flex flex-wrap items-start justify-center p-5"> 138 + {resume.buzzwords.map((buzzword) => ( 139 + <span class="m-2 p-2 text-sm bg-bg-1 dark:bg-bgDark-1 text-fg-1 dark:text-fgDark-1 rounded-lg">{buzzword}</span> 140 + ))} 141 + </div> 142 + </> 143 + ); 78 144 }