- Add conditional "Dashboard" link in navbar that shows when a user is logged in - Tests verify the link is hidden for unauthenticated users and visible when authenticated - Investigation reports for Q1 (drafts/scheduled), Q2 (RSS), Q3 (email subs)
225 lines
12 KiB
Markdown
225 lines
12 KiB
Markdown
# Question 2: How can we make RSS feeds more obvious to viewers?
|
|
|
|
## 1. Where are the RSS/Atom feeds currently served?
|
|
|
|
**Application router** (`app/lib/firehose_web/router.ex`, lines 39-41):
|
|
|
|
```elixir
|
|
scope "/api/blog" do
|
|
forward "/engineering", Blogex.Router, blog: Firehose.EngineeringBlog
|
|
forward "/releases", Blogex.Router, blog: Firehose.ReleaseNotes
|
|
end
|
|
```
|
|
|
|
The Blogex.Router is mounted under `/api/blog/{engineering,releases}`. This means feeds are at:
|
|
|
|
| Feed | URL |
|
|
|------|-----|
|
|
| Engineering RSS | `/api/blog/engineering/feed.xml` |
|
|
| Engineering Atom | `/api/blog/engineering/atom.xml` |
|
|
| Release Notes RSS | `/api/blog/releases/feed.xml` |
|
|
| Release Notes Atom | `/api/blog/releases/atom.xml` |
|
|
|
|
**Blogex.Router** (`blogex/lib/blogex/router.ex`, lines 27-61) handles:
|
|
|
|
- `GET /feed.xml` (line 27) — RSS 2.0 via `Blogex.Feed.rss/2`
|
|
- `GET /atom.xml` (line 39) — Atom feed via `Blogex.Feed.atom/2`
|
|
|
|
The feeds are **not mounted under the human-facing `/blog/{id}/` paths** but under `/api/blog/{id}/`. This is suboptimal for usability — users browsing at `/blog/engineering` won't find a feed at `/blog/engineering/feed.xml`.
|
|
|
|
**Feed generation** (`blogex/lib/blogex/feed.ex`):
|
|
|
|
- `Blogex.Feed.rss/2` generates RSS 2.0 with proper XML, using `all_posts()`, respecting a `:limit` option (default 20).
|
|
- `Blogex.Feed.atom/2` generates Atom feed with same post data.
|
|
- Both include a self-referencing `<atom:link>` in RSS / `<link rel="self">` in Atom (for feed reader validation).
|
|
- Blog/author info is read from the blog module's `title/0`, `description/0`, `base_path/0` functions.
|
|
|
|
---
|
|
|
|
## 2. Is there any RSS icon or link in the current UI?
|
|
|
|
**No. There are zero references to RSS/Atom/feed in any template.**
|
|
|
|
| Location | File | Line(s) | Has RSS link? |
|
|
|----------|------|---------|---------------|
|
|
| Navigation bar | `app/lib/firehose_web/components/layouts/app.html.heex` | 1-32 | **No** |
|
|
| Homepage | `app/lib/firehose_web/controllers/page_html/home.html.heex` | 1-38 | **No** |
|
|
| Blog index | `app/lib/firehose_web/controllers/blog_html/index.html.heex` | 1-9 | **No** |
|
|
| Blog post show | `app/lib/firehose_web/controllers/blog_html/show.html.heex` | 1-23 | **No** |
|
|
| Blog tag page | `app/lib/firehose_web/controllers/blog_html/tag.html.heex` | 1-10 | **No** |
|
|
| HTML `<head>` | `app/lib/firehose_web/components/layouts/root.html.heex` | 1-40 | **No** |
|
|
|
|
Confirmed by codebase grep — `grep -rn "feed\|rss\|atom" app/lib/firehose_web/` returned only comments and false matches (e.g. `"feed"` in error handling, not RSS).
|
|
|
|
---
|
|
|
|
## 3. Best places to add RSS feed links
|
|
|
|
### (A) HTML `<head>` — Autodiscovery (highest priority)
|
|
|
|
**File:** `app/lib/firehose_web/components/layouts/root.html.heex`
|
|
|
|
Two `<link>` tags per blog for RSS autodiscovery (feed readers use these to auto-detect feeds):
|
|
|
|
```html
|
|
<link rel="alternate" type="application/rss+xml" title="Engineering Blog" href="/api/blog/engineering/feed.xml" />
|
|
<link rel="alternate" type="application/atom+xml" title="Engineering Blog (Atom)" href="/api/blog/engineering/atom.xml" />
|
|
<link rel="alternate" type="application/rss+xml" title="Release Notes" href="/api/blog/releases/feed.xml" />
|
|
<link rel="alternate" type="application/atom+xml" title="Release Notes (Atom)" href="/api/blog/releases/atom.xml" />
|
|
```
|
|
|
|
**Challenge:** The root layout (`root.html.heex`) is shared across all pages (hompage, about, contact, blog pages). Hardcoding both blogs' feeds works, but ideally only the currently-relevant blog's feed links appear on blog-specific pages. Since the app router uses a single root layout, you'd need to pass the blog context from the controller into the layout assigns, or use `@content_for`/`put_layout` approaches.
|
|
|
|
**Option A1 (simple):** Hardcode both feeds in `<head>` unconditionally. Acceptable because:
|
|
- The site only has two blogs with stable URLs.
|
|
- Readers can subscribe to either.
|
|
- Zero configuration needed.
|
|
|
|
**Option A2 (precise):** Add blog-specific metadata to the assigns in `BlogController` (lines 14-28, 31-46) and pass it to the layout via `@content_for`, similar to how `meta_tags` are already handled (line 20: `FirehoseWeb.Layouts.put_content_for(:meta_tags, meta)`). This would require adding a new `@content_for` slot for feed links.
|
|
|
|
### (B) Blog index pages (app/lib/firehose_web/controllers/blog_html/index.html.heex)
|
|
|
|
Add an RSS icon next to the blog title in the `<header>` section (line 4):
|
|
|
|
```
|
|
<h1 class="text-3xl font-bold font-display">{@blog_title}</h1>
|
|
```
|
|
|
|
Change to include a small RSS icon link pointing at the appropriate feed URL. The `@base_path` assign is already available (set in `BlogController.index/2`, line 24). We can derive the feed URL as `/api/blog/engineering/feed.xml` when `@base_path` is `/blog/engineering`, but there's no direct mapping. A helper mapping function would be needed, or a `@blog_id` assign should be added to the controller.
|
|
|
|
**Option B1:** Add a `blog_id` assign to the controller, then in the template do:
|
|
|
|
```elixir
|
|
<a href={"/api/blog/#{@blog_id}/feed.xml"} class="..." title="RSS feed">
|
|
<.rss_icon />
|
|
</a>
|
|
```
|
|
|
|
**Option B2 (simpler):** Hardcode the mapping in the template or add a helper function in `BlogHTML`:
|
|
|
|
```elixir
|
|
defp feed_url("/blog/engineering"), do: "/api/blog/engineering/feed.xml"
|
|
defp feed_url("/blog/releases"), do: "/api/blog/releases/feed.xml"
|
|
```
|
|
|
|
### (C) Blog post pages (app/lib/firehose_web/controllers/blog_html/show.html.heex)
|
|
|
|
Add a subtle "Subscribe via RSS" link or icon near the "Back to posts" link (line 2). The `@base_path` and `@post` assigns are available.
|
|
|
|
Best placement: inline with the "Back to posts" link at the top, or as a small badge/icon in the post metadata area (which is rendered by `Blogex.Components.post_meta/1` in `blogex/lib/blogex/components.ex`, line 76).
|
|
|
|
### (D) Homepage (app/lib/firehose_web/controllers/page_html/home.html.heex)
|
|
|
|
Add an RSS icon or link near the "Recent posts" heading (line 21, currently just `<h2>Recent posts</h2>`). Since the homepage shows posts from both blogs, you could:
|
|
|
|
- Link to the Engineering blog feed (primary blog)
|
|
- Or show a dropdown between the two feeds
|
|
- Or link to both (Engineering RSS, Releases RSS)
|
|
|
|
### (E) Navigation bar (app/lib/firehose_web/components/layouts/app.html.heex)
|
|
|
|
More prominent placement: add an RSS icon as a nav item (after the Contact link, line 25). Could be a dropdown linking to both feeds, or just the Engineering blog feed as default. This makes RSS discoverable from any page.
|
|
|
|
---
|
|
|
|
## 4. HTML for RSS autodiscovery links in `<head>`
|
|
|
|
The standard pattern for RSS 2.0 autodiscovery is:
|
|
|
|
```html
|
|
<link rel="alternate" type="application/rss+xml" title="Engineering Blog" href="/api/blog/engineering/feed.xml" />
|
|
```
|
|
|
|
And for Atom:
|
|
|
|
```html
|
|
<link rel="alternate" type="application/atom+xml" title="Engineering Blog (Atom)" href="/api/blog/engineering/atom.xml" />
|
|
```
|
|
|
|
For both blogs, this would be 4 `<link>` tags inserted in `root.html.heex` between the favicon links (line 9) and the `<.live_title>` component (line 10), or after line 15 (after the title).
|
|
|
|
**Autodiscovery works with relative paths** (feed readers resolve them against the page URL), so using `/api/blog/engineering/feed.xml` is fine and avoids needing the full host URL.
|
|
|
|
### Recommended implementation for `root.html.heex`
|
|
|
|
Insert after line 14 (`</.live_title>`) and before the CSS link (line 15):
|
|
|
|
```html
|
|
<link rel="alternate" type="application/rss+xml" title="Engineering Blog" href="/api/blog/engineering/feed.xml" />
|
|
<link rel="alternate" type="application/atom+xml" title="Engineering Blog (Atom)" href="/api/blog/engineering/atom.xml" />
|
|
<link rel="alternate" type="application/rss+xml" title="Release Notes" href="/api/blog/releases/feed.xml" />
|
|
<link rel="alternate" type="application/atom+xml" title="Release Notes (Atom)" href="/api/blog/releases/atom.xml" />
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Adding RSS subscription icons while keeping the design clean
|
|
|
|
### Icon options
|
|
|
|
Use an inline SVG (no additional dependencies), a commonly recognized RSS icon, approximately 16-20px, matching the current text color. The standard RSS icon is the orange/white dot-and-waves — but matching the site's monochrome theme (text color / primary color) would be more cohesive.
|
|
|
|
The current design uses:
|
|
- `text-base-content` for text
|
|
- `text-primary` for accent links
|
|
- Consistently uses `btn btn-ghost btn-sm` for nav links
|
|
|
|
### Placement strategies (from subtle to prominent)
|
|
|
|
1. **Only autodiscovery** (no visible icon) — functional for feed readers, invisible to human visitors. Minimum viable.
|
|
|
|
2. **Small RSS icon in blog header** — next to the blog title on index pages. Clean and contextual.
|
|
|
|
3. **Small RSS icon next to "Recent posts" on homepage** — visible on the landing page.
|
|
|
|
4. **RSS icon as a nav item** — consistently visible from any page:
|
|
```
|
|
[Blog] [Releases] [QWAN] [Contact] [📡] [theme toggle]
|
|
```
|
|
|
|
5. **Combination**: Autodiscovery + blog index icons + optionally a nav item.
|
|
|
|
### Recommended approach (clean design)
|
|
|
|
Use a small inline SVG RSS icon (matching the `text-base-content/60` muted color) placed:
|
|
|
|
- **In `<head>`** for autodiscovery (always, no visual impact)
|
|
- **In blog index header** (a small icon right-aligned next to the page title, or an inline link reading "RSS" in subtle text)
|
|
- **Optionally in the navbar** as a subtle icon-only button
|
|
|
|
### Implementation details
|
|
|
|
For the blog index (`index.html.heex`), the current template at line 4:
|
|
|
|
```heex
|
|
<h1 class="text-3xl font-bold font-display">{@blog_title}</h1>
|
|
```
|
|
|
|
Could become:
|
|
|
|
```heex
|
|
<h1 class="text-3xl font-bold font-display flex items-center gap-3">
|
|
{@blog_title}
|
|
<a href={feed_url(@base_path)} class="text-base-content/40 hover:text-primary transition" title="Subscribe to RSS feed">
|
|
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M6.18 15.64a2.18 2.18 0 0 1 2.18 2.18C8.36 19 7.38 20 6.18 20C5 20 4 19 4 17.82a2.18 2.18 0 0 1 2.18-2.18M4 4.44A15.56 15.56 0 0 1 19.56 20h-2.83A12.73 12.73 0 0 0 4 7.27V4.44m0 5.66a9.9 9.9 0 0 1 9.9 9.9h-2.83A7.07 7.07 0 0 0 4 12.93v-2.83Z"/>
|
|
</svg>
|
|
</a>
|
|
</h1>
|
|
```
|
|
|
|
This requires a `feed_url/1` helper. Since `base_path` maps cleanly to the API route (`/blog/engineering` → `/api/blog/engineering/feed.xml`), a simple `String.replace_prefix(@base_path, "/blog", "/api/blog") <> "/feed.xml"` would work.
|
|
|
|
### Summary of implementation points
|
|
|
|
| Location | File | Action |
|
|
|----------|------|--------|
|
|
| `<head>` | `app/lib/firehose_web/components/layouts/root.html.heex` ~ line 14 | Add 4 `<link rel="alternate">` tags |
|
|
| Blog index | `app/lib/firehose_web/controllers/blog_html/index.html.heex` ~ line 4 | Add RSS icon next to title |
|
|
| Blog show | `app/lib/firehose_web/controllers/blog_html/show.html.heex` ~ line 2 | Add subtle RSS link near "Back to posts" |
|
|
| Homepage | `app/lib/firehose_web/controllers/page_html/home.html.heex` ~ line 21 | Add RSS icon near "Recent posts" heading |
|
|
| Navbar | `app/lib/firehose_web/components/layouts/app.html.heex` ~ line 25 | Optionally add RSS icon nav item |
|
|
| Controller | `app/lib/firehose_web/controllers/blog_controller.ex` ~ line 22 | Optionally add `blog_id` assign for feed URL mapping |
|
|
| Helper | `app/lib/firehose_web/controllers/blog_html.ex` | Add `feed_url/1` helper function |
|
|
|
|
**Note:** The current feed URLs under `/api/blog/` are slightly awkward. Consider adding the `feed.xml` and `atom.xml` routes to the main Blogex.Router *also* under the human-facing path (e.g., `/blog/engineering/feed.xml`) by mounting Blogex.Router at both paths, or by adding explicit routes. However, this would be a larger refactor — the simplest short-term approach is to use the existing `/api/blog/` URLs and just link to them prominently. |