Skip to content

Commit fd2238e

Browse files
committed
feat: add Vitest configuration for testing and coverage
1 parent e1ab5bf commit fd2238e

37 files changed

Lines changed: 9455 additions & 42 deletions

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@
7777
"Bash(node scripts/test-stats-logic.mjs:*)",
7878
"Bash(node scripts/test-stats-api.mjs:*)",
7979
"Bash(npm run lint:*)",
80-
"Bash(xargs cat:*)"
80+
"Bash(xargs cat:*)",
81+
"Bash(pnpm --filter @pairux/shared-types build:*)"
8182
],
8283
"deny": [
8384
"Bash(npm *)",

.github/workflows/pr-checks.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: PR Checks
2+
3+
on:
4+
pull_request:
5+
branches: [main, master]
6+
push:
7+
branches: [main, master]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lint:
15+
name: Lint
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Setup pnpm
22+
uses: pnpm/action-setup@v4
23+
with:
24+
version: 9
25+
26+
- name: Setup Node.js
27+
uses: actions/setup-node@v4
28+
with:
29+
node-version: 24
30+
cache: 'pnpm'
31+
32+
- name: Install dependencies
33+
run: pnpm install --frozen-lockfile
34+
35+
- name: Lint
36+
run: pnpm lint
37+
38+
- name: Type check
39+
run: pnpm typecheck
40+
41+
- name: Format check
42+
run: pnpm format:check
43+
44+
build-web:
45+
name: Build Web
46+
runs-on: ubuntu-latest
47+
steps:
48+
- name: Checkout
49+
uses: actions/checkout@v4
50+
51+
- name: Setup pnpm
52+
uses: pnpm/action-setup@v4
53+
with:
54+
version: 9
55+
56+
- name: Setup Node.js
57+
uses: actions/setup-node@v4
58+
with:
59+
node-version: 24
60+
cache: 'pnpm'
61+
62+
- name: Install dependencies
63+
run: pnpm install --frozen-lockfile
64+
65+
- name: Build shared packages
66+
run: pnpm --filter @pairux/shared-types build
67+
68+
- name: Build web app
69+
run: pnpm --filter @pairux/web build
70+
env:
71+
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL || 'https://placeholder.supabase.co' }}
72+
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY || 'placeholder-key' }}
73+
74+
- name: Upload build artifact
75+
uses: actions/upload-artifact@v4
76+
with:
77+
name: web-build
78+
path: apps/web/.next
79+
retention-days: 7
80+
81+
test:
82+
name: Test
83+
runs-on: ubuntu-latest
84+
steps:
85+
- name: Checkout
86+
uses: actions/checkout@v4
87+
88+
- name: Setup pnpm
89+
uses: pnpm/action-setup@v4
90+
with:
91+
version: 9
92+
93+
- name: Setup Node.js
94+
uses: actions/setup-node@v4
95+
with:
96+
node-version: 24
97+
cache: 'pnpm'
98+
99+
- name: Install dependencies
100+
run: pnpm install --frozen-lockfile
101+
102+
- name: Run tests
103+
run: pnpm test
104+
105+
- name: Upload coverage
106+
uses: codecov/codecov-action@v4
107+
with:
108+
files: ./coverage/lcov.info
109+
fail_ci_if_error: false
110+
continue-on-error: true

