Relaunch: app shell, feed, create flow, onboarding, live search#1331
Draft
NiallJoeMaher wants to merge 86 commits into
Draft
Relaunch: app shell, feed, create flow, onboarding, live search#1331NiallJoeMaher wants to merge 86 commits into
NiallJoeMaher wants to merge 86 commits into
Conversation
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>
- 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>
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>
…-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>
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft PR for the relaunch work. Code + DB migrations only (no docs). Opening as
draft for review.
What's in here
Design system & shell
.eyebrow/.card, mint focus ring); WCAG-AA--text-faint.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
flat Type · Sort · Topic filters, onboarding nudge.
til+questionadded;discussion/question/tilrender viathe article reader.
modal (Discussion/Link publish immediately; Article → editor). Restyled
article editor.
Members
/welcome(interests/experience/focus) → saved touser.topics; signups routed here. Editable "Your topics" modal.saved / settings, split-screen auth.
Search (replaces Algolia)
search.everythingtRPC endpoint (posts + people + tags), debounced in thepalette, with LIKE-escaping, result caps, and a per-user/IP rate limiter.
Backend
MODERATION_ENABLED(default off).EMAIL_AUTH_ENABLED(dev-on);GitHub/GitLab always on.
content.create(publish) and publicsponsor.submit.contact modal; newsletter price removed.
0025–0027.Notes
default.
Playwright suite needs the
ENV=E2Eharness + seeded DB to run in CI.cross-instance limits on serverless.
🤖 Generated with Claude Code