Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 2 additions & 10 deletions .storybook/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
/**
* Vitest Setup for Storybook
*
* Configures project annotations for testing stories with Vitest.
* The @storybook/addon-vitest automatically handles the beforeAll hook.
* Configures browser-only mocks for Storybook's Vitest project.
* The @storybook/addon-vitest applies project annotations automatically.
*/
import * as a11yAddonAnnotations from '@storybook/addon-a11y/preview'
import { setProjectAnnotations } from '@storybook/nextjs-vite'
import { vi } from 'vitest'

import * as projectAnnotations from './preview'

/**
* Storybook browser tests render components without a Next.js server, so server
* actions must resolve successfully for optimistic UI stories to pass.
Expand All @@ -35,7 +31,3 @@ if (typeof window !== 'undefined') {
}
})
}

// Apply project annotations for testing stories
// The addon-vitest automatically loads Storybook's beforeAll hook
setProjectAnnotations([a11yAddonAnnotations, projectAnnotations])
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.3.2.0] - 2026-10-05

### Changed

- Updated all direct dependencies to their latest stable releases, including Next.js 16.3.8, React 19.3, Sentry 11, MSW 3, Vitest 5, and Motion 14.
- Adopted the TypeScript 7 native compiler for typechecking while keeping the TypeScript 6 API available to ESLint and other tools that require it.

### Fixed

- Migrated Sentry and MSW configuration to their current APIs and refreshed the test Service Worker.
- Kept unit tests stable with Motion's JavaScript animation fallback in Happy DOM.

## [0.3.1.3] - 2026-05-27

### Removed
Expand Down
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This application requires GitHub authentication to access any functionality beyo

**GitBox** - PWA for managing GitHub repositories in Kanban format.

**Tech Stack:** Next.js 16 App Router, React 19.2, Redux Toolkit, Supabase, @dnd-kit
**Tech Stack:** Next.js 16 App Router, React 19.3, Redux Toolkit, Supabase, @dnd-kit

**Navigation:** `Landing → GitHub OAuth → /boards → /board/[id] (Kanban)`

Expand Down Expand Up @@ -459,8 +459,9 @@ Dark: dark, midnight, graphite, forest, ocean, plum, rust

Key project-specific rules:

- **TypeScript 7:** `@typescript/native` supplies the `tsc` binary for `pnpm typecheck`. The `typescript` alias points to `@typescript/typescript6` so ESLint and other compiler-API consumers can use TypeScript 6. Keep both packages when updating dependencies.
- **Type-only fixes:** Don't alter runtime behavior when fixing TS errors
- **React 19.2:** Use `useOptimistic`, `useActionState`, `use` API, Form Actions
- **React 19.3:** Use `useOptimistic`, `useActionState`, `use` API, Form Actions
- **UI Components:** Reuse from `src/components/ui` (shadcn/ui)
- **Helper Functions:** Extract as pure functions below component definition

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ When you have dozens (or hundreds) of repos from side projects, experiments, and
## Tech Stack

- **Framework**: Next.js 16 (App Router)
- **UI**: React 19.2, Tailwind CSS 4, shadcn/ui
- **UI**: React 19.3, Tailwind CSS 4, shadcn/ui
- **State**: Redux Toolkit + @laststance/redux-storage-middleware
- **Database**: Supabase (PostgreSQL + Auth + RLS)
- **Rich Text**: Plate.js (Platejs 53)
- **Drag & Drop**: @dnd-kit
- **Validation**: Zod 4
- **Monitoring**: Sentry 10
- **Testing**: Playwright (E2E), Vitest (Unit), Storybook 10
- **Monitoring**: Sentry 11
- **Testing**: Playwright 1.63 (E2E), Vitest 5 (Unit), Storybook 10

## Getting Started

Expand Down
14 changes: 7 additions & 7 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@
| Category | Technology |
| ---------- | ---------------------------------------------------- |
| Framework | Next.js 16 (App Router) |
| UI Library | React 19.2 |
| Language | TypeScript 5.9 (strict, noUncheckedIndexedAccess) |
| UI Library | React 19.3 |
| Language | TypeScript 7 (strict, noUncheckedIndexedAccess) |
| Styling | Tailwind CSS 4 + shadcn/ui (OKLCH tokens) |
| State | Redux Toolkit + @laststance/redux-storage-middleware |
| Database | Supabase (PostgreSQL + Auth + RLS) |
| Rich Text | Plate.js (Platejs 52) |
| Rich Text | Plate.js (Platejs 53) |
| D&D | @dnd-kit (core + sortable + modifiers) |
| Testing | Vitest 4, Playwright 1.58, Storybook 10 |
| Monitoring | Sentry 10 |
| Testing | Vitest 5, Playwright 1.63, Storybook 10 |
| Monitoring | Sentry 11 |
| Analytics | Vercel Analytics |
| Validation | Zod 4 |
| Hosting | Vercel |
Expand Down Expand Up @@ -1301,13 +1301,13 @@ export async function cdpBoardDragAndDrop(

### 12.1 Unit Tests

- **Runner**: Vitest 4 + happy-dom
- **Runner**: Vitest 5 + happy-dom
- **Coverage**: @vitest/coverage-v8
- **React Testing**: @testing-library/react + @testing-library/user-event

### 12.2 E2E Tests (Hybrid Architecture)

- **Runner**: Playwright 1.58
- **Runner**: Playwright 1.63
- **Database**: Real local Supabase (not mocked)
- **GitHub API**: MSW mocking (stability for external API)
- **Auth**: Pre-authenticated via `e2e/auth.setup.ts`
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.3.1.3
0.3.2.0
2 changes: 1 addition & 1 deletion mocks/handlers/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* @see https://docs.github.com/en/rest
*/
import { http, HttpResponse, type HttpHandler } from 'msw'
import { http, HttpResponse, type HttpHandler } from 'msw/http'

