Open
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
perf: enable webpack production mode and optimization
perf: add compression middleware and optimize cache headers
Perf/webpack babel
perf: migrate Tailwind CSS from CDN runtime to build-time PostCSS Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* perf: migrate Tailwind CSS from CDN runtime to build-time PostCSS Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: replace jQuery, moment.js, lodash, bluebird with native APIs Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: keep Buffer in ProvidePlugin (needed by CoveredImage until PR6) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* perf: migrate Tailwind CSS from CDN runtime to build-time PostCSS Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: replace jQuery, moment.js, lodash, bluebird with native APIs Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: add route-based code splitting with React.lazy and dynamic imports Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: add route-based code splitting with React.lazy and dynamic imports Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* ci: add CI workflow for lint, typecheck, build, and E2E Add GitHub Actions CI workflow that runs on PRs and pushes to main. Jobs run in parallel (lint, typecheck, build) with E2E depending on build. E2E uses continue-on-error since Linux VRT snapshots are not yet available. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix(ci): run corepack enable before setup-node setup-node's pnpm cache requires pnpm to be on PATH, so corepack enable must run before setup-node, not after. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: resolve typecheck and formatting errors Remove unused RequestHandler import in static.ts and apply oxfmt formatting fixes to pass CI checks. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix(ci): correct build artifact path to application/dist/ Webpack outputs to application/dist/, not application/client/dist/. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
ci: parallelize E2E tests with sharding and cache Playwright browsers Split E2E tests into 3 shards running in parallel, cache Playwright browser binaries across runs, and set E2E_WORKERS=2 to utilize both vCPUs on ubuntu-latest runners. Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
chore: add pre-commit hook with lint-staged for automated linting Set up git hooks via .husky/pre-commit to run oxlint and oxfmt on staged files automatically before each commit using lint-staged. Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* perf: migrate Tailwind CSS from CDN runtime to build-time PostCSS Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: replace jQuery, moment.js, lodash, bluebird with native APIs Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: add route-based code splitting with React.lazy and dynamic imports Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: optimize fonts (WOFF2), images (WebP), and simplify CoveredImage Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
ci: fix VRT snapshots for Linux CI and add snapshot update workflow - Remove *.png from e2e .gitignore to track VRT snapshots in git - Change Playwright browser from chromium to chrome to match config - Add workflow_dispatch workflow for updating Linux snapshots - Include existing darwin snapshots in git Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Replace intentionally heavy main-thread patterns with efficient observers: - InfiniteScroll: remove 2^18 DOM read loop, use single check with rAF throttle and passive listeners - DirectMessagePage: replace 1ms setInterval+getComputedStyle with MutationObserver - useHasContentBelow: replace 1ms postTask polling with IntersectionObserver - AspectRatioBox: replace setTimeout(500)+resize listener with ResizeObserver Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
perf: optimize initial render (remove load listener, react-helmet, add font preload)
- Remove window.addEventListener("load") wrapper for immediate React render
- Replace react-helmet with document.title via useEffect across all containers
- Add font preload links for WOFF2 files in index.html
- Add decoding="async" to CoveredImage img tag
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
perf: reduce bundle size (splitChunks, remove polyfills, native compression) - Add webpack splitChunks cacheGroups for React vendor chunk + maxSize 200KB - Remove standardized-audio-context ProvidePlugin (use native AudioContext) - Replace pako gzip with native CompressionStream API - Switch react-syntax-highlighter to light build with selective language registration Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
perf: subset fonts (3.8MB→260KB) and dynamic import katex CSS - Subset ReiNoAreMincho WOFF2 fonts to only include used characters (1255 chars) - Regular: 3.8MB → 262KB, Heavy: 3.9MB → 260KB - Move katex CSS import to dynamic import for code-split chunk loading Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
perf: optimize media (native GIF rendering, direct audio URL) - Replace gifler/omggif canvas-based GIF decoding with native <img> tag - Use direct audio URL in <audio> element instead of fetchBinary + blob URL - SoundWaveSVG fetches audio internally on demand instead of receiving ArrayBuffer - Remove gifler, omggif, @types/omggif dependencies Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
) - Replace 1ms scheduler.postTask polling in useSearchParams with popstate/pushState interception - Add React.memo to TimelineItem, PostItem, ChatMessage - Extract Markdown plugin arrays to module scope in ChatMessage - Debounce sentiment analysis (300ms) in SearchPage - Debounce BM25 suggestion search (200ms) in ChatInput - Scope MutationObserver to message list container in DirectMessagePage Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
- Add indexes to FK columns (Post, Comment, DirectMessage, DirectMessageConversation, User) - Optimize DirectMessage afterSave hook (skip redundant findByPk, use unscoped) - Merge dual search queries into single query with Op.or - Use unscoped() in DM list endpoint to control eager loading Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* perf: add Brotli compression via shrink-ray-current - Replace compression middleware with shrink-ray-current for Brotli support - Remove compression and @types/compression dependencies - Add pnpm.onlyBuiltDependencies for native build deps (iltorb, node-zopfli-es) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: add negaposi-analyzer-ja to onlyBuiltDependencies The negaposi-analyzer-ja package downloads its dictionary file (pn_ja.dic.json) via a postinstall script. Without listing it in pnpm.onlyBuiltDependencies, the script is blocked and the build fails with a missing module error. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: remove node-zopfli-es from onlyBuiltDependencies node-zopfli-es fails to build with node-gyp on Node 24 (both CI and local). It is only used for zopfli compression by shrink-ray-current and is not required for Brotli. Removing it from the allowlist lets pnpm skip its broken native build. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
npx was resolving to the latest global version (0.41.0) instead of the project-pinned version (0.36.0), causing formatting check failures. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- Remove core-js, image-size (installed but never imported) - Remove buffer package and Buffer ProvidePlugin from webpack - Replace encoding-japanese with native TextDecoder in extract_metadata_from_sound Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
fix: add SubmissionError guard for search form validation on React 19 redux-form 8.x relies on UNSAFE_componentWillReceiveProps for initial syncErrors hydration. React 19's batching changes prevent this from firing on mount when initialValues are provided, leaving the store without syncErrors and allowing invalid submissions to bypass validation. Adding explicit validate + SubmissionError in onSubmit ensures the error message is displayed even when redux-form's internal sync validation pipeline is not triggered. Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
…26) shrink-ray-current depends on iltorb, a deprecated native Brotli module that fails to build with node-gyp on Linux (Docker). Replace it with the compression middleware which uses Node.js built-in zlib and requires no native compilation. Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
fix: make AuthModalContainer static import to prevent sign-in dialog timeout
AuthModalContainer was lazy-loaded with <Suspense fallback={null}>, which meant
the <dialog> element didn't exist in the DOM until the chunk finished loading.
When the sign-in button (using Invoker Commands API: command="show-modal") was
clicked before the chunk loaded, nothing happened — causing E2E test timeouts.
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
- Remove default loading="lazy" and fetchPriority="low" from CoveredImage so above-fold images use browser native heuristics instead of being forced lazy - Correctly identify first image post in Timeline for isAboveFold marking - Set profile images in viewport to loading="eager" - Change PostItem (detail page) profile image to loading="eager" - Parallelize waveform computation in static.ts with Promise.all - Pre-compute all waveforms at server startup to warm cache and eliminate TTFB blocking on first home page request Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
fix: use inline style for dynamic background color in UserProfileHeader
Tailwind CSS cannot detect dynamically generated class names like
`bg-[${averageColor}]` at build time, so the average color extracted
from the profile image was never applied (header stayed white instead
of the expected color). Switch to an inline `style` attribute to
ensure the computed color is rendered correctly.
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
perf: defer modal chunk loading to reduce TBT variability AuthModalContainer and NewPostModalContainer were loaded via React.lazy() + Suspense on every page, causing their chunk parse/eval to sometimes fall within the FCP→TTI measurement window and inflate TBT scores unpredictably (0–30 range). Replace with DeferredModal component that: - Renders a lightweight placeholder <dialog> immediately (preserving commandfor compat) - Loads the actual chunk via requestIdleCallback (outside measurement window) - Falls back to toggle-event-driven loading if user interacts before idle load completes Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
- Remove FFmpeg WASM / ImageMagick WASM dead code (unused util files) - Move negaposi-analyzer-ja sentiment analysis to server API (/api/v1/sentiment) - Move kuromoji / BM25 suggestion filtering to server API (/api/v1/crok/suggestions?q=) - Move web-llm translation to server API (/api/v1/translate) using MyMemory - Remove 17MB kuromoji dict files from public/dicts/ - Clean up webpack config (aliases, cacheGroups, ignoreWarnings) - Remove 13 client dependencies: @ffmpeg/*, @imagemagick/*, @mlc-ai/web-llm, kuromoji, bayesian-bm25, negaposi-analyzer-ja, common-tags, json-repair-js, langs, piexifjs and related @types Client bundle reduced from ~10MB to ~2.78MB. Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* fix: use 2-phase query for search API to fix pagination with subQuery: false subQuery: false causes LIMIT to apply after JOIN expansion, so posts with multiple images consume multiple rows. Split into Phase 1 (ID-only query without images JOIN) and Phase 2 (full data fetch by IDs). Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: sort search results by createdAt DESC to match original behavior The original search code sorted results by createdAt DESC. The 2-phase query fix needs to preserve this ordering since defaultScope uses id DESC (UUIDs don't correlate with creation time). Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* perf: fix LCP image loading and pre-compute waveforms - Remove default loading="lazy" and fetchPriority="low" from CoveredImage so above-fold images use browser native heuristics instead of being forced lazy - Correctly identify first image post in Timeline for isAboveFold marking - Set profile images in viewport to loading="eager" - Change PostItem (detail page) profile image to loading="eager" - Parallelize waveform computation in static.ts with Promise.all - Pre-compute all waveforms at server startup to warm cache and eliminate TTFB blocking on first home page request Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: add server-side image resizing with disk cache Add sharp-based on-the-fly image resize middleware that intercepts image requests with ?w= query parameter, resizes to the requested width, and caches results to /tmp/image-cache/. All image components now request appropriately sized images (686px for post images, 80-256px for profile images) instead of full-resolution originals. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: use nearLossless WebP and skip resize for color-extracted profile image - UserProfileHeader uses FastAverageColor on the profile image, so resizing changes the extracted color and breaks VRT. Use original image here. - Switch WebP encoding to nearLossless for better VRT compatibility. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
chore: improve CLAUDE.md with missing API routes and dev notes - Add complete API route list (including sentiment, translate) - Add GITHUB_TOKEN note to Git & PRs section - Add parallel development workflow section for worktree-based agents Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* perf: replace redux-form with react-hook-form and remove Redux Migrate all 3 forms (auth, search, DM) from redux-form HOC to react-hook-form hooks. Remove redux, react-redux, redux-form and their type definitions. This eliminates ~55KB gzip from the initial bundle (redux-form + lodash transitive dependency + redux + react-redux). Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: use mode onChange and show errors after submit attempt - Change react-hook-form mode from onBlur to onChange so isValid updates on every keystroke (matching redux-form's invalid behavior) - Show validation errors after submit attempt (isSubmitted) to match redux-form marking all fields as touched on submit - Remove redundant manual validation in SearchPage onSubmit Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Redux removal, Webpack optimization enablement, and heavy dependency cleanup were already done in prior PRs but CLAUDE.md still described the initial unoptimized state. Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
) perf: lazy-load Markdown renderer and use startTransition for Crok chat Reduce TBT/INP on Crok AI chat by: - Wrapping onDone state updates in startTransition so React can split the heavy Markdown rendering into interruptible chunks - Extracting MarkdownRenderer (react-markdown + KaTeX + GFM) into a lazy-loaded component with Suspense fallback showing plain text Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* chore: update CLAUDE.md to reflect current codebase state Redux removal, Webpack optimization enablement, and heavy dependency cleanup were already done in prior PRs but CLAUDE.md still described the initial unoptimized state. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * perf: cache home HTML response and inject initial data for all routes Home page HTML is now cached after first build (with dedup for concurrent requests). Non-home routes (/posts/:id, /users/:username, /search) get server-injected __INITIAL_DATA__ to eliminate the JS→API waterfall. Cache is invalidated on POST /posts and rebuilt on POST /initialize. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
fix: use raw SQL subquery for correct per-conversation latest message in DM list Sequelize 6's `separate: true` + `limit: 1` applies LIMIT globally instead of per-parent, causing each conversation to show an incorrect "latest" message. Replace with a raw SQL subquery that correctly gets MAX(createdAt) per conversation, fixing DM list ordering and preview. Co-authored-by: Claude Haiku 4.5 <[email protected]>
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.
No description provided.