.github/workflows/web-deploy.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Web Deploy
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
paths:
7+
- 'apps/web/**'
8+
- 'packages/**'
9+
- 'pnpm-lock.yaml'
10+
release:
11+
types: [published]
12+
workflow_dispatch:
13+
14+
jobs:
15+
deploy:
16+
name: Deploy to Railway/Vercel
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
22+
- name: Setup pnpm
23+
uses: pnpm/action-setup@v4
24+
with:
25+
version: 9
26+
27+
- name: Setup Node.js
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version: 24
31+
cache: 'pnpm'
32+
33+
- name: Install dependencies
34+
run: pnpm install --frozen-lockfile
35+
36+
- name: Build shared packages
37+
run: pnpm --filter @pairux/shared-types build
38+
39+
- name: Build web app
40+
run: pnpm --filter @pairux/web build
41+
env:
42+
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
43+
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
44+
NEXT_PUBLIC_APP_URL: ${{ secrets.NEXT_PUBLIC_APP_URL || 'https://pairux.com' }}
45+
46+
# Vercel deployment (if VERCEL_TOKEN is set)
47+
- name: Deploy to Vercel
48+
if: ${{ secrets.VERCEL_TOKEN != '' }}
49+
uses: amondnet/vercel-action@v25
50+
with:
51+
vercel-token: ${{ secrets.VERCEL_TOKEN }}
52+
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
53+
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
54+
working-directory: apps/web
55+
vercel-args: ${{ github.event_name == 'release' && '--prod' || '' }}
56+
57+
# Railway deployment (if RAILWAY_TOKEN is set) - uses railway.toml config
58+
- name: Deploy to Railway
59+
if: ${{ secrets.RAILWAY_TOKEN != '' && secrets.VERCEL_TOKEN == '' }}
60+
run: |
61+
npm install -g @railway/cli
62+
cd apps/web
63+
railway up --detach
64+
env:
65+
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
66+
67+
# Build artifact for manual deployment
68+
build-artifact:
69+
name: Build Artifact
70+
runs-on: ubuntu-latest
71+
if: github.event_name == 'workflow_dispatch'
72+
steps:
73+
- name: Checkout
74+
uses: actions/checkout@v4
75+
76+
- name: Setup pnpm
77+
uses: pnpm/action-setup@v4
78+
with:
79+
version: 9
80+
81+
- name: Setup Node.js
82+
uses: actions/setup-node@v4
83+
with:
84+
node-version: 24
85+
cache: 'pnpm'
86+
87+
- name: Install dependencies
88+
run: pnpm install --frozen-lockfile
89+
90+
- name: Build
91+
run: pnpm --filter @pairux/web build
92+
env:
93+
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL || 'https://placeholder.supabase.co' }}
94+
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY || 'placeholder-key' }}
95+
96+
- name: Upload artifact
97+
uses: actions/upload-artifact@v4
98+
with:
99+
name: web-dist
100+
path: apps/web/.next
101+
retention-days: 30

TODO.md

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,55 +7,55 @@
77

88
## 🏗️ Infrastructure & Setup
99

10-
- [ ] **Monorepo Foundation**
11-
- [ ] pnpm workspace configuration
12-
- [ ] Turborepo build pipeline
13-
- [ ] Shared TypeScript config
14-
- [ ] ESLint + Prettier setup
15-
- [ ] Vitest test framework
16-
17-
- [ ] **Environment & Deployment**
18-
- [ ] Environment variable management (.env symlinks)
19-
- [ ] Railway Docker deployment (web)
20-
- [ ] GitHub Actions CI/CD
21-
- [ ] Pre-commit hooks (lint, test, build)
10+
- [x] **Monorepo Foundation**
11+
- [x] pnpm workspace configuration
12+
- [x] Turborepo build pipeline
13+
- [x] Shared TypeScript config
14+
- [x] ESLint + Prettier setup
15+
- [x] Vitest test framework
16+
17+
- [x] **Environment & Deployment**
18+
- [x] Environment variable management (.env symlinks)
19+
- [x] Railway Docker deployment (web)
20+
- [x] GitHub Actions CI/CD
21+
- [x] Pre-commit hooks (lint, test, build)
2222

2323
---
2424

2525
## 🌐 Web App (Next.js PWA)
2626

2727
### Marketing Site
28-
- [ ] **Landing Page**
29-
- [ ] Hero section with value proposition
30-
- [ ] Feature highlights
31-
- [ ] How it works (3-step flow)
28+
- [x] **Landing Page**
29+
- [x] Hero section with value proposition
30+
- [x] Feature highlights
31+
- [x] How it works (3-step flow)
3232
- [ ] Social proof / testimonials placeholder
33-
- [ ] CTA buttons (Download, Try Now)
33+
- [x] CTA buttons (Download, Try Now)
3434

