Introducing Linkat Directory: A 'Link-in-Bio' Frontend

Right, so I've gone and built Linkat Directory , which is essentially a SvelteKit application for curating and displaying Bluesky profiles and their Linkat boards. Not that I needed to do this, mind you—I already have my links displayed perfectly well through Linkat on my website. But here we are anyway.

The "Why" Behind the Madness

The thing is, I was perfectly content with how my links were working through the existing Linkat system. It integrates nicely with my website , fetches data from my PDS via the AT Protocol, and generally does what it says on the tin. But sometimes you see a gap that doesn't really need filling and think, "You know what? I fancy a bit of reinventing the wheel today."

What drew me in was the idea of creating a more curated directory experience—something that could showcase multiple users' Linkat boards in a clean, responsive interface whilst giving complete control over the presentation. Plus, I'd been meaning to dive deeper into SvelteKit, and this seemed like a reasonable excuse.

What It Actually Does

Linkat Directory pulls profile data directly from the AT Protocol, specifically targeting the blue.linkat.board collection that the original Linkat service uses. The application handles both single-user and multi-user configurations, so you can either showcase your own links or create a proper directory of multiple users.

The setup is refreshingly straightforward:

# Clone and install
git clone git@github.com:ewanc26/linkat-directory.git
cd linkat-directory
npm install

# Configure your users in .env
DIRECTORY_OWNER=did:plc:your-did-here
# or for multiple users:
PUBLIC_LINKAT_USERS=did:plc:user1,did:web:user2

# Optional: Hide the directory owner's card, false by default
HIDE_OWNER_CARD=true

# Optional: Display the user banner, false by default
DISPLAY_USER_BANNER=true

# Optional: Display the user description, false by default
DISPLAY_USER_DESCRIPTION=false

# Required: Set the public origin for prerendering, defaults to http://localhost:5713
PUBLIC_ORIGIN=http://localhost:5713

# Run it
npm run dev

The application dynamically fetches profile information—avatars, display names, descriptions, banners—and presents everything in a clean grid layout. Each user gets their own profile page with their curated links displayed in responsive cards. It's not groundbreaking stuff, but it works well.

The Technical Bits That Went Right

The project structure is fairly sensible, with distinct components for user directories, individual profiles, and link displays. I've used CSS variables throughout for theming, so the whole thing can be restyled without too much faff. The caching system helps avoid hammering the AT Protocol endpoints unnecessarily.

One thing I'm particularly pleased with is how it handles user data. Rather than requiring manual configuration of every detail, it dynamically fetches what it needs from each user's PDS. You provide the DIDs, and the application sorts out the rest—handles, avatars, descriptions, and most importantly, their Linkat boards.

The responsive design adapts well across devices, which was important since people access link directories from all sorts of screens. The card-based layout scales nicely from mobile to desktop without looking stretched or cramped.

Things That Could Be Better

Let's be honest, there are a few rough edges. The configuration system works but isn't terribly user-friendly for non-technical folks. If you're comfortable with environment variables and DIDs, you're golden. If those terms make your eyes glaze over, you might find the setup process a bit daunting.

I've also noticed that the AT Protocol can be a bit inconsistent with response times, which occasionally leads to longer loading periods than I'd like. Not much to be done about that on my end, really.

The Usual Identity Crisis

As I was building this, I couldn't shake the feeling that I was solving a problem that didn't really exist. The original Linkat works brilliantly, and there are plenty of other link-in-bio solutions out there. But sometimes the point isn't to solve a problem—it's to explore how you might solve it differently.

This project gave me a chance to experiment with SvelteKit's server-side rendering, work more deeply with the AT Protocol's data structures, and create something that feels distinctly mine whilst still being useful to others.

Open Source and All That

The entire codebase is available on GitHub under the GNU Affero General Public License Version 3. It's not the most exciting code you'll ever read, but it works, and it's there if you want to poke at it or adapt it for your own purposes.

I've tried to document things reasonably well, though as always with my projects, the comments lean toward British understatement rather than comprehensive technical documentation. If you find something confusing or broken, GitHub issues are welcome.

Final Thoughts

Will this replace the original Linkat for most people? Probably not, and it doesn't need to. But if you want more control over how your link directory looks and behaves, or if you're interested in showcasing multiple users' Linkat boards in a single interface, this might be worth a look.

The whole experience reminded me why I enjoy working with the AT Protocol. The decentralised approach means I can build tools like this without needing to negotiate with APIs or worry about rate limits in the traditional sense. Your data is yours, and applications like this can interact with it cleanly.

Plus, it gave me another excuse to tinker with SvelteKit, which continues to be a pleasant framework to work with. Not the most profound achievement, perhaps, but satisfying in its own small way.

Linkat Directory is available at github.com/ewanc26/linkat-directory. Contributions, complaints, and confused questions all welcome.