alpha
Login
or
Join now
julien.rbrt.fr
/
glean
Star
3
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
The social RSS reader. Built on AT Protocol.
glean.at
Star
3
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
Pipelines
refactor: improve responsive design
author
Julien Robert
date
2 weeks ago
(Jun 8, 2026, 6:09 PM +0200)
commit
df519dda
df519ddaff85c5659caa9bf5f5839c4db3b479b7
parent
9ed5b26f
9ed5b26f067ffda11a0c6493ffdc73e04bd74e62
+25
-25
11 changed files
Expand all
Collapse all
Unified
Split
internal
tmpl
article_detail.html
articles.html
dashboard.html
feeds.html
partials
annotation-card.html
article-card-expanded.html
article-card.html
feed-item.html
trending-card.html
profile.html
stats.html
+1
-1
internal/tmpl/article_detail.html
Reviewed
···
32
32
{{end}}
33
33
</div>
34
34
35
35
-
<div class="flex items-center gap-2 mt-6">
35
35
+
<div class="flex items-center gap-2 mt-6 flex-wrap">
36
36
<button hx-post="/articles/{{.Article.ID}}/like?bordered=true" hx-target="this" hx-swap="outerHTML"
37
37
title="{{if .HasLiked}}Unlike{{else}}Like{{end}}"
38
38
class="group inline-flex items-center gap-1.5 text-[10px] uppercase tracking-button px-2.5 py-1 rounded-pill transition {{if .HasLiked}}text-spot-red bg-spot-red/15 hover:bg-spot-red/25{{else}}text-spot-text bg-spot-hover hover:text-spot-red hover:bg-spot-red/15{{end}}">
+9
-9
internal/tmpl/articles.html
Reviewed
···
6
6
<div class="flex items-center gap-2 mb-4">
7
7
<a href="/articles" class="text-xs text-spot-secondary hover:text-spot-text transition">← All articles</a>
8
8
</div>
9
9
-
<div class="flex items-center justify-between">
10
10
-
<div class="flex items-center gap-3.5">
9
9
+
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3">
10
10
+
<div class="flex items-center gap-3.5 min-w-0">
11
11
{{template "favicon" dict "src" .Feed.FaviconURL.String "size" "w-10 h-10"}}
12
12
-
<div>
12
12
+
<div class="min-w-0">
13
13
<h1 class="text-2xl font-bold text-spot-text" style="letter-spacing: -0.02em;">{{if .Feed.SiteURL.Valid}}<a href="{{.Feed.SiteURL.String}}" target="_blank" rel="noopener noreferrer" class="hover:text-spot-green transition">{{end}}{{if .Feed.Title.Valid}}{{.Feed.Title.String}}{{else}}{{.Feed.FeedURL}}{{end}}{{if .Feed.SiteURL.Valid}}</a>{{end}}</h1>
14
14
{{if .Feed.SiteURL.Valid}}<a href="{{.Feed.SiteURL.String}}" target="_blank" rel="noopener noreferrer" class="text-xs text-spot-secondary hover:text-spot-green transition">{{.Feed.SiteURL.String}}</a>{{end}}
15
15
</div>
16
16
</div>
17
17
-
<div class="flex items-center gap-3">
17
17
+
<div class="flex items-center gap-3 shrink-0">
18
18
{{if not .IsSubscribed}}
19
19
<form hx-post="/feeds/add" hx-swap="none" hx-on::after-request="if(event.detail.successful) window.location.reload()">
20
20
{{csrfInput .CSRFToken}}
···
33
33
{{if .Feed.Description.Valid}}<p class="text-sm text-spot-secondary mt-3 leading-relaxed">{{.Feed.Description.String}}</p>{{end}}
34
34
</div>
35
35
36
36
-
<div class="flex items-center gap-3 mb-6 flex-wrap">
37
37
-
<form method="GET" action="/articles" class="relative flex-1 min-w-[200px]">
36
36
+
<div class="flex flex-col sm:flex-row sm:items-center gap-3 mb-6">
37
37
+
<form method="GET" action="/articles" class="relative w-full sm:flex-1 sm:min-w-[200px]">
38
38
<input type="text" name="q" value="{{.SearchQuery}}" placeholder="Search articles..."
39
39
class="w-full bg-spot-hover text-spot-text rounded-pill pl-10 pr-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-secondary"
40
40
hx-get="/articles" hx-trigger="keyup changed delay:300ms, search" hx-target="#article-list" hx-swap="innerHTML" hx-include="[name='q']">
···
96
96
</div>
97
97
<p class="text-sm text-spot-secondary mb-6">All your subscribed articles, {{if .SortOldest}}oldest first{{else}}newest first{{end}}.</p>
98
98
99
99
-
<div class="flex items-center gap-3 mb-6 flex-wrap">
100
100
-
<div class="flex items-center gap-1.5">
99
99
+
<div class="flex flex-col sm:flex-row sm:items-center gap-3 mb-6">
100
100
+
<div class="flex items-center gap-1.5 flex-wrap">
101
101
<a href="/articles?{{if not .SortOldest}}sort=oldest{{end}}{{if .Status}}&status={{.Status}}{{end}}"
102
102
class="px-2.5 py-1.5 rounded-pill text-xs transition
103
103
{{if .SortOldest}}bg-spot-active-pill-bg text-spot-active-pill-text font-bold{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}}"
···
113
113
<a href="/articles?{{if .Status}}status={{.Status}}&{{end}}category=__none__{{if .SortOldest}}&sort=oldest{{end}}" class="text-sm px-3 py-1 rounded-pill font-bold {{if eq .Category "__none__"}}bg-spot-active-pill-bg text-spot-active-pill-text{{else}}bg-spot-hover text-spot-secondary hover:text-spot-text{{end}} transition">Uncategorized</a>
114
114
{{end}}
115
115
</div>
116
116
-
<form method="GET" action="/articles" class="relative flex-1 min-w-[180px]">
116
116
+
<form method="GET" action="/articles" class="relative w-full sm:flex-1 sm:min-w-[180px]">
117
117
<input type="text" name="q" value="{{.SearchQuery}}" placeholder="Search articles..."
118
118
class="w-full bg-spot-hover text-spot-text rounded-pill pl-8 pr-3 py-1.5 text-xs focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-secondary"
119
119
hx-get="/articles" hx-trigger="keyup changed delay:300ms, search" hx-target="#article-list" hx-swap="innerHTML" hx-include="[name='q']">
+1
-1
internal/tmpl/dashboard.html
Reviewed
···
1
1
{{define "dashboard.html"}}
2
2
-
<div class="flex items-center justify-between mb-2">
2
2
+
<div class="flex items-center justify-between mb-2 flex-wrap gap-2">
3
3
<h1 class="text-2xl font-bold text-spot-text" style="letter-spacing: -0.02em;">Dashboard</h1>
4
4
{{if gt .SubscriptionCount 0}}
5
5
<div class="flex gap-4 text-sm">
+1
-1
internal/tmpl/feeds.html
Reviewed
···
1
1
{{define "feeds.html"}}
2
2
<div class="flex items-center justify-between gap-3 mb-2 flex-wrap">
3
3
<h1 class="text-2xl font-bold text-spot-text" style="letter-spacing: -0.02em;">Feeds <span class="text-base font-normal text-spot-secondary">({{.SubscriptionCount}})</span></h1>
4
4
-
<div class="flex items-center gap-3">
4
4
+
<div class="flex items-center gap-3 flex-wrap">
5
5
<button id="refresh-btn"
6
6
hx-post="/feeds/refresh" hx-target="#feed-list" hx-swap="innerHTML"
7
7
hx-on::before-request="gleanRefreshStart()"
+1
-1
internal/tmpl/partials/annotation-card.html
Reviewed
···
1
1
{{define "annotation-card.html"}}
2
2
-
<div id="annotation-{{.annotation.ID}}" class="bg-spot-surface rounded-xl p-5 border border-spot-divider">
2
2
+
<div id="annotation-{{.annotation.ID}}" class="bg-spot-surface rounded-xl p-4 sm:p-5 border border-spot-divider">
3
3
{{if .annotation.ArticleURL}}
4
4
<div class="text-xs mb-3 flex items-center gap-2">
5
5
{{if .annotation.ArticleID.Valid}}<a href="/articles/{{.annotation.ArticleID.Int64}}" class="text-spot-green hover:text-spot-text transition truncate inline-flex items-center gap-1">
+1
-1
internal/tmpl/partials/article-card-expanded.html
Reviewed
···
1
1
{{define "article-card-expanded.html"}}
2
2
-
<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" data-expanded="true" class="bg-spot-surface rounded-xl px-5 py-4 shadow-spot relative {{if not .IsRead.Bool}}border-l border-spot-green/80{{end}}">
2
2
+
<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" data-expanded="true" class="bg-spot-surface rounded-xl px-4 sm:px-5 py-4 shadow-spot relative {{if not .IsRead.Bool}}border-l border-spot-green/80{{end}}">
3
3
<div class="flex items-start justify-between gap-4">
4
4
<div class="min-w-0 flex-1">
5
5
<div class="flex items-start gap-2.5">
+3
-3
internal/tmpl/partials/article-card.html
Reviewed
···
1
1
{{define "article-card.html"}}
2
2
-
<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative group {{if not .IsRead.Bool}}border-l border-spot-green/80{{end}}">
2
2
+
<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" class="bg-spot-surface rounded-xl px-4 sm:px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative group {{if not .IsRead.Bool}}border-l border-spot-green/80{{end}}">
3
3
<div class="flex items-start justify-between gap-4">
4
4
<div class="min-w-0 flex-1">
5
5
<div class="flex items-start gap-2.5">
···
17
17
</div>
18
18
<div class="grid grid-cols-1 gap-2 shrink-0 pt-0.5">
19
19
{{template "like-button.html" .}}
20
20
-
<button id="read-btn-{{.ID}}" hx-post="/articles/{{.ID}}/{{if .IsRead.Bool}}unread{{else}}read{{end}}" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" title="{{if .IsRead.Bool}}Mark as unread{{else}}Mark as read{{end}}" class="group inline-flex items-center justify-center gap-1 text-[10px] text-spot-text hover:text-spot-green hover:bg-spot-green/10 hover:border-spot-green/20 uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-surface border border-spot-divider transition w-full">
20
20
+
<button id="read-btn-{{.ID}}" hx-post="/articles/{{.ID}}/{{if .IsRead.Bool}}unread{{else}}read{{end}}" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" title="{{if .IsRead.Bool}}Mark as unread{{else}}Mark as read{{end}}" class="group inline-flex items-center justify-center gap-1 text-[10px] text-spot-text hover:text-spot-green hover:bg-spot-green/10 hover:border-spot-green/20 uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-surface border border-spot-divider transition">
21
21
<svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
22
22
<span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>
23
23
</button>
24
24
{{if .DismissURL}}
25
25
<button hx-post="{{.DismissURL}}" hx-target="closest article" hx-swap="delete" hx-vals='{"{{.DismissField}}": "{{.DismissValue}}"}' title="Remove from recommendations"
26
26
-
class="group inline-flex items-center justify-center gap-1 text-[10px] text-spot-text hover:text-spot-red hover:bg-spot-red/10 hover:border-spot-red/20 uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-surface border border-spot-divider transition w-full">
26
26
+
class="group inline-flex items-center justify-center gap-1 text-[10px] text-spot-text hover:text-spot-red hover:bg-spot-red/10 hover:border-spot-red/20 uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-surface border border-spot-divider transition">
27
27
<svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
28
28
<span>Hide</span>
29
29
</button>
+3
-3
internal/tmpl/partials/feed-item.html
Reviewed
···
1
1
{{define "feed-item.html"}}
2
2
<div id="feed-{{.ID}}" class="contents">
3
3
-
<div class="feed-item px-5 py-4 flex items-center justify-between gap-3 hover:bg-spot-hover-50 transition">
3
3
+
<div class="feed-item px-4 sm:px-5 py-4 flex items-center justify-between gap-3 hover:bg-spot-hover-50 transition">
4
4
<a href="/articles?feed={{.FeedURL}}" class="min-w-0 flex-1 flex items-center gap-3">
5
5
{{template "favicon" dict "src" .FaviconURL.String "size" "w-5 h-5"}}
6
6
<div class="min-w-0 flex-1">
···
29
29
</form>
30
30
</div>
31
31
</div>
32
32
-
<div id="feed-edit-{{.ID}}" class="px-5 py-4 bg-spot-hover/50 hidden">
32
32
+
<div id="feed-edit-{{.ID}}" class="px-4 sm:px-5 py-4 bg-spot-hover/50 hidden">
33
33
<form hx-post="/feeds/edit" hx-target="#feed-{{.ID}}" hx-swap="outerHTML"
34
34
-
class="flex items-center gap-2">
34
34
+
class="flex flex-col sm:flex-row items-stretch sm:items-center gap-2">
35
35
{{csrfInput .CSRFToken}}
36
36
<input type="hidden" name="feed_url" value="{{.FeedURL}}">
37
37
<input type="text" name="category" value="{{if .Category.Valid}}{{.Category.String}}{{end}}"
+1
-1
internal/tmpl/partials/trending-card.html
Reviewed
···
1
1
{{define "trending-card.html"}}
2
2
-
<div class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot">
2
2
+
<div class="bg-spot-surface rounded-xl px-4 sm:px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot">
3
3
<div class="flex items-start justify-between gap-4">
4
4
<div class="min-w-0 flex-1">
5
5
<a href="/articles/{{.ArticleID}}" class="font-semibold text-spot-text hover:text-spot-green transition text-[17px] leading-snug">{{.Title}}</a>
+3
-3
internal/tmpl/profile.html
Reviewed
···
1
1
{{define "profile.html"}}
2
2
<div class="max-w-2xl mx-auto">
3
3
-
<div class="bg-spot-surface rounded-2xl p-6 mb-6">
4
4
-
<div class="flex items-center gap-5">
3
3
+
<div class="bg-spot-surface rounded-2xl p-4 sm:p-6 mb-6">
4
4
+
<div class="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-5 text-center sm:text-left">
5
5
{{if .ProfileUser.AvatarURL}}<img src="{{.ProfileUser.AvatarURL}}" class="w-20 h-20 rounded-full ring-2 ring-spot-divider">{{else}}<div class="w-20 h-20 rounded-full bg-spot-hover flex items-center justify-center text-spot-muted"><svg class="w-10 h-10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 4-7 8-7s8 3 8 7"/></svg></div>{{end}}
6
6
<div class="min-w-0 flex-1">
7
7
<h1 class="text-2xl font-bold text-spot-text truncate" style="letter-spacing: -0.02em;">
8
8
{{if .ProfileUser.DisplayName}}{{.ProfileUser.DisplayName}}{{end}}
9
9
</h1>
10
10
<p class="flex items-center gap-1.5 text-spot-secondary mt-1">@{{.ProfileUser.Handle}}<a href="https://bsky.app/profile/{{.ProfileUser.Handle}}" target="_blank" rel="noopener" class="text-spot-secondary hover:text-spot-green transition"><svg class="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">{{template "icon-bluesky"}}</svg></a></p>
11
11
-
<div class="flex gap-4 mt-3">
11
11
+
<div class="flex gap-4 mt-3 justify-center sm:justify-start">
12
12
<a href="/feeds" class="group">
13
13
<span class="text-xl font-bold text-spot-text">{{.SubscriptionCount}}</span>
14
14
<span class="text-sm text-spot-secondary ml-1 group-hover:text-spot-text transition">feeds</span>
+1
-1
internal/tmpl/stats.html
Reviewed
···
16
16
</div>
17
17
<div class="divide-y divide-spot-divider">
18
18
{{range $metrics}}
19
19
-
<div class="px-5 py-3.5 flex items-start justify-between hover:bg-spot-hover transition">
19
19
+
<div class="px-4 sm:px-5 py-3.5 flex flex-col sm:flex-row sm:items-start justify-between hover:bg-spot-hover transition gap-1 sm:gap-0">
20
20
<div class="flex-1 min-w-0">
21
21
<div class="flex items-center gap-2">
22
22
<span class="text-sm font-medium text-spot-text">{{.Name}}</span>