35-
- [ ] **Features Page**
36-
- [ ] Screen sharing capabilities
37-
- [ ] Remote control features
35+
- [x] **Features Page**
36+
- [x] Screen sharing capabilities
37+
- [x] Remote control features
3838
- [ ] Screen recording (local)
3939
- [ ] Text chat integration
40-
- [ ] Security highlights
41-
42-
- [ ] **Download Page**
43-
- [ ] OS detection (auto-recommend)
44-
- [ ] macOS: Homebrew cask command
45-
- [ ] Windows: WinGet command
46-
- [ ] Linux: apt/dnf/AUR commands
47-
- [ ] Direct download links (GitHub Releases)
40+
- [x] Security highlights
41+
42+
- [x] **Download Page**
43+
- [x] OS detection (auto-recommend)
44+
- [x] macOS: Homebrew cask command
45+
- [x] Windows: WinGet command
46+
- [x] Linux: apt/dnf/AUR commands
47+
- [x] Direct download links (GitHub Releases)
4848
- [ ] SHA256 checksums display
4949

50-
- [ ] **Pricing Page** (placeholder)
51-
- [ ] Free tier details
52-
- [ ] Future paid plans placeholder
50+
- [x] **Pricing Page** (placeholder)
51+
- [x] Free tier details
52+
- [x] Future paid plans placeholder
5353

54-
- [ ] **Docs/FAQ Page**
55-
- [ ] Getting started guide
56-
- [ ] System requirements
57-
- [ ] Troubleshooting common issues
58-
- [ ] Privacy & security FAQ
54+
- [x] **Docs/FAQ Page**
55+
- [x] Getting started guide
56+
- [x] System requirements
57+
- [x] Troubleshooting common issues
58+
- [x] Privacy & security FAQ
5959

6060
### PWA Viewer (Join Session)
6161
- [ ] **Session Join Flow**
@@ -290,8 +290,8 @@
290290

291291
## 🧪 Testing
292292

293-
- [ ] **Unit Tests**
294-
- [ ] Utility functions
293+
- [x] **Unit Tests**
294+
- [x] Utility functions
295295
- [ ] State management
296296
- [ ] API route handlers
297297

apps/web/next-env.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
/// <reference path="./.next/types/routes.d.ts" />
4+
5+
// NOTE: This file should not be edited
6+
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

apps/web/next.config.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import type { NextConfig } from 'next';
2+
3+
const nextConfig: NextConfig = {
4+
// Enable React strict mode for better development experience
5+
reactStrictMode: true,
6+
7+
// Transpile shared packages
8+
transpilePackages: ['@pairux/shared-types'],
9+
10+
// Image optimization
11+
images: {
12+
remotePatterns: [
13+
{
14+
protocol: 'https',
15+
hostname: '*.supabase.co',
16+
},
17+
],
18+
},
19+
20+
// Headers for security
21+
async headers() {
22+
return [
23+
{
24+
source: '/(.*)',
25+
headers: [
26+
{
27+
key: 'X-Frame-Options',
28+
value: 'DENY',
29+
},
30+
{
31+
key: 'X-Content-Type-Options',
32+
value: 'nosniff',
33+
},
34+
{
35+
key: 'Referrer-Policy',
36+
value: 'strict-origin-when-cross-origin',
37+
},
38+
],
39+
},
40+
];
41+
},
42+
43+
// Redirects
44+
async redirects() {
45+
return [
46+
{
47+
source: '/github',
48+
destination: 'https://github.com/pairux/pairux',
49+
permanent: false,
50+
},
51+
];
52+
},
53+
};
54+
55+
export default nextConfig;

0 commit comments

Comments
 (0)