Adding a Friend Links Section to an Astro Blog
One of the quickest wins for improving discoverability across personal sites is to surface a small “Friend Links” block that mirrors the existing tag/category cards. Below is the full process I used to ship a Komari Monitor link in the Yukina-based Astro blog you are reading.
Prerequisites
- Astro + Yukina starter already running (the repo lives in
/Users/wangchengan/Documents/blog-astro). - Sidebar lives in
src/components/SideBar.astroand pulls data fromyukina.config.ts. - Comfortable with editing TypeScript configs and Astro components.
Step 1 · Inspect the Sidebar Layout
Open src/components/SideBar.astro and notice the existing sequence of cards: profile → categories → tags. Each block is wrapped in the same onload-animation container, so any new section should mimic that skeleton:
<div
class="onload-animation space-y-2 rounded-3xl bg-[var(--card-color)] p-3"
style="animation-delay: calc(var(--onload-animation-delay) + 2 * var(--onload-animation-interval));"
>
<!-- title + content -->
</div>
Keeping the Friend Links markup close to this pattern is what ensures consistent spacing, card radius, and theme-aware colors.
Step 2 · Extend the Shared Configuration Type
All sidebar data comes from yukina.config.ts, which implements the Configuration interface inside src/types/config.ts. Before defining actual links we need to tell TypeScript that friendLinks is a supported field:
// src/types/config.ts
interface Configuration {
socialLinks: { icon: string; link: string }[];
friendLinks: { name: string; url: string }[];
maxSidebarCategoryChip: number;
Adding this property prevents type errors when we later augment YukinaConfig.
Step 3 · Declare the Links in yukina.config.ts
Now that the interface knows about friendLinks, populate it with any sites you want to highlight. Each entry is simple name + url JSON:
// yukina.config.ts
socialLinks: [
// existing GitHub / Telegram / mail icons…
],
friendLinks: [
{
name: "Komari Monitor",
url: "https://komari.shaynewong.xyz/",
},
],
maxSidebarCategoryChip: 6,
Feel free to append more objects to this array; the UI will loop over each item automatically.
Step 4 · Render the Friend Links Card
Back in src/components/SideBar.astro, read the new config array and render it after the tags block so it appears at the bottom of the left column. The key additions are:
const friendLinks = YukinaConfig.friendLinks ?? [];
<!-- friend links -->
{friendLinks.length !== 0 && (
<div
class="onload-animation space-y-2 rounded-3xl bg-[var(--card-color)] p-3"
style="animation-delay: calc(var(--onload-animation-delay) + 3 * var(--onload-animation-interval));"
>
<div class="title m-[0.375rem]">
<p class="pl-4 text-xl font-bold text-[var(--text-color)]">Friend Links</p>
</div>
<div class="flex flex-col">
{friendLinks.map((link) => (
<a
href={link.url}
target="_blank"
rel="noopener noreferrer"
class="friend-link category flex flex-row items-center rounded-lg px-3 py-2 transition-all hover:bg-[var(--primary-color-lighten)]"
data-tooltip={link.name}
>
<p class="text-[var(--text-color)] transition-all">{link.name}</p>
</a>
))}
</div>
</div>
)}
- Same title styling: reuse the
.titleclass so the colored bar and typography match the existing section headings. - Category class reuse: leveraging
.categorykeeps font families consistent and gives us the hover animation that nudges text to the right. target="_blank"+ rel: Friend links usually open in a new tab, so I preserved that ergonomic touch while keeping security best practices (noopener noreferrer).
Step 5 · Add Tooltip Styling That Honors Themes
To nail the “color-changing tooltip” requirement, I extended the <style> block at the bottom of the file. The idea is to use CSS variables (var(--primary-color) and var(--card-color)) instead of hard-coded hex values so the tooltip adapts naturally in light/dark mode:
.friend-link {
position: relative;
overflow: visible;
}
.friend-link::after {
content: attr(data-tooltip);
position: absolute;
left: 50%;
bottom: calc(100% + 0.35rem);
transform: translate(-50%, 4px);
padding: 0.2rem 0.75rem;
border-radius: 9999px;
background-color: var(--primary-color-lighten);
color: var(--primary-color);
opacity: 0;
transition: all 0.2s ease;
}
.friend-link:hover::after {
opacity: 1;
transform: translate(-50%, -2px);
background-color: var(--primary-color);
color: var(--card-color);
}
Because these variables are defined globally (see src/styles and the theme root), the tooltip now inherits the same hues the rest of the sidebar uses, ensuring the colors flip correctly when toggling dark mode.
Step 6 · Verify in Dev or Build
With the code in place, run either command to confirm everything renders:
pnpm dev
# or
pnpm build && pnpm preview
Open the homepage, scroll to the left column, and you should see the “Friend Links” card beneath Tags. Hovering over “Komari Monitor” displays the pill-shaped tooltip with color transitions matching the rest of the UI. If you add more links, they stack vertically with identical styling.
Bonus · Maintaining the Section
- To reorder or remove entries, edit only the
friendLinksarray inyukina.config.ts; no component changes are necessary. - Want per-link tooltips? Change
data-tooltip={link.name}to any string (e.g.,link.desc ?? link.name) and update your config shape accordingly. - If you add many links, consider borrowing the gradient “View more” overlay logic used in categories/tags to avoid a tall sidebar.
That’s all it takes to bring a polished Friend Links experience into an Astro blog—config-driven data, one extra card, and a sprinkle of CSS for the tooltip glow.