import {
GITHUB_API_URL,
Expand Down
2 changes: 1 addition & 1 deletion mocks/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
* @see https://mswjs.io/docs/concepts/request-handler
*/
import type { HttpHandler } from 'msw'
import type { HttpHandler } from 'msw/http'

import { githubApiHandlers } from './github'
import { supabaseHandlers } from './supabase'
Expand Down
2 changes: 1 addition & 1 deletion mocks/handlers/supabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @see https://supabase.com/docs/reference/javascript/auth-api
* @see https://postgrest.org/en/stable/api.html
*/
import { http, HttpResponse, type HttpHandler } from 'msw'
import { http, HttpResponse, type HttpHandler } from 'msw/http'

import {
SUPABASE_URL,
Expand Down
4 changes: 3 additions & 1 deletion next.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { withSentryConfig } from '@sentry/nextjs'
import { withSentryConfig } from '@sentry/nextjs/config'
import { codeInspectorPlugin } from 'code-inspector-plugin'
import type { NextConfig } from 'next'

Expand All @@ -18,6 +18,8 @@ if (process.env.VERCEL && process.env.NEXT_PUBLIC_ENABLE_MSW_MOCK === 'true') {
}

const nextConfig: NextConfig = {
// Keep MSW's Node interceptors outside Turbopack for test-mode server rendering.
serverExternalPackages: ['msw'],
turbopack: {
rules: codeInspectorPlugin({
bundler: 'turbopack',
Expand Down
117 changes: 59 additions & 58 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gitbox",
"version": "0.3.1.3",
"version": "0.3.2",
"private": true,
"type": "module",
"description": "A web application for managing GitHub repositories in Kanban board format",
Expand Down Expand Up @@ -41,25 +41,25 @@
"validate": "concurrently -n build,lint,test,type -c blue,yellow,green,cyan \"pnpm run build\" \"pnpm run lint:fix\" \"vitest run\" \"pnpm run typecheck\""
},
"dependencies": {
"@ariakit/react": "^0.4.38",
"@ariakit/react": "^0.4.40",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@laststance/redux-storage-middleware": "^0.3.2",
"@laststance/redux-storage-middleware": "^0.4.0",
"@platejs/autoformat": "^53.0.0",
"@platejs/basic-nodes": "^53.0.0",
"@platejs/callout": "^53.0.0",
"@platejs/code-block": "^53.0.0",
"@platejs/combobox": "^53.0.0",
"@platejs/date": "^53.0.0",
"@platejs/dnd": "^53.1.0",
"@platejs/dnd": "^53.3.8",
"@platejs/floating": "^53.0.0",
"@platejs/indent": "^53.0.0",
"@platejs/layout": "^53.0.0",
"@platejs/link": "^53.3.5",
"@platejs/list": "^53.1.3",
"@platejs/math": "^53.0.0",
"@platejs/list": "^53.3.13",
"@platejs/math": "^53.3.12",
"@platejs/media": "^53.1.4",
"@platejs/resizable": "^53.0.0",
"@platejs/selection": "^53.1.6",
Expand All @@ -82,87 +82,88 @@
"@radix-ui/react-toolbar": "^1.1.19",
"@radix-ui/react-tooltip": "^1.2.16",
"@radix-ui/react-visually-hidden": "^1.2.11",
"@reduxjs/toolkit": "^2.12.0",
"@sentry/nextjs": "^10.71.0",
"@supabase/ssr": "^0.12.5",
"@supabase/supabase-js": "^2.112.4",
"@reduxjs/toolkit": "^2.13.0",
"@sentry/nextjs": "^11.4.0",
"@supabase/ssr": "^0.12.7",
"@supabase/supabase-js": "^2.117.2",
"@t3-oss/env-nextjs": "^0.13.11",
"@tanstack/react-virtual": "^3.14.10",
"@tanstack/react-virtual": "^3.14.13",
"@types/lodash": "^4.17.25",
"@udecode/cn": "^52.3.4",
"@vercel/analytics": "^2.0.1",
"axios": "^1.19.0",
"axios": "^1.20.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"destr": "^2.0.5",
"framer-motion": "^13.1.1",
"framer-motion": "^14.0.0",
"lodash": "^4.18.1",
"lowlight": "^3.3.0",
"lucide-react": "^1.34.0",
"next": "^16.3.2",
"lucide-react": "^1.52.0",
"next": "^16.3.8",
"nextjs-toploader": "^3.9.17",
"pino": "^10.3.1",
"platejs": "^53.3.7",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"pino": "^10.4.0",
"platejs": "^53.3.15",
"react": "^19.3.0",
"react-dom": "^19.3.0",
"react-redux": "^9.3.0",
"sonner": "^2.0.8",
"tailwind-merge": "^3.6.0",
"tailwind-merge": "^3.7.0",
"ts-pattern": "^5.9.0",
"zod": "^4.4.3"
"zod": "^4.6.5"
},
"devDependencies": {
"@chromatic-com/storybook": "^5.3.0",
"@laststance/react-next-eslint-plugin": "^2.3.0",
"@next/eslint-plugin-next": "16.3.2",
"@playwright/test": "^1.62.1",
"@storybook/addon-a11y": "^10.5.10",
"@storybook/addon-docs": "^10.5.10",
"@storybook/addon-mcp": "^0.7.0",
"@storybook/addon-vitest": "^10.5.10",
"@storybook/nextjs-vite": "^10.5.10",
"@chromatic-com/storybook": "^5.4.0",
"@laststance/react-next-eslint-plugin": "^2.4.0",
"@next/eslint-plugin-next": "16.3.8",
"@playwright/test": "^1.63.0",
"@storybook/addon-a11y": "^10.6.1",
"@storybook/addon-docs": "^10.6.1",
"@storybook/addon-mcp": "^10.6.1",
"@storybook/addon-vitest": "^10.6.1",
"@storybook/nextjs-vite": "^10.6.1",
"@tailwindcss/postcss": "^4.3.3",
"@tailwindcss/vite": "^4.3.3",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.6",
"@types/node": "^26.2.0",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.5",
"@vitejs/plugin-react": "^6.1.0",
"@vitest/browser-playwright": "^4.1.11",
"@vitest/coverage-v8": "^4.1.11",
"code-inspector-plugin": "^2.0.8",
"@testing-library/react": "^16.3.3",
"@testing-library/user-event": "^14.6.7",
"@types/node": "^26.6.4",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@typescript/native": "npm:typescript@^7.0.2",
"@vitejs/plugin-react": "^6.1.1",
"@vitest/browser-playwright": "^5.0.3",
"@vitest/coverage-v8": "^5.0.3",
"code-inspector-plugin": "^2.0.9",
"concurrently": "^10.0.5",
"eslint": "^10.9.1",
"eslint-config-ts-prefixer": "^4.3.0",
"eslint": "^10.12.0",
"eslint-config-ts-prefixer": "^5.1.0",
"eslint-import-resolver-typescript": "^4.4.5",
"eslint-plugin-browser-security": "^2.0.6",
"eslint-plugin-browser-security": "^2.1.9",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-you-might-not-need-an-effect": "^1.0.2",
"globals": "^17.11.0",
"happy-dom": "^20.11.6",
"globals": "^17.13.0",
"happy-dom": "^20.14.5",
"husky": "^9.1.7",
"knip": "^6.32.2",
"lint-staged": "^17.3.0",
"monocart-reporter": "^2.12.6",
"msw": "^2.15.0",
"msw-storybook-addon": "^3.0.0",
"playwright": "^1.62.1",
"postcss": "^8.5.26",
"prettier": "^3.9.6",
"knip": "^6.39.0",
"lint-staged": "^17.6.0",
"monocart-reporter": "^2.14.0",
"msw": "^3.0.2",
"msw-storybook-addon": "^3.0.3",
"playwright": "^1.63.0",
"postcss": "^8.5.28",
"prettier": "^3.9.9",
"prettier-plugin-tailwindcss": "^0.8.1",
"prettier-plugin-tailwindcss-canonical-classes": "^0.1.5",
"storybook": "^10.5.10",
"prettier-plugin-tailwindcss-canonical-classes": "^0.1.6",
"storybook": "^10.6.1",
"tailwind-scrollbar-hide": "^4.0.0",
"tailwindcss": "^4.3.3",
"tailwindcss-animate": "^1.0.7",
"tsx": "^4.23.12",
"tsx": "^4.23.15",
"tw-animate-css": "^1.4.0",
"typescript": "^6.0.3",
"vite": "^8.2.2",
"vitest": "^4.1.11"
"typescript": "npm:@typescript/typescript6@^6.0.2",
"vite": "^8.3.2",
"vitest": "^5.0.3"
}
}
Loading
Loading