Skip to content

feat: add thoughts page with timeline-style moments - #13

Merged
BobbyLin23 merged 3 commits into
release/v0.3.0from
feat/thoughts-page
Aug 18, 2026
Merged

BobbyLin23 merged 3 commits into
release/v0.3.0from
feat/thoughts-page

Conversation

@BobbyLin23

@BobbyLin23 BobbyLin23 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a new /thoughts page — a timeline.so-style "moments" feed of short, timestamped posts. New content collection thoughts (content/thoughts/*.md), a vertical timeline UI with entrance animations, i18n for all 6 locales, a nav entry, and E2E smoke coverage.

Changes

  • content.config.ts — new thoughts collection: type: 'page', source: 'thoughts/*.md', schema date/title/tags?/draft.
  • app/pages/thoughts/index.vue — single stream page: grouped vertical timeline with a rail line + amber dots, per-moment card (timestamp + markdown body via ContentRenderer), staggered SafeMotion entrances, empty state, useSeoMeta. Date renders with time-of-day when the frontmatter date includes one.
  • app/components/AppHeader.vue — "Thoughts" nav item (between Weekly and About).
  • i18n/locales/*.jsonnav.thoughts + thoughts.title/description/empty in en, zh, zh-TW, es, ja, fr.
  • content/thoughts/ — 3 placeholder sample moments.
  • tests/e2e/site.spec.ts — smoke routes for /en/thoughts and /zh/thoughts.

Scope notes

  • Single stream page only (no per-moment detail pages, comments, or AI translation — intentional).
  • No RSS feed for thoughts (out of scope).

Verification

  • pnpm lint — 0 errors.
  • pnpm fmt:check — all touched files formatted (remaining warnings are pre-existing files unrelated to this PR).
  • pnpm test:e2e — 27/27 passed, including the new thoughts smoke tests.

Summary by Sourcery

Introduce a localized timeline feed for sharing short, timestamped thoughts.

New Features:

  • Add a localized /thoughts page that presents published short posts in a timestamped timeline.
  • Add a thoughts content collection with dated, titled, optionally tagged and draftable entries.
  • Add Thoughts navigation and localized page metadata and empty-state text across all supported locales.

Enhancements:

  • Provide localized date and date-time formatting, responsive timeline presentation, entrance animations, SEO metadata, and an empty state for the thoughts feed.

Tests:

  • Add end-to-end smoke coverage for the English and Chinese thoughts routes.

Chores:

  • Seed the thoughts collection with three sample moments.

@sourcery-ai

sourcery-ai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements a new localized /thoughts timeline page backed by a dedicated content collection, wires it into site navigation, seeds sample content, and adds basic E2E smoke coverage for key locales.

Sequence diagram for the new /thoughts timeline page rendering

sequenceDiagram
  actor User
  participant AppHeader
  participant Router
  participant ThoughtsPage
  participant ContentCollection_thoughts
  participant ContentRenderer

  User->>AppHeader: click navItems to localePath(/thoughts)
  AppHeader->>Router: navigate /thoughts
  Router->>ThoughtsPage: mount thoughts/index.vue
  ThoughtsPage->>ThoughtsPage: useSeoMeta
  ThoughtsPage->>ContentCollection_thoughts: queryCollection(thoughts).where(draft,=,false).order(date,DESC).all
  ContentCollection_thoughts-->>ThoughtsPage: moments
  ThoughtsPage->>ThoughtsPage: formatDate(moment.date)
  ThoughtsPage->>ContentRenderer: render moment
Loading

File-Level Changes

Change Details Files
Add a dedicated thoughts content collection for timestamped short-form posts.
  • Define thoughts collection as type: 'page' with source: 'thoughts/*.md'.
  • Specify schema fields date, title, optional tags, and draft with a default of false.
content.config.ts
Introduce the /thoughts timeline page that queries and renders non-draft moments with localized SEO metadata and formatted timestamps.
  • Fetch thoughts entries via useAsyncData and queryCollection, filtering draft === false and ordering by date descending.
  • Define locale-aware date and datetime formatters and a helper that chooses between them based on whether the frontmatter date includes a time component.
  • Render a vertical timeline UI with a rail and markers, using SafeMotion for animated page header and per-moment card entrances.
  • Render moment content (date, optional title, markdown body) within styled cards using ContentRenderer, and show a translated empty state when there are no moments.
  • Set SEO meta title/description from i18n resources and ogUrl based on public.siteUrl.
app/pages/thoughts/index.vue
Expose the Thoughts page through the site navigation and translations for all supported locales.
  • Insert a new nav item between Weekly and About that routes to the localized /thoughts path and marks active based on the current route.
  • Add nav.thoughts plus thoughts.title, thoughts.description, and thoughts.empty keys across all locale JSON files to fully localize the page heading, description, and empty state copy.
app/components/AppHeader.vue
i18n/locales/en.json
i18n/locales/es.json
i18n/locales/fr.json
i18n/locales/ja.json
i18n/locales/zh-TW.json
i18n/locales/zh.json
Seed the new collection with sample moments to populate the timeline.
  • Add three content/thoughts/*.md entries with dates, titles, and short markdown bodies to serve as initial content and development fixtures.
content/thoughts/2026-08-03-thoughts-here.md
content/thoughts/2026-08-12-reading-staff-engineer.md
content/thoughts/2026-08-17-shipped-v0.3.md
Extend E2E smoke tests to cover the new Thoughts page in key locales.
  • Add /en/thoughts and /zh/thoughts to the smoke route list with expected localized headings to ensure the page builds and renders in CI.
tests/e2e/site.spec.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The ogUrl in useSeoMeta is hard-coded to /thoughts, which will generate a non-localized canonical URL for non-EN locales; consider deriving it from the current route (e.g., config.public.siteUrl + route.path) or a locale-aware helper instead.
  • The date field in the thoughts collection is a free-form z.string() and later passed to new Date(dateStr); tightening this to an ISO-like constraint (or coercing to Date in the schema) would make the parsing in formatDate more robust and avoid surprising timezone/format issues.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `ogUrl` in `useSeoMeta` is hard-coded to `/thoughts`, which will generate a non-localized canonical URL for non-EN locales; consider deriving it from the current route (e.g., `config.public.siteUrl + route.path`) or a locale-aware helper instead.
- The `date` field in the `thoughts` collection is a free-form `z.string()` and later passed to `new Date(dateStr)`; tightening this to an ISO-like constraint (or coercing to `Date` in the schema) would make the parsing in `formatDate` more robust and avoid surprising timezone/format issues.

## Individual Comments

### Comment 1
<location path="app/pages/thoughts/index.vue" line_range="35" />
<code_context>
+    }),
+)
+
+function formatDate(dateStr: string) {
+  const date = new Date(dateStr)
+  return dateStr.includes('T')
</code_context>
<issue_to_address>
**issue:** Guard against invalid `dateStr` values to avoid `Invalid Date` rendering.

`new Date(dateStr)` can return an invalid date for malformed or unexpected input, which may render as a confusing string or "Invalid Date". Add a validity check (e.g., `isNaN(date.getTime())`) and fall back to the raw `dateStr` when invalid to keep the UI robust and easier to debug.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread app/pages/thoughts/index.vue
@BobbyLin23
BobbyLin23 merged commit 87465f2 into release/v0.3.0 Aug 18, 2026
2 checks passed
@BobbyLin23
BobbyLin23 deleted the feat/thoughts-page branch August 18, 2026 01:05
BobbyLin23 added a commit that referenced this pull request Aug 18, 2026
* feat: implement Notion publishing integration with GitHub

* feat: add oauth login and comments on posts

Let visitors sign in with GitHub or Google and leave comments on blog and weekly posts, stored in sqlite/D1.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat: add thoughts page with timeline-style moments (#13)

* fix: fix the tailwind issues

* fix: fix login modal's loading issues

* feat: add rich text editor for comments

* chore: improve e2e test

* fix: update some issues from sourcery

* fix: fix e2e actions

---------

Co-authored-by: BobbyLin7 <bobbylin23@163.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants