Skip to content

Relaunch: app shell, feed, create flow, onboarding, live search#1331

Draft
NiallJoeMaher wants to merge 86 commits into
codu-code:developfrom
NiallJoeMaher:feat/relaunch-repositioning
Draft

Relaunch: app shell, feed, create flow, onboarding, live search#1331
NiallJoeMaher wants to merge 86 commits into
codu-code:developfrom
NiallJoeMaher:feat/relaunch-repositioning

Conversation

@NiallJoeMaher
Copy link
Copy Markdown
Contributor

Draft PR for the relaunch work. Code + DB migrations only (no docs). Opening as
draft for review.

What's in here

Design system & shell

  • Full design-token system (status colors + washes, radii/shadow/motion scale,
    .eyebrow/.card, mint focus ring); WCAG-AA --text-faint.
  • New app shell: sticky 3-column top bar (logo · centered search · Create /
    avatar), left rail (text nav + "Your topics"), global right rail, ⌘K command
    palette
    , logged-out sign-in bar, and a mobile bottom nav (≤720px).

Feed & content

  • Editorial feed rows (kind chip, helpful/replies/Save/Share reaction bar),
    flat Type · Sort · Topic filters, onboarding nudge.
  • Post kinds til + question added; discussion/question/til render via
    the article reader.
  • Single "+ Create" entry point → first-run dos-&-don'ts gate → compose
    modal (Discussion/Link publish immediately; Article → editor). Restyled
    article editor.

Members

  • 3-step onboarding at /welcome (interests/experience/focus) → saved to
    user.topics; signups routed here. Editable "Your topics" modal.
  • Profile tabs (Posts / Achievements / About), restyled jobs / notifications /
    saved / settings, split-screen auth.

Search (replaces Algolia)

  • search.everything tRPC endpoint (posts + people + tags), debounced in the
    palette, with LIKE-escaping, result caps, and a per-user/IP rate limiter.

Backend

  • Write → in-review moderation flow + admin queue + admin email — gated behind
    MODERATION_ENABLED (default off)
    .
  • Email magic-link provider gated behind EMAIL_AUTH_ENABLED (dev-on);
    GitHub/GitLab always on.
  • Rate limits on content.create (publish) and public sponsor.submit.
  • Info pages restyled (Privacy/Conduct text preserved verbatim); advertise
    contact modal; newsletter price removed.
  • Richer seed data; migrations 00250027.

Notes

  • Moderation, smart auto-moderation, and email magic-link are env-flagged off by
    default.
  • e2e specs added/updated (feed filters, search, onboarding, create); the
    Playwright suite needs the ENV=E2E harness + seeded DB to run in CI.
  • The in-memory rate limiter is per-instance — swap for Redis/Upstash for
    cross-instance limits on serverless.

🤖 Generated with Claude Code

NiallJoeMaher and others added 30 commits June 6, 2026 22:00
Shift positioning from 'the free web developer community' / 'Ireland's largest
web developer community' to 'Codú — the community for AI builders & indie
hackers' across the homepage, app layouts, hero, newsletter CTA, structured data
(website + organization JSON-LD), manifest, RSS feed, the advertise page, and the
profile/volunteer title metadata.

Also refocus SEO keywords away from generic web-dev/React terms toward the
AI-builder / indie-hacker stack (LLM apps, agents, RAG, prompt engineering, vibe
coding, SaaS, MVP, bootstrapping), and reconcile the advertise metrics by dropping
the contradictory '100,000+' and the 'Ireland' geography claim.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New server-rendered About page reusing the Sponsorship visual system: hero with
the positioning line, a 'What Codú is for' manifesto, a 'What you get' card grid
(tutorials, feed, newsletter, Discord), a small honest founder note (not a flex),
and a closing CTA. Add /about to the sitemap's indexed routes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build the job board from the existing create-form stub:
- job table + job_type/job_status enums + migration 0020 (AI-native tagging,
  featured/paid tier, full lifecycle, payment columns for a future provider)
- tRPC jobRouter: create (+ admin email), public list (remote/AI-native/type
  filters, featured-first, keyset pagination) + getBySlug, owner getById/myJobs,
  admin adminList/moderate/setFeatured, and a markPaid payment stub
- wire the create form to the mutation; add AI-native toggle + tags input
- /jobs listing + /jobs/[slug] detail pages
- flag-gated Jobs nav link in the sidebar (+ the /about nav link)

