Automatically create shortlinks for your Astro site
at main 236 lines 5.5 kB view raw view rendered
1# astro-shortlinks 2 3Automatically create shortlinks for your [Astro](https://astro.build) site. This 4integration hooks into your build process to generate short URLs for your pages 5using various shortlink services. 6 7## Installation 8 9```bash 10npm install astro-shortlinks 11# or 12pnpm add astro-shortlinks 13# or 14yarn add astro-shortlinks 15``` 16 17## Basic Usage 18 19Add the integration to your `astro.config.mjs`: 20 21```javascript 22import { defineConfig } from "astro/config"; 23import shortlinks, { chhotoUrl } from "astro-shortlinks"; 24 25export default defineConfig({ 26 site: "https://example.com", // Required for shortlinks 27 integrations: [ 28 shortlinks( 29 chhotoUrl({ 30 domain: "https://short.example.com", 31 apiKey: process.env.CHHOTO_API_KEY, 32 }), 33 { 34 getPageMapping: (pages) => 35 pages.map((page) => ({ 36 longlink: page.toString(), 37 shortlink: page.pathname.replace(/^\//, ""), 38 })), 39 } 40 ), 41 ], 42}); 43``` 44 45## Built-in Shortlinkers 46 47### chhoto-url 48 49Creates shortlinks using a 50[chhoto-url](https://github.com/SinTan1729/chhoto-url) instance. 51 52```javascript 53import { chhotoUrl } from "astro-shortlinks"; 54 55const shortlinker = chhotoUrl({ 56 domain: "https://short.example.com", 57 apiKey: process.env.CHHOTO_API_KEY, // Optional 58 resetHits: false, // Reset hit counter when updating links (default: false) 59}); 60``` 61 62### worker-links 63 64Creates shortlinks using a [worker-links](https://github.com/erisa/worker-links) 65Cloudflare Worker. 66 67```javascript 68import { workerLinks } from "astro-shortlinks"; 69 70const shortlinker = workerLinks({ 71 domain: "https://worker-links.example.workers.dev", 72 secret: process.env.WORKER_LINKS_SECRET, // Required 73}); 74``` 75 76### multi-shortlinker 77 78Runs multiple shortlinkers in sequence, to create shortlinks on multiple 79services. 80 81```javascript 82import { multiShortlinker, chhotoUrl, workerLinks } from "astro-shortlinks"; 83 84const shortlinker = multiShortlinker([ 85 chhotoUrl({ 86 domain: "https://short1.example.com", 87 apiKey: process.env.CHHOTO_API_KEY, 88 }), 89 workerLinks({ 90 domain: "https://short2.example.workers.dev", 91 secret: process.env.WORKER_LINKS_SECRET, 92 }), 93 // Add more shortlinkers as needed 94]); 95``` 96 97## Configuration 98 99The second argument for `shortlinks` provides general configuration for 100shortlinkers. 101 102### `getPageMapping` 103 104The `getPageMapping` function is required and determines how your page URLs are 105mapped to shortlinks: 106 107```javascript 108{ 109 getPageMapping: (pages) => { 110 // pages is an array of URL objects 111 return pages.map((page) => ({ 112 longlink: page.toString(), // Full URL of the page 113 shortlink: page.pathname.replace(/^\//, ""), // Path without leading slash 114 })); 115 }; 116} 117``` 118 119You can customize this to: 120 121- Use custom shortlink patterns 122- Filter out certain pages 123- Add custom prefixes or suffixes 124 125### Example: Custom Shortlink Mapping 126 127```javascript 128{ 129 getPageMapping: (pages) => { 130 return pages 131 .filter((page) => !page.pathname.startsWith("/admin")) 132 .map((page) => ({ 133 longlink: page.toString(), 134 shortlink: "blog/" + page.pathname.split("/").pop(), 135 })); 136 }; 137} 138``` 139 140## Creating a Custom Shortlinker 141 142You can create your own shortlinker by implementing the `Shortlinker` interface: 143 144```javascript 145import type { Shortlinker } from 'astro-shortlinks'; 146 147interface MyShortlinkerOptions { 148 apiKey: string; 149 domain: string; 150} 151 152export const myShortlinker = ({ apiKey, domain }: MyShortlinkerOptions): Shortlinker => { 153 return { 154 name: 'my-shortlinker', 155 async run(mappings, logger) { 156 try { 157 // Your implementation here 158 for (const { longlink, shortlink } of mappings) { 159 const response = await fetch(`${domain}/api/create`, { 160 method: 'POST', 161 headers: { 162 'Authorization': `Bearer ${apiKey}`, 163 'Content-Type': 'application/json' 164 }, 165 body: JSON.stringify({ 166 short: shortlink, 167 long: longlink 168 }) 169 }); 170 171 if (!response.ok) { 172 logger.error(`Failed to create shortlink ${shortlink}: ${response.statusText}`); 173 return false; 174 } 175 } 176 177 logger.info(`Successfully created ${mappings.length} shortlinks`); 178 } catch (error) { 179 logger.error(`Error creating shortlinks: ${error}`); 180 return false; 181 } 182 } 183 }; 184}; 185``` 186 187### Shortlinker Interface 188 189```typescript 190interface Shortlinker { 191 name: string; 192 run( 193 mappings: PageMapping[], 194 logger: AstroIntegrationLogger 195 ): Promise<void | boolean>; 196} 197 198type PageMapping = { 199 longlink: string; // Full URL to redirect to 200 shortlink: string; // Short URL path 201}; 202``` 203 204**Important:** 205 206- Return `false` from `run()` if the shortlinker fails and provides its own 207 logging 208- The logger is namespaced to your shortlinker for better debugging 209- Handle errors gracefully and provide meaningful log messages 210- Consider supporting both creating new links and updating existing ones 211 212## Requirements 213 214- Astro 5.0.0 or higher 215- The `site` configuration option must be set in your Astro config 216 217## Development 218 219A [Nix flake](./flake.nix) is provided to easily set up a development 220environment, otherwise read it to see the current required system dependencies 221for developing astro-shortlinks. 222 223```bash 224# Install dependencies 225pnpm install 226 227# Build the project 228pnpm build 229 230# Development mode with TypeScript watch 231pnpm dev 232``` 233 234## License 235 236[MIT License](./LICENSE)