Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
af1e318
chore: claude init
leonard475192 Mar 20, 2026
a31bfdb
perf: enable webpack production mode, tree-shaking, and code splitting
leonard475192 Mar 20, 2026
633d5ab
perf: add compression middleware and optimize cache headers
leonard475192 Mar 20, 2026
0f8143e
Merge branch 'CyberAgentHack:main' into main
leonard475192 Mar 20, 2026
16b77b7
Merge pull request #1 from leonard475192/perf/webpack-babel
leonard475192 Mar 20, 2026
c45ce67
Merge pull request #2 from leonard475192/perf/server-optimization
leonard475192 Mar 20, 2026
1e04def
Merge pull request #7 from leonard475192/perf/webpack-babel
leonard475192 Mar 20, 2026
d160893
perf: re migrate Tailwind CSS from CDN to build-time (#8)
leonard475192 Mar 20, 2026
2bb6edf
perf: replace jQuery, moment.js, lodash, bluebird with native APIs (#9)
leonard475192 Mar 20, 2026
d85c14a
perf: add route-based code splitting with React.lazy (#5)
leonard475192 Mar 20, 2026
1f78011
ci: add CI workflow for lint, typecheck, build, and E2E (#10)
leonard475192 Mar 20, 2026
12591e4
ci: parallelize E2E tests with sharding and Playwright cache (#11)
leonard475192 Mar 20, 2026
92985e6
chore: add pre-commit hook with lint-staged (#12)
leonard475192 Mar 20, 2026
1001037
perf: optimize fonts (WOFF2), images (WebP), CoveredImage (#6)
leonard475192 Mar 20, 2026
ee788ac
style: fix oxfmt formatting in CoveredImage and index.css (#13)
leonard475192 Mar 20, 2026
05cead4
ci: fix VRT snapshots for Linux CI (#14)
leonard475192 Mar 20, 2026
bd2e98d
perf: eliminate UI jank from aggressive polling and DOM reads (#15)
leonard475192 Mar 20, 2026
a2057a6
perf: optimize initial render (FCP/LCP improvement) (#16)
leonard475192 Mar 20, 2026
fa9578d
perf: reduce bundle size (splitChunks, polyfill removal) (#17)
leonard475192 Mar 20, 2026
0765439
perf: subset fonts (3.8MB→260KB) and dynamic katex CSS (#19)
leonard475192 Mar 20, 2026
86c5da1
perf: optimize media (native GIF/audio, remove heavy deps) (#18)
leonard475192 Mar 20, 2026
b361e69
perf: eliminate runtime bottlenecks (polling, re-renders, debounce) (…
leonard475192 Mar 20, 2026
17e266a
perf: optimize server DB queries and add indexes (#23)
leonard475192 Mar 20, 2026
13e7ba9
perf: add Brotli compression via shrink-ray-current (#20)
leonard475192 Mar 20, 2026
d00d61a
fix(ci): use pnpm exec instead of npx for oxlint/oxfmt
leonard475192 Mar 20, 2026
3c7e496
perf: remove unused dependencies and Buffer polyfill (#22)
leonard475192 Mar 20, 2026
b9980d0
ci: add oxfmt diff debug step to diagnose Linux formatting issue
leonard475192 Mar 20, 2026
380191a
ci: remove oxfmt debug step
leonard475192 Mar 20, 2026
3440ad8
fix: search form validation bypass on React 19 (#25)
leonard475192 Mar 20, 2026
041b753
fix: replace shrink-ray-current with compression to fix Docker build …
leonard475192 Mar 20, 2026
60f194c
perf: optimize image delivery and add resource hints (#24)
leonard475192 Mar 20, 2026
5ddc872
Merge branch 'CyberAgentHack:main' into main
leonard475192 Mar 20, 2026
cbc99b7
fix: resolve e2e test failures after perf optimizations (#27)
leonard475192 Mar 20, 2026
4329cb9
perf: improve LCP across all pages (#28)
leonard475192 Mar 20, 2026
4e4a234
chore: add Git/PR rules, debugging guidelines and cleanup deps (#29)
leonard475192 Mar 20, 2026
d0e5c94
perf: fix LCP root causes - pagination, DM query, skeletons, image at…
leonard475192 Mar 20, 2026
5aa7c52
perf: lazy load containers and dynamically import WASM (#32)
leonard475192 Mar 21, 2026
b87dbc5
perf: lazy load negaposi-analyzer-ja dictionary (#33)
leonard475192 Mar 21, 2026
75f54c3
perf: inject initial API data into HTML for faster LCP (#34)
leonard475192 Mar 21, 2026
a67203d
perf: convert GIF movies to MP4 for 83% size reduction (#31)
leonard475192 Mar 21, 2026
20badc3
perf: fix ReDoS in password validation (#35)
leonard475192 Mar 21, 2026
7d713b2
perf: fix ReDoS in search query parsing (#36)
leonard475192 Mar 21, 2026
05a18fb
perf: optimize Crok AI SSE streaming and rendering (#37)
leonard475192 Mar 21, 2026
d9a0a05
perf: improve DM INP with typing throttle and optimistic updates (#38)
leonard475192 Mar 21, 2026
cd12f52
perf: move media conversion from client WASM to server-side (#39)
leonard475192 Mar 21, 2026
96ba5ab
perf: optimize bundle size with dynamic imports and code splitting (#40)
leonard475192 Mar 21, 2026
41dc847
perf: optimize network fetching and caching (#42)
leonard475192 Mar 21, 2026
0aa24ff
Fix conflict test (#43)
leonard475192 Mar 21, 2026
d1010cd
fix: resolve DM read receipt race condition (#44)
leonard475192 Mar 21, 2026
f68b618
ci: fix Docker build failure and add docker-build CI job (#45)
leonard475192 Mar 21, 2026
32a93dc
Merge branch 'main' into main
leonard475192 Mar 21, 2026
3c63091
fix: sort DM conversations by latest message timestamp (#46)
leonard475192 Mar 21, 2026
4a8775a
perf: optimize rendering performance and reduce CLS (#41)
leonard475192 Mar 21, 2026
8f5166f
chore: update VRT snapshots from reference images (#47)
leonard475192 Mar 21, 2026
4819e57
perf: optimize Crok AI chat streaming performance (#48)
leonard475192 Mar 21, 2026
f5642a2
perf: optimize DM page queries (#49)
leonard475192 Mar 21, 2026
a955503
perf: optimize home timeline loading performance (#50)
leonard475192 Mar 21, 2026
281ecd3
chore: add restart script and fix stale HTML cache in dev (#51)
leonard475192 Mar 21, 2026
24dbbda
fix: AuthModalContainer を静的importに変更しサインインダイアログのタイムアウトを修正 (#52)
leonard475192 Mar 21, 2026
4320100
perf: fix LCP image loading and pre-compute waveforms (#54)
leonard475192 Mar 21, 2026
e0f6063
fix: use inline style for user profile header background color (#55)
leonard475192 Mar 21, 2026
bc8cea6
perf: defer modal chunk loading to reduce TBT (#53)
leonard475192 Mar 21, 2026
26540a0
perf: remove heavy client-side deps and move processing to server (#57)
leonard475192 Mar 21, 2026
038b42f
fix: search API pagination with subQuery: false (#56)
leonard475192 Mar 21, 2026
f99cc17
perf: add server-side image resizing for properly sized images (#58)
leonard475192 Mar 21, 2026
12f1606
chore: improve CLAUDE.md with missing info and dev notes (#60)
leonard475192 Mar 21, 2026
ccfb805
perf: replace redux-form with react-hook-form, remove Redux (#59)
leonard475192 Mar 21, 2026
23de48d
fix: remove unused setError variable in SearchPage (#61)
leonard475192 Mar 21, 2026
21731b0
chore: update CLAUDE.md to reflect current codebase state (#62)
leonard475192 Mar 21, 2026
7011f1e
perf: lazy-load Markdown renderer and startTransition for Crok chat (…
leonard475192 Mar 21, 2026
f967a0b
perf: cache home HTML and inject initial data for all routes (#64)
leonard475192 Mar 21, 2026
335968a
style: ユーザー名 (#65)
leonard475192 Mar 21, 2026
6bd17fb
fix: correct DM list ordering by using raw SQL for latest message (#67)
leonard475192 Mar 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .claude/skills/pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# PR作成スキル

## Context

- Current git status: !`git status`
- Current git diff (staged and unstaged changes): !`git diff HEAD`
- Current branch: !`git branch --show-current`
- Commits on branch: !`git log --oneline main..HEAD 2>/dev/null`

## Your task

Context の情報だけで判断し、追加の確認コマンド(`git remote -v`, `gh auth status`, `git log` 等)は実行しない。即座に以下を実行する:

1. main ブランチにいる場合は新しいフィーチャーブランチを作成する(`perf/`, `fix/`, `chore/`, `ci/` などのプレフィックスを使用)
2. 未コミットの変更がある場合のみ、適切なコミットメッセージで単一のコミットを作成する
3. origin に push する
4. `unset GITHUB_TOKEN && gh auth switch --user leonard475192 2>&1` を実行してから `gh pr create` で PR を作成する

ルール:
- `--repo leonard475192/web-speed-hackathon-2026` を必ず指定する
- upstream(CyberAgentHack)には絶対に PR を作らない
- タイトルは70文字以内

```
unset GITHUB_TOKEN && gh auth switch --user leonard475192 2>&1 && \
gh pr create \
--repo leonard475192/web-speed-hackathon-2026 \
--base main \
--title "prefix: short description" \
--body "$(cat <<'EOF'
## Summary
- 変更点1
- 変更点2

## Test plan
- [ ] テスト項目

Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"
```

5. You have the capability to call multiple tools in a single response. You MUST do all of the above in a single message. Do not use any other tools or do anything else. Do not send any other text or messages besides these tool calls.
119 changes: 119 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: CI

on:
push:
branches: [main]
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: "24.14.0"
cache: pnpm
cache-dependency-path: application/pnpm-lock.yaml
- run: cd application && pnpm install --frozen-lockfile
- run: cd application && pnpm exec oxlint .
- run: cd application && pnpm exec oxfmt --check .

typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: "24.14.0"
cache: pnpm
cache-dependency-path: application/pnpm-lock.yaml
- run: cd application && pnpm install --frozen-lockfile
- run: cd application && pnpm run typecheck

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: "24.14.0"
cache: pnpm
cache-dependency-path: application/pnpm-lock.yaml
- run: cd application && pnpm install --frozen-lockfile
- run: cd application && pnpm run build
- uses: actions/upload-artifact@v4
with:
name: client-dist
path: application/dist/
retention-days: 1

e2e:
runs-on: macos-latest
needs: build
continue-on-error: true
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3]
shardTotal: [3]
steps:
- uses: actions/checkout@v4
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: "24.14.0"
cache: pnpm
cache-dependency-path: application/pnpm-lock.yaml
- run: cd application && pnpm install --frozen-lockfile
- uses: actions/download-artifact@v4
with:
name: client-dist
path: application/dist/
- name: Get Playwright version
id: playwright-version
run: echo "version=$(cd application/e2e && npx playwright --version)" >> "$GITHUB_OUTPUT"
- uses: actions/cache@v4
id: playwright-cache
with:
path: ~/Library/Caches/ms-playwright
key: playwright-macos-${{ steps.playwright-version.outputs.version }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: cd application && pnpm --filter @web-speed-hackathon-2026/e2e exec playwright install --with-deps chrome
- name: Install Playwright deps (cached)
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: cd application && pnpm --filter @web-speed-hackathon-2026/e2e exec playwright install-deps chrome
- name: Start server and run E2E tests
env:
E2E_WORKERS: 2
run: |
cd application && pnpm run start &
for i in $(seq 1 30); do curl -s http://localhost:3000 > /dev/null 2>&1 && break; sleep 2; done
cd application/e2e && pnpm run test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: e2e-report-${{ matrix.shardIndex }}
path: application/e2e/test-results/
retention-days: 7

docker-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: .
push: false
load: true
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cd application && npx lint-staged
146 changes: 146 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Web Speed Hackathon 2026 — 架空の SNS「CaX」のパフォーマンスを改善する競技。意図的に重く作られたアプリを高速化する。採点は Lighthouse ベース(1150点満点)。

**重要な制約(レギュレーション):**

- VRT と手動テストが失敗しない範囲でのみ変更可能
- `fly.toml` は変更禁止
- `GET /api/v1/crok{?prompt}` の SSE プロトコルは変更禁止
- `POST /api/v1/initialize` でデータベースが初期値にリセットされること必須
- シードデータの各種 ID は変更禁止

## Commands

### Setup

```bash
mise trust && mise install # Node 24.14.0 + pnpm 10.32.1
cd application && pnpm install --frozen-lockfile
```

### Build & Run (application/ ディレクトリ内)

```bash
pnpm run build # Webpack でクライアントビルド
pnpm run start # サーバー起動 (http://localhost:3000)
```

### Lint & Format (application/ ディレクトリ内)

```bash
pnpm run format # oxlint --fix && oxfmt
pnpm run typecheck # 全ワークスペースの tsc
```

### E2E テスト (application/ ディレクトリ内)

```bash
pnpm --filter @web-speed-hackathon-2026/e2e exec playwright install chromium
pnpm run build && pnpm run start # サーバー起動が前提
cd e2e && pnpm run test # VRT 実行 (localhost:3000)
cd e2e && pnpm run test:update # スナップショット更新
E2E_BASE_URL=https://example.com pnpm run test # リモート対象
```

### ローカル採点 (scoring-tool/ ディレクトリ内)

```bash
cd scoring-tool && pnpm install --frozen-lockfile
pnpm start --applicationUrl http://localhost:3000
pnpm start --applicationUrl http://localhost:3000 --targetName # 計測名一覧
pnpm start --applicationUrl http://localhost:3000 --targetName "投稿" # 特定の計測のみ
```

### シードデータ (application/server/ ディレクトリ内)

```bash
pnpm run seed:generate # シード生成
pnpm run seed:insert # シード挿入
```

## Architecture

### Monorepo 構成 (pnpm workspaces)

- `application/client/` — React 19 SPA (Webpack 5, Babel, React Router v7)
- `application/server/` — Express 5 API サーバー (Sequelize + SQLite, tsx で実行)
- `application/e2e/` — Playwright VRT
- `application/upload/` — ユーザーアップロードメディアの保存先
- `scoring-tool/` — Lighthouse ベースの採点ツール(独立した pnpm workspace)

### Key Files

- `application/client/webpack.config.js` — Webpack ビルド設定(最適化の主要編集対象)
- `application/client/src/index.tsx` — クライアントエントリポイント
- `application/client/src/containers/AppContainer.tsx` — ルーティング定義
- `application/server/src/index.ts` — サーバーエントリポイント
- `application/server/src/routes/api/` — REST API ルート群
- `application/server/src/eventhub.ts` — リアルタイムイベントバス
- `Dockerfile` — Alpine Linux ベースのデプロイ用ビルド
- `mise.toml` — Node.js / pnpm バージョン管理

### Client

- **エントリポイント**: `client/src/index.tsx` → BrowserRouter
- **ルーティング** (`containers/AppContainer.tsx`): `/`, `/posts/:postId`, `/dm`, `/dm/:conversationId`, `/search`, `/users/:username`, `/terms`, `/crok`。全ページ `React.lazy` でcode-split済み
- **状態管理**: React hooks でローカル管理(Redux は削除済み)
- **ビルド**: Webpack 5。minimize, splitChunks, concatenateModules, usedExports, sideEffects 有効化済み。バンドル合計 約930KB
- **残存する重い依存**: katex(数式レンダリング)

### Server

- **エントリポイント**: `server/src/index.ts` → Sequelize 初期化 → Express app 起動 (port 3000)
- **DB**: SQLite (`server/src/database.sqlite` をシードとして temp にコピー)。起動時に毎回初期化
- **セッション**: express-session (MemoryStore)
- **リアルタイム**: WebSocket (ws) で DM・タイピング通知、SSE で CROK AI チャット
- **API**: `/api/v1/` 以下に REST エンドポイント群。主要ルートファイルは `server/src/routes/api/` 配下
- **モデル**: User, Post, Image, Movie, Sound, Comment, ProfileImage, DirectMessage, DirectMessageConversation, QaSuggestion
- **API ルート**: auth, initialize, image, movie, post, user, direct_message, sound, crok, search, sentiment, translate
- **イベントバス**: `server/src/eventhub.ts` (Node EventEmitter) でリアルタイム機能を実装

### 採点ページ(9ページ表示 + 5シナリオ操作)

表示: ホーム, 投稿詳細(テキスト/写真/動画/音声), DM一覧, DM詳細, 検索, 利用規約
操作: 認証, DM送信, 検索, Crok AI, 投稿

## Git & PRs

- `gh` コマンド実行時は `GITHUB_TOKEN=` 環境変数を付与する
- PRを作成する前に `git remote -v` と `gh repo view --json nameWithOwner` でリモートを確認し、ターゲットリポジトリをユーザーに確認する
- origin = `leonard475192/web-speed-hackathon-2026`(フォーク)、upstream = `CyberAgentHack/web-speed-hackathon-2026`(本家)
- PRは常に **origin(フォーク)** に対して作成する。upstream に PR を作らない
- main に直接 push しない。必ずフィーチャーブランチを作成する
- 1改善 = 1PR の粒度を保つ

## デバッグ指針

- ホワイトスクリーンやアプリ障害時は、ブラウザキャッシュクリアなどの表面的な対処ではなく、エラーハンドリングコード(API レスポンスハンドラ等)を調査する
- CI 失敗時は修正を試みる前に: 1) CI 設定ファイルを読む、2) エラーログ全文を読む、3) 根本原因の仮説を立ててユーザーに共有する
- 修正が成功したと主張する前に、実際のテスト出力で検証する

## Development Notes

### 並行開発

- パフォーマンス改善は worktree を使い並行して実施する(`EnterWorktree` → agent 並列実行)
- 1改善 = 1ブランチ = 1PR の粒度を保つ

### Docker / デプロイ制約

- Dockerfile は Alpine Linux ベース。ネイティブアドオンを含む npm パッケージ(例: `shrink-ray-current`, `node-zopfli-es`)はビルドに失敗する可能性が高い。pure JS の代替を選ぶこと(例: `compression`)
- `fly.toml` は変更禁止

### CI 注意事項

- CI 上で oxlint / oxfmt を実行する場合は `pnpm exec` を使う(`npx` は不可)

### パフォーマンス変更時のワークフロー

- パフォーマンス変更後は必ず E2E テスト(VRT)を実行して視覚的な差分がないか確認すること
- 変更が多岐にわたる場合、最初から個別ブランチで作業し、1改善=1PR の粒度を保つ
- `pnpm run build && pnpm run start` 後に `cd e2e && pnpm run test` で確認
6 changes: 2 additions & 4 deletions application/client/babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ module.exports = {
[
"@babel/preset-env",
{
targets: "ie 11",
corejs: "3",
modules: "commonjs",
targets: "defaults",
modules: false,
useBuiltIns: false,
},
],
[
"@babel/preset-react",
{
development: true,
runtime: "automatic",
},
],
Expand Down
Loading
Loading