Positioned for AI developer roles (employment), not indie hackers (self-employed
builders aren't job-seeking). Jobs UI is gated behind FEATURE_FLAGS.JOBS
(auto-on in dev, dark in prod until the PostHog flag is enabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expand the content aggregator toward the AI-builder positioning: add 26
RSS-verified AI sources (Latent Space, Simon Willison, Ahead of AI, Import AI,
Eugene Yan, Lilian Weng, Chip Huyen, Hamel Husain, Jay Alammar, Interconnects,
One Useful Thing, AI Snake Oil, The Gradient, Google DeepMind, Microsoft AI,
AWS ML, NVIDIA, Together AI, Replicate, Ollama, LlamaIndex, Roboflow, fast.ai,
Answer.AI, BAIR, Apple ML) to drizzle/seed-sources.ts.

Takes the 'ai' category from 6 to 32 sources. Additive only — existing web-dev
sources are kept (web-dev content stays, just no longer the headline). Seed is
idempotent (insert-by-url), so re-running only adds the new feeds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A dev-gated (NODE_ENV) design canvas at /kitchen-sink for iterating on the
redesign. Proposes a fresh, editorial direction — cool dark canvas, Bricolage
Grotesque display, Hanken Grotesk body, JetBrains Mono micro-labels — and drops
the orange/pink gradient entirely. Renders four fresh accent options (Mint, Lime,
Sky, Iris) side-by-side plus tokens, buttons, form controls, tags, a job card,
and an applied hero so we can lock a theme before touching real pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s living design system

- Load Bricolage Grotesque / Hanken Grotesk / JetBrains Mono via next/font in the
  root layout and expose them as --font-display / --font-sans / --font-mono.
- Rebuild /kitchen-sink as the canonical, dev-only LIVING design system: Mint
  accent locked, cool-dark tokens, organized Foundations / Components / Patterns to
  grow as we build real pages.
- Apply the anti-trope direction researched this session: editorial 'number +
  hairline + display-title' section headers instead of the common '// label'
  dev-tool convention, hairline rules over soft shadows, no bento/blobs.
- Include a side-by-side section-label comparison (code-comment vs slash vs
  editorial) to decide the structural device.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the prototype's inline styles with a real system:
- Add CSS-variable-driven design tokens (canvas/surface/elevated/hairline/fg/
  muted/faint/accent) in styles/globals.css (dark-first via .dark) and register
  them in tailwind.config.js with opacity support, plus font-display/sans/mono.
- Restyle global .primary-button / .secondary-button / .focus-style to the Mint
  accent — removes the orange→pink gradient app-wide.
- Add reusable components/ds: Eyebrow ('// label' mono, the approved convention)
  and Tag (default/accent/soft pills).
- Refactor /kitchen-sink to consume theme classes + ds components (no inline
  colors/fonts), wrapped in 'dark' so it always shows the canonical palette.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nnel)

Start the growth-driven page rebuild:
- New NewsletterCapture ds component (inline + compact) with real on-site beehiiv
  capture via a subscribeNewsletter server action (degrades gracefully in dev).
  Replaces the old blue->pink gradient NewsletterCTA on the homepage rail.
- Rebuild the Hero as a token-driven server component: editorial dotted-grid
  atmosphere (no gradient/starfield), Bricolage display H1 with the accent on
  'AI builders', mono eyebrow, single primary CTA (Join free) + Browse feed.
- Rework the post-hero band from a clashing light-gray duplicate CTA into a dark,
  on-system 'the community / build in public' beat with one CTA.

No vanity metrics (social proof deferred per owner). Funnel: cold -> subscribe,
warm -> join free.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stop re-skinning the old app shell — give the front door its own layout.
- Force dark-only (next-themes forcedTheme + html.dark).
- New (marketing) route group: top-nav + footer shell (no app sidebar), full-bleed,
  with the org JSON-LD and a footer newsletter capture.
- Rebuild the homepage from scratch as an editorial landing: hero (accent glow +
  dotted grid), a real 'Fresh from the feed' proof-of-life grid (live AI posts),
  a numbered 'why Codú' value grid, and a community beat — all token-driven, no
  vanity metrics. Move it out of the (app) sidebar layout.
- The (app) sidebar shell stays for the logged-in app pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make 'Fresh from the feed' read as clickable articles, not an info box:
- pull post cover images and render them as CSS background images (external feed
  domains aren't allowed by next/image), with an on-brand dotted fallback when a
  post has no cover
- switch from the seamless gap-px grid to separated cards with hover-lift,
  accent border on hover, and a 'Read ›' affordance

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…existing logo

- Move get-started into a new (auth) route group with a bare layout (no nav,
  no sidebar, no footer) for a zero-distraction sign-in/sign-up.
- Rebuild the auth UI on the new tokens: mono eyebrow, Bricolage heading, clean
  bordered GitHub/GitLab buttons (no orange/pink gradient), terms/privacy note.
- Use the existing Codú wordmark logo (/images/codu.png) in the auth header,
  marketing nav, and footer instead of a text wordmark (new logo is a later task).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move /about out of the app sidebar layout into (marketing), rebuilt token-driven
(editorial hero, manifesto, what-you-get cards, small founder note, CTA) — drop
the old orange/pink Sponsorship-style sections and retire components/About.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…letter card sitewide

- App sidebar: canvas bg + hairline border + mint active icons (was bg-black /
  neutral); footer + socials to tokens.
- Swap the old blue->pink NewsletterCTA for the token-driven NewsletterCapture on
  /feed and /articles, and delete the dead NewsletterCTA component.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- De-bootstrap the nav: animated accent underline on links, refined spacing.
- Capture competitive learnings from IndieHackers (right-rail conversion hub with
  Submit-a-Post/Advertise, the Build Board leaderboard, content-forward layout) in
  the growth doc as the next-build backlog.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ct form

- Move /advertise into (marketing), rebuilt token-driven: hero, 'ways to partner'
  offering cards (newsletter/jobs/events/content), real past-partner logos kept as
  legit proof, dropped the vanity metrics + generic testimonial.
- Recolor the 3-step sponsor ContactForm from orange/pink to mint tokens.
- Retire the old (app)/advertise route + unused Sponsorship section components
  (keep ContactForm).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Recolor every remaining orange/pink utility to the mint accent across ~55 app +
  component files (feed, jobs, admin, editor, comments, badges, search, 404, etc.).
  Archived /letters posts left untouched.
- Homepage feed cards: remove the jump-on-hover; keep a subtle image zoom + chevron
  slide. Same de-jump applied to /about cards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New ConversionHub ds component (Write a post / Post a job / Advertise) surfaced at
the top of the feed sidebar, and retoken the 'About the Feed' card. Gives content
pages a clear contribute/monetise hub like IH's right rail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WS3 v1, built safely (engagement never breaks core actions):
- Schema + migration: append-only point_event (with dedupe/anti-gaming index) and
  per-user user_streak.
- server/lib/engagement: award() (never throws) + recordDailyActivity() (idempotent
  daily streak roll-forward).
- Award points on post publish + comment create; roll the daily streak in the app
  layout for signed-in users.
- engagement tRPC router: myStats (streak + points) and leaderboard (week/all).
- UI: StreakBadge (🔥) in the app header for signed-in users; BuildBoard weekly
  leaderboard in the feed rail — flag-gated (FEATURE_FLAGS.BUILD_BOARD) and hidden
  while empty to avoid a ghost-town board.
- Fix the header Create button contrast (black on mint).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y + engagement-plan doc

- Kill remaining grey: retokenize UnifiedContentCard, the inline /articles ArticleCard
  + skeleton, SavedItemCard, PopularTagsSidebar, legacy ArticlePreview, and the feed
  Filters dropdowns to the design tokens (surface/canvas, hairline, fg/muted/faint,
  accent hover).
- Simplify taxonomy: remove the redundant rail 'Sources' filter (it duplicated the
  Topics dropdown via source category); sources remain as card attribution. Relabel
  the dropdown to 'Topics'.
- Add codu-relaunch/04-community/engagement-plan.md (shipped / building / deferred /
  last).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New HeroBackdrop: refined mint aurora glows, a deterministic twinkling
  constellation, and occasional shooting stars — restrained, reduced-motion aware
  (motion-safe only). Replaces the flat dotted-grid+blur hero backdrop.
- Add reusable keyframes/animations to the Tailwind theme (twinkle/aurora/drift/
  shoot/rise) and a staggered load reveal on the hero eyebrow/H1/sub/CTAs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…play)

- Schema + migration: badge + user_badge (unique per user/badge).
- engagement.ts: BADGE_RULES + checkBadges() (runs after award; first post, 7/30-day
  streak, 100/500 points; connector wired in the referral step) + getUserBadges().
- Seed 6 starter badges (drizzle/seed-badges.ts).
- Display badge pills on the profile header.
- Reference + AI design prompt: codu-relaunch/04-community/badges.md; auto-mod plan:
  ai-moderation-plan.md (deferred).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… aurora

- Add ogl + a themed GradientBlinds component (reactbits-derived) — animated mint
  gradient blinds with a cursor spotlight, reduced-motion aware (single static frame).
- Use it as the homepage hero backdrop with a readability scrim; retire HeroBackdrop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Schema + migration: user.referralCode (unique) + user.invitedBy; add 'referral'
  to the point_action enum.
- engagement.ts: ensureReferral() (lazy code-gen + cookie attribution → award the
  referrer 'referral' points + checkBadges → Connector badge); wire real referral
  count into the connector badge rule.
- /get-started captures ?ref into a cookie; the app layout attributes it on next
  visit (idempotent, never throws).
- engagement.myReferral query; ReferralCard (invite link + count) in Settings →
  'Invite friends'.
- Backfill referral codes for existing users (drizzle/seed-referral-codes.ts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…first, composer

- Schema + migration: follow table (follower/following, unique pair, indexes).
- follow tRPC router: follow / unfollow / isFollowing / counts.
- Feed: 'following' filter in content.getFeed (+ fix the previously-unused tag
  filter) and a For-you / Following tab on /feed (signed-in), with an empty state.
- Profiles: FollowButton (Follow/Following, optimistic invalidation) + follower/
  following counts in the header.
- Feed-first: signed-in users are redirected from / to /feed (marketing stays for
  logged-out + SEO).
- Inline composer ('What are you building?') at the top of the feed.
- Datastore note: recommend staying on Postgres over a Mongo migration
  (codu-relaunch/01-platform/datastore-consideration.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…llowing lists

- Follow notifications: NEW_FOLLOWER type, created on a new follow; widen the
  notification read filters (type 0/1/2, drop the postId-not-null requirement) and
  render 'started following you' in the notifications list.
- Achievements section on profiles (engagement.profileEngagement): current/longest
  streak, points, and the full badge set with earned + LOCKED states + criteria
  (the 'potential awards' view). Replaces the simple header pills.
- Followers / Following lists: follow.getFollowers/getFollowing + clickable counts
  that reveal the list (with avatar, name, Follow button per row).

Verified logged-in: Follow → Following toggle, live count, followers list, and the
achievements panel all work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 0 of the design-handoff recreation. Treat the handoff at
design_handoff_codu/ as the source of truth.

- styles/globals.css: full token set (surface ladder hover/inset,
  border-strong, on-accent, status colors success/warning/danger/info),
  fix dark --color-faint #5b6472 -> #757e8c for WCAG AA, align fg/accent-soft
  to handoff hexes, add focus-ring/shadow ladder CSS vars
- globals base layer: global mint :focus-visible ring, display-font headings,
  .eyebrow/.slash + .card utilities, reconcile primary/secondary/ghost buttons
  to handoff (on-accent text, radius-md, press translate), drop dead .old-input
- tailwind.config.js: expose new colors + washes (opacity modifiers), radii
  scale, boxShadow, container maxWidth, fontSize/letterSpacing scale, motion
  tokens, bg-grid-lines
- components/ds: Tag/FollowButton text-black -> text-on-accent
- kitchen-sink: full color ladder + status + elevation/radii + toggle refs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1. Replace the single-sidebar layout with the handoff shell.

- components/Layout/AppShell: sticky TopBar over the .app-main 3-column grid
  (LeftRail / center / RightRail) + ⌘K palette + logged-out SignInBar; global
  ⌘K/Esc keydown handling
- TopBar: logo→/feed, search-button styled like an input (opens palette),
  Feed/Discussions/Jobs nav, Write + avatar menu / Log in + Join free
- LeftRail: primary nav (+ Notifications/Saved/Profile when authed), Your
  topics tags, bottom-pinned Privacy/Conduct/Advertise/About footer
- RightRail (now global on every page): ProgressCard (points+streak+next
  milestone from engagement.myStats) / JoinCard → trending tags → ConversionHub
  / NewsletterCapture
- CommandPalette: quick actions + live tag search (tag.search); posts/people
  via Algolia is a follow-up
- styles/globals.css: .app-topbar/.app-main/.app-leftrail/.app-rightrail grid
  with bespoke 1080/720 breakpoints
- feed/_client: drop internal rail+grid (rails are global now), render center
  column only; text-black→text-on-accent on the composer CTA
- (app)/layout: render AppShell; drop Algolia sidebar wiring

Old SidebarAppLayout/sidebar-layout/MinimalHeader/AppSidebar now unused.
Note: /discussions nav target lands in Phase 6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 2. Per the handoff, the feed is the landing surface; there is no
marketing homepage.

- (marketing)/page.tsx: 308 permanentRedirect / -> /feed (canonical home).
  Drop the GradientBlinds hero / value-prop / feed-preview landing (the
  GradientBlinds component stays for reuse on /about).
- Logged-out visitors land on the public, indexable feed (getFeed is a
  publicProcedure) with the shell's sign-in bar + Join free.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tion kinds

Phase 3.

- schema: add `til` + `question` to the post_type enum (migration
  0025_normal_nuke); extend ContentTypeSchema + toDbType/toFrontendType so
  QUESTION maps to a real `question` kind and TIL is first-class
- UnifiedContentCard: rebuilt as an editorial row — kind chip (Article/TIL/
  Question/Discussion/Link), author + @handle · time (· via source), display
  title with ↗ for links, 2-line excerpt, OG thumb / striped placeholder, mono
  #tag metadata, reaction bar (▲ helpful · replies · Save · Share with
  copy-link). Vote/bookmark/click mutations preserved; drop legacy chevron/
  bookmark-icon body and dead URL helpers
- feed: dismissible OnboardingBanner (first-win 3 steps, useSyncExternalStore)
  + low-bar Composer (Tip/Ask/Share/Write chips → /create?kind=)
- FeedFilters: add TIL option; feed type validation accepts `til`

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 4. Visual restyle of the three reader clients (user article, curated
link, user link) under app/(app)/[username]/[slug]/ — functionality, data,
voting/bookmark/share, FollowButton, and the comments component preserved.

- ‹ Back to feed ghost link, // eyebrow (tag/source · meta), large display
  title, author row + Follow, cover in a hairline frame / grid-dots placeholder
- mono editorial reaction footer; "Discussion {count}" header above comments
- swap all hardcoded neutral/blue/green/red + dark: colors for design tokens;
  text on accent is text-on-accent

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NiallJoeMaher and others added 6 commits June 8, 2026 16:20
- AppShell: /speakers + /volunteer render rail-less (centered single column) —
  they're standalone forms, not feed reading surfaces
- radios on those forms now tint mint via a dedicated .accent-mint utility
  (Tailwind's arbitrary accent-[...] inference was unreliable for accent-color;
  verified computed accent-color = rgb(45 212 191))
- playwright: default to Desktop Chrome locally (~4× faster); full cross-browser
  + mobile matrix runs on CI or with ALL_BROWSERS=1

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- e2e: feed-is-home — "/" renders the feed (no redirect), /feed→/; get-started
  authed → "/"; feed/create specs use "/"; notifications card class →
  border-hairline
- radios: fully custom appearance:none control (mint ring + dot, mint focus
  outline). accent-color is ignored by Chrome under color-scheme:dark, so the
  native control kept painting UA blue regardless of value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wait for the "Add to the discussion…" composer (the redesigned DiscussionEditor
trigger) instead of a "Discussion (N)" heading, and post via it. The reader
that renders user-authored posts has no discussion section header — noted for
review. All 37 relaunch feature specs green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ofile

Seed (e2e/setup.ts): a published discussion + question by user one (with a
top-level comment + nested reply), user two → user one follow, and user one's
topics / experience / referral code / point events. All cleaned via the
user-delete cascade.

New specs:
- discussions.spec: discussions listing + Start CTA; thread renders the post +
  seeded comment/reply; signed-in reply composer opens
- follow.spec: Following feed surfaces followed users' posts; profile follower/
  following stats; follow control reflects the existing relationship
- profile.spec: name + interest tags + Posts/Achievements tabs (no About);
  Achievements surfaces points/streak

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Seed marks user one onboarded, so /welcome bounces to the feed homepage; widen
the URL assertion to accept "/".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- editor.spec: delete the obsolete Link-tab + tab-switching + link-publish/
  validation blocks (the editor lost its Link tab; links go via the compose
  modal). Fix the article-editor tests for the no-tabs editor; publish flow
  accepts the in_review redirect (MODERATION_ENABLED in e2e)
- articles.spec: point at "/?type=article"; drop tests now covered by feed.spec
  or asserting the removed sidebar; keep article-detail nav, comment/cannot-
  comment, write-and-publish (via compose → Article → editor)
- saved.spec: bookmark via the feed-card Save action + reader Save; new empty-
  state copy; serial + retries to absorb shared-bookmark-state parallel flake

Full suite: 117 passed on Desktop Chrome.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NiallJoeMaher and others added 2 commits June 8, 2026 17:46
Collapse decorative section banners, redundant JSX labels, and tutorial-voice
narration across 44 relaunch source files; keep the non-obvious WHY/gotchas
(fail-open engagement, moderation gate, dedupe-index anti-gaming, accent-color
under color-scheme:dark, handoff mirrors, etc.). Comments only — code unchanged;
tsc + eslint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NiallJoeMaher and others added 4 commits June 8, 2026 17:55
…-code#5 §1)

New components/Vote/VoteControl.tsx: a hairline pill (up-chevron · net score ·
down-chevron, inline-SVG chevrons, tabular-nums). Up active → accent-soft, down
→ danger; hover previews the arrow colour; clicking the active arrow clears the
vote; stopPropagation so it never opens the row. Wired (reusing existing
mutations) into the feed card reaction bar (content.vote), discussion comments/
replies (discussion.vote), and the article reader footer (post/content vote) —
replacing the old "▲ helpful" upvote-only control. Outline variant only (the
prototype's tinted variant + tweaks panel are prototype-only). feed.spec updated
to the Upvote/Downvote labels.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
 §3)

New components/RichText/: useRichText hook + selection-aware markdown transforms
(bold/italic/strike/clear/link/ul/ol/quote/code/table), RichToolbar (inline ·
lists · block groups with dividers + "Switch to Markdown"), AaToggle, and
MdTextarea (autosize). Storage stays markdown; the toolbar wraps/inserts md
around the textarea selection (onMouseDown preventDefault keeps selection).

Replaces the TipTap comment/reply editor (deleted its Toolbar/useEditor/
extensions/help-modal) with this markdown composer — keeps the collapsed trigger
+ onSubmit(markdown)/submitLabel contract so DiscussionArea is unchanged — and
upgrades the ComposeModal body field. The TipTap article editor is untouched
(articles keep WYSIWYG). e2e comment-flow specs type into the new textarea.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…doff codu-code#5 §4)

New components/Celebrate/: Confetti (canvas burst, mint/status palette, ~1.7s,
early-returns under prefers-reduced-motion) and BadgeUnlock (full-screen dialog,
hexagon badge tile with codu-badge-pop + ring-pulse, "// badge unlocked", +points,
Keep browsing / See your badges → profile achievements). Fires once when the
real onboarding wins all complete — guarded by a localStorage flag (read via
useSyncExternalStore) + a close flag, trigger in an effect (no setState-in-effect).
username threaded through ShellActions for the badges link. Keyframes added to
globals (motion gated on prefers-reduced-motion).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Publications = feed sources, now followable. New publication_follow table
(userId↔sourceId, migration 0028) + publication tRPC router (getBySlug with
follower/article counts + isFollowing, follow/unfollow). The source profile at
/{slug} (_sourceProfileClient) is redesigned to the publication layout: square
logo tile, "// publication" eyebrow, name + @handle, Follow/Share, tagline,
Followers + Articles stats, "// latest articles" via UnifiedContentCard — no
banner. Byline "in {Publication}" links (card + reader MetaHeader) point to
/{slug}. (The /feed/[sourceSlug] route is 308-redirected to /{slug} by
next.config, so the canonical page lives there.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NiallJoeMaher and others added 7 commits June 8, 2026 19:01
point_event_dedupe was a unique INDEX with default NULLS DISTINCT, so only
upvote_received (non-null actor) ever deduped — post_published/comment_created/
daily_active/referral all passed actorId NULL and never conflicted, silently
disabling idempotency (farmable points; republish re-awarded +20). Converted to
a UNIQUE constraint with NULLS NOT DISTINCT (migration 0029 dedupes existing
rows first, correcting any farmed points). post_published is now once per post.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ug (review M2)

- enforceRateLimit on comment.create (10/min per user) — anti-spam/farm
- don't award comment_created when commenting on your own post
- fix the false "edited" badge: the post-insert ltree path write tripped the
  updatedAt $onUpdate, so every new comment rendered as "· edited"; pin updatedAt
  back to createdAt on that internal write

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…L6/L7 + UI)

Security/integrity:
- H3: moderation in_review gate now applies to create/update (not just publish)
  in content.ts + post.ts — no more self-publishing around review
- M3: publish mutations share the create rate limit (10/5min)
- M1: per-referrer daily cap (5/24h) on referral points
- L3: removing/downgrading an upvote revokes the author's upvote_received points
- M4: newsletter subscribe action throttled by IP (3/hr)
- L2: Sentry warning when RATE_LIMIT_TABLE is unset in production
- L4: HTML-escape title/authorName in the moderation admin email
- L1: document the new env vars in sample.env

UI/feature:
- discussion sort → feed FilterPill style (Top/New/Oldest); comment "···" menu +
  other action menus restyled to the relaunch popover pattern (bg-elevated/
  border-strong/shadow-pop, danger destructive)
- M5: onboarding "focus" step optional + de-overpromised copy
- M7: Jobs nav entries gated behind the JOBS flag (rail/drawer/palette/hub)
- M8: "Discussion {N}" heading on the user-post reader
- L6: single <h1> on profile pages; L7: BuildBoard mounted in the right rail
  behind its flag

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ery-param tabs

- next/image: allow robohash.org + picsum.photos + i.pravatar.cc (seed/e2e
  avatars + covers were throwing "hostname not configured" and breaking pages)
- feed: remove the big "Feed" h1, float the For-you/Following tabs + filters to
  the top to reclaim space
- cards: unify kind chips — all soft corners (rounded-sm) with an opaque token
  wash per kind (Discussion/Question no longer look offset; Link no longer a pill)
- settings + profile tabs are now ?tab= query params (deep-linkable, URL-as-state)
- home.spec updated for the removed heading

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ved header

- BuildBoard was orphaned legacy content that doesn't fit the relaunch — removed
  the RightRail mount, the component, its barrel export, and the now-unused
  engagement.leaderboard endpoint
- feed.spec: drop the "Feed" h1 assertions (the heading was removed)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Discussions page drops the topic-tag row for the feed pattern: All / Following
tabs (deep-linkable via ?view=) + a FilterPill sort (Recent/Active/Top). New
post_follow table (migration 0030) + discussion.follow/unfollow/isFollowing;
a +Follow ⇄ ✓Following toggle on the thread. New comments notify the post's
followers (NEW_COMMENT_ON_FOLLOWED_POST, de-duped vs author/parent/commenter),
rendered on the notifications page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove redundant JSX banners, numbered group labels, and narration across the
recently-changed files; keep the WHY/gotchas/security rationale. Comments only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…schedule timeout

- onboarding spec: the removed "Feed" h1 broke feed-detection on the onboarded
  redirect — detect the feed by its "For you" tab instead
- editor schedule-modal wait 5s→10s to absorb full-suite parallel-load flake

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…able

Run prettier --write across the relaunch/handoff-#5/fix changes (the format
check was failing CI), auto-remove genuinely-unused eslint-disable directives,
and restore the one disable lint:fix wrongly stripped (the synchronous
setSelectedIndex in slash-command's useLayoutEffect). eslint 0 errors, prettier
check passes, tsc clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…chips

- user discussion/link/article readers no longer wrap content in a warm
  dark:bg-neutral-900 card — they render bare on the black canvas like the
  source-article reader (also tokenized the meta row + tag pills in those
  branches)
- type chips (UnifiedContentCard KIND + ContentDetail TypeBadge) are now opaque
  bg-elevated pills with a per-kind colored border + label, so Link/Discussion/
  article/etc. read as anchored bordered pills instead of floating text

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.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.

1 participant