diff --git a/README.md b/README.md
index 5a0f3d8..bd3ec9f 100644
--- a/README.md
+++ b/README.md
@@ -15,11 +15,13 @@ Your Now page links will be automatically updated from this:
**HTML links** (before):
```html
-tktk
+blog
+gitlab
```
**Markdown links** (before):
```markdown
-[tktk](https://your-blog.com)
+[blog](service-link)
+[gitlab](service-link)
```
to this:
@@ -27,12 +29,16 @@ to this:
**HTML links** (after):
```html
My Latest Post
+Pushed to repository
```
**Markdown links** (after):
```markdown
[My Latest Post](https://your-blog.com/2025/12/my-latest-post)
+[Pushed to repository](https://gitlab.com/username/project)
```
+**New in this fork**: Use service names as link text instead of URLs! Just write `servicename` and the script fills in both the text and URL.
+
## Setup
1. Fork this repo
@@ -76,15 +82,78 @@ export const items = [
## Configuration
-Edit `config.js` to define your content sources. Each item needs:
-- `id`: identifier for logs
-- `regex`: pattern to match your link
-- `getLatest`: async function that fetches and returns latest content
+### Quick Start
-Set `linkFormat` to `'html'` or `'markdown'` depending on your Now page format.
+1. **In your Now page**, use service names as link text:
+```html
+blog
+gitlab
+```
+
+2. **In services.js**, find the service and flip `isActive` to `true`:
+```javascript
+{
+ id: 'gitlab',
+ isActive: true, // just change this!
+ regex: htmlServiceLinkRegex('gitlab'),
+ feedUrl: 'https://gitlab.com/users/your-username/activity.atom',
+ feedType: 'atom',
+}
+```
+
+That's it! No importing, no commenting/uncommenting.
+
+### Files
+
+- **config.js** - Link format setting and filter logic (rarely needs editing)
+- **services.js** - All available services with `isActive` flags (edit this to enable/disable services)
+- **utils.js** - Generic feed handlers and special service logic
+
+### Service Structure
+
+Each service has:
+- `id`: identifier for logs
+- `isActive`: `true` to enable, `false` to disable
+- `regex`: matches service name in your Now page
+- `feedType`: Handler to use (`rss`, `atom`, `json`, or special handler name like `mastodon`)
+- `feedUrl`: Direct feed URL (use this for custom feeds without usernames)
+- `feedUrlTemplate`: URL template with `{userId}` placeholder (use this for standard services)
+- `userId`: Your username/ID (only needed with feedUrlTemplate)
+- Extra params as needed (e.g., `instance`, `steamId`, `traktId`, `showImage`)
+
+**Note**: Use either `feedUrl` (direct) OR `feedUrlTemplate` + `userId` (template). Both work!
+
+Set `linkFormat` in config.js to `'html'` or `'markdown'`.
## Available Functions
+### Code Activity
+- `getSourceTubeActivity(username)` - Forgejo activity on source.tube
+- `getGitLabActivity(username)` - GitLab activity feed
+- `getCodebergActivity(username)` - Codeberg activity feed
+
+### Content Creation
+- `getYouTubeLatestVideo(channelId)` - Latest YouTube video (requires channel ID starting with "UC")
+- `getVimeoLatestVideo(username)` - Latest Vimeo video
+- `getTwitchLatestStream(channel)` - Latest Twitch stream/VOD (via TwitchRSS, no API key needed)
+
+### Gaming
+- `getBackloggdActivity(username, showImage)` - Backloggd game activity with optional cover images
+- `getExophaseActivity(username, showImage)` - Multi-platform gaming achievements
+- `getSteamRecentlyPlayed(steamId)` - Recently played Steam game (requires STEAM_WEBAPI_KEY)
+
+### Books
+- `getGoodreadsActivity(userId, showImage)` - Goodreads activity (requires numeric user ID, not username)
+- `getHardcoverActivity(username)` - Currently reading books via GraphQL API
+
+### Music
+- `getListenBrainzScrobble(username)` - Latest music scrobble (open source Last.fm alternative)
+
+### Social Media
+- `getPixelfedPost(instance, username)` - Latest Pixelfed post from federated instance
+- `getBlueskyPost(handle)` - Latest Bluesky post (note: links not clickable in RSS)
+
+### General/Legacy
- `getRSSItemTitle(feedUrl)` - Standard RSS feeds
- `getJsonFeedItemTitle(feedUrl, showImage)` - JSON feeds
- `getLetterboxdActivity(username, showImage)` - Letterboxd activity
@@ -94,11 +163,17 @@ Set `linkFormat` to `'html'` or `'markdown'` depending on your Now page format.
- `getMastodonPost(feedUrl)` - Latest non-reply Mastodon post
- `getMalojaScrobble(url)` - Latest music scrobble from [maloja](https://github.com/krateng/maloja)
-**Notes:**
+**Important Notes:**
- `showImage` (defaults to `true`) controls whether images/posters are included in the output. Set it to `false` to show text only.
- For Last.fm, use `getRSSItemTitle('https://lfm.xiffy.nl/your-username')` (via [lfm.xiffy.nl](https://lfm.xiffy.nl))
+- **YouTube** requires channel ID (not username), find it in your channel's page source or URL
+- **Goodreads** requires numeric user ID (found in profile URL after `/user/show/`)
+- **Steam** requires Steam ID 64 (convert at https://steamid.io/)
+- **Pixelfed** requires instance domain and username (e.g., `pixelfed.social`, `username`)
-## Trakt
+## API Keys Setup
+
+### Trakt
To get your Trakt slurm key, follow these steps:
@@ -107,7 +182,15 @@ To get your Trakt slurm key, follow these steps:
3. The URL it shows will look something like this: `https://trakt.tv/users/crankle/history.atom?slurm=your-slurm-key`
4. Copy the `slurm` value from the URL and add it as a secret in your Actions settings named `TRAKT_SLURM`.
-There may be a better way to get this key, but this is how I found it.
+### Steam
+
+To get your Steam Web API key:
+
+1. Visit https://steamcommunity.com/dev/apikey
+2. Enter a domain name (can be localhost for personal use)
+3. Agree to the terms and get your API key
+4. Add it to your `.env` file as `STEAM_WEBAPI_KEY` or to Actions secrets
+5. Find your Steam ID 64 at https://steamid.io/ (enter your profile URL)
## Credits
diff --git a/index.js b/index.js
index d2ce2fe..d39ba99 100644
--- a/index.js
+++ b/index.js
@@ -7,6 +7,7 @@ import {
getJsonFeedItemTitle,
getLetterboxdActivity,
getListenBrainzScrobble,
+ getMalojaScrobble,
getMastodonPost,
getRSSItemTitle,
getSourceTubeActivity,
@@ -29,6 +30,7 @@ const feedHandlers = {
'trakt-movie': getTraktMovie,
steam: getSteamRecentlyPlayed,
listenbrainz: getListenBrainzScrobble,
+ maloja: getMalojaScrobble,
hardcover: getHardcoverActivity,
}