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.astro and pulls data from yukina.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.

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.

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 .title class so the colored bar and typography match the existing section headings.
  • Category class reuse: leveraging .category keeps 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 friendLinks array in yukina.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.

Friend Links for Blog

Author

Shayne Wong

Publish Date

11 - 18 - 2025

License

Shayne Wong

Avatar
Shayne Wong

All time is no time when it is past.