AT Protocol Link Shortener#
A server-side link shortening service powered by your Linkat board. No database required - all links are fetched directly from AT Protocol!
✨ Features#
- Zero Configuration Database: Uses your existing Linkat board as the data source
- ⚡ Hash-Based Shortcodes: Automatic 6-character codes generated from URLs (e.g.,
/a3k9zx) - 🚀 Server-Side Only: Pure API-based, no client UI needed
- 🎯 Smart Redirects: Instant HTTP 301 redirects to your target URLs
- 🔍 Automatic PDS Discovery: Resolves your PDS endpoint via Slingshot
- ⚡ Built-in Cache: 5-minute cache for optimal performance
- 🎨 Tailwind CSS 4: Modern styling with the latest Tailwind version
🚀 Quick Start#
1. Clone and Install#
git clone git@github.com:ewanc26/atproto-shortlink # or git@tangled.sh:ewancroft.uk/atproto-shortlink
cd atproto-shortlink
npm install
2. Configure Your DID#
Create a .env file:
cp .env.example .env
Edit .env and add your AT Protocol DID:
# Find your DID at https://pdsls.dev/ by entering your handle
ATPROTO_DID=did:plc:your-did-here
How to find your DID:
- Visit PDSls
- Enter your AT Protocol handle (e.g.,
yourname.bsky.social) - Copy the
did:plc:...identifier
3. Set Up Your Linkat Board#
If you don't have a Linkat board yet:
- Visit https://linkat.blue
- Create a board with your links
- Add your links with titles and emojis
The shortener will automatically generate unique codes for each URL!
4. Test Your Configuration (Optional)#
Run the configuration test to verify everything is set up correctly:
npm run test:config
This will:
- ✅ Check if
.envexists and is configured - ✅ Validate your DID format
- ✅ Test PDS connectivity
- ✅ Verify your Linkat board is accessible
- ✅ Show a preview of your first few links
5. Run the Server#
npm run dev
Visit http://localhost:5173 to see your service running!
📖 Usage#
Once running, your short links work like this:
# Redirect to your configured URLs
http://localhost:5173/a3k9zx → Redirects to your GitHub
http://localhost:5173/b7m2wp → Redirects to your blog
http://localhost:5173/c4n8qz → Redirects to your portfolio
# View service info
http://localhost:5173/ → Shows API information and available links
# Get JSON list of links
http://localhost:5173/api/links → Returns all short links as JSON
🔧 API Endpoints#
| Endpoint | Method | Description | Response |
|---|---|---|---|
/ |
GET | Service status and link listing | HTML |
/:shortcode |
GET | Redirect to full URL | 301 Redirect |
/api/links |
GET | List all available short links | JSON |
Example API Response#
{
"success": true,
"count": 3,
"links": [
{
"shortcode": "a3k9zx",
"url": "https://github.com/yourname",
"title": "My GitHub Profile",
"emoji": "💻",
"shortUrl": "/a3k9zx"
},
{
"shortcode": "b7m2wp",
"url": "https://yourblog.com",
"title": "Personal Blog",
"emoji": "📝",
"shortUrl": "/b7m2wp"
}
]
}
📝 How Shortcodes Work#
Shortcodes are automatically generated as 6-character base62 hashes from your URLs. Each URL will always produce the same shortcode, ensuring consistency.
- Base62 encoding: Uses 0-9, a-z, A-Z (62 characters)
- Collision-resistant: 62^6 = ~56 billion possible combinations
- Deterministic: Same URL = same shortcode every time
- URL-safe: No special characters needed
🌐 Deployment#
Build for Production#
npm run build
npm run preview # Test the production build locally
Deploy to Platforms#
This project uses @sveltejs/adapter-auto which works with:
- Vercel: Push to GitHub and connect your repo
- Netlify: Push to GitHub and connect your repo
- Cloudflare Pages: Push to GitHub and connect your repo
- Node.js: Use
adapter-nodefor standalone Node servers
For specific platforms, see SvelteKit adapters.
Environment Variables for Deployment#
Make sure to set ATPROTO_DID in your deployment platform's environment variables!
⚙️ Configuration#
| Variable | Required | Description | Example |
|---|---|---|---|
ATPROTO_DID |
✅ Yes | Your AT Protocol DID | did:plc:abc123xyz |
🏗️ How It Works#
- You maintain your links in Linkat (stored in
blue.linkat.boardcollection) - Service fetches on-demand from your AT Protocol PDS via Slingshot resolution
- URLs are shortened using deterministic base62 hash encoding
- Accessing a short link (e.g.,
/a3k9zx) triggers an instant 301 redirect
graph LR
A[User visits /a3k9zx] --> B[Service fetches Linkat data]
B --> C[Looks up shortcode in links]
C --> D[301 Redirect to target URL]
🔒 Security#
- ✅ All Linkat data is public by design
- ✅ No authentication required
- ✅ Read-only access to AT Protocol data
- ✅ No data storage (fetches on-demand with cache)
- ✅ 5-minute cache to prevent abuse
🛠️ Development#
# Install dependencies
npm install
# Start dev server
npm run dev
# Type check
npm run check
# Format code
npm run format
# Check formatting
npm run lint
🎨 Styling with Tailwind CSS 4#
This project uses Tailwind CSS 4 with the new Vite plugin.
Key features:
- ✅ Native CSS imports with
@import 'tailwindcss' - ✅ Faster builds with the Vite plugin
- ✅ Automatic dark mode support
- ✅ No config file needed for basic usage
📦 Tech Stack#
- Framework: SvelteKit 2
- Styling: Tailwind CSS 4
- Runtime: Server-side only (no client JavaScript required)
- Data Source: AT Protocol (
blue.linkat.boardcollection) - PDS Resolution: Slingshot by Microcosm
- Redirects: HTTP 301 (permanent)
- Shortcode Format: Base62 hash encoding
🔧 Troubleshooting#
Having issues? Check the Troubleshooting Guide for common problems and solutions.
Quick checks:
- Run
npm run test:configto verify your setup - Make sure Node.js 18+ is installed:
node --version - Check your DID at pdsls.dev
- Verify your Linkat board at linkat.blue
🤝 Contributing#
Contributions are welcome! Please feel free to submit a Pull Request.
📄 Licence#
AGPLv3 Licence - See LICENCE file for details
Links#
- Linkat - The link board service
- AT Protocol - The underlying protocol
- SvelteKit - The web framework
- Tailwind CSS - CSS framework
- PDSls - Find your DID
- Slingshot - Identity resolver
Made with ❤️ using AT Protocol and Linkat