Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
afad7cd
refactor: simplify pagination logic and improve type safety
Producdevity May 26, 2026
49393ea
refactor: rename helper function for clarity and ensure unique elemen…
Producdevity May 26, 2026
cc02009
refactor: update cookie consent logic to use storage keys and improve…
Producdevity May 26, 2026
17d15b3
refactor: add native thin scrollbar styles for improved aesthetics
Producdevity May 26, 2026
2fbc2ea
refactor: mock external service scripts
Producdevity May 26, 2026
dc4e0a4
refactor: remove beta feature flag and related components
Producdevity May 27, 2026
c075f78
refactor: remove AnimatePresence wrapper from ActiveFiltersSummary co…
Producdevity May 27, 2026
6b8e661
refactor: replace individual Async*MultiSelect components with consol…
Producdevity May 27, 2026
95f1f3f
refactor: update AsyncSocFilterSelect tests to use constants for opti…
Producdevity May 28, 2026
7cd1846
refactor: update service and tests to use TrustPrismaTransaction type…
Producdevity May 28, 2026
6acb6aa
refactor: update service and tests to use TrustPrismaTransaction type…
Producdevity May 28, 2026
40d79ad
refactor: update form event types from FormEvent to SubmitEvent for c…
Producdevity May 28, 2026
26e4a60
refactor: add internal-regex setting and adjust path groups for ESLin…
Producdevity May 28, 2026
5d744d2
fix: address review and own-report handling
Producdevity May 28, 2026
7b024bf
docs: clarify deployment and commit permissions in AGENTS.md
Producdevity May 28, 2026
de43ea4
refactor: remove reverseTrustAction function
Producdevity May 28, 2026
65e1a19
docs: filters and selects documentation for clarity
Producdevity May 28, 2026
f6f058e
fix: include index in Autocomplete option IDs to ensure uniqueness
Producdevity May 28, 2026
d470445
fix: Turnstile configuration check to require both keys
Producdevity May 29, 2026
5efc41d
fix: prevent impossible challenge when human verification is not conf…
Producdevity May 29, 2026
9f664cc
fix: disable retry for mutations in TRPC query configuration
Producdevity May 29, 2026
561952a
fix: refactor safe ID generation for Autocomplete options
Producdevity May 29, 2026
8326dda
test: add structured error handling tests and improve error serializa…
Producdevity May 29, 2026
a3fa69c
docs: streamline error handling documentation and update usage examples
Producdevity May 29, 2026
d6378d2
fix: handle Turnstile script readiness and widget initialization more…
Producdevity May 30, 2026
458c917
fix: remove unused Google Analytics script
Producdevity May 30, 2026
f6aec3e
fix: update Turnstile keys in environment example files
Producdevity Jun 1, 2026
ea06e2b
fix: implement rate limits and duplicate detection for game submissions
Producdevity Jun 1, 2026
01c294c
fix: update game placeholder SVG with new design and layout adjustments
Producdevity Jun 1, 2026
8eba5f7
fix: improve Turnstile script handling and widget rendering reliabili…
Producdevity Jun 1, 2026
b1c8112
fix: validate Turnstile responses with stricter hostname and action c…
Producdevity Jun 1, 2026
68a30e9
tests: fix tests, remove tests that are not actually testing anything
Producdevity Jun 1, 2026
91cd3dc
refactor: remove redundant comments from CommunitySupportBanner compo…
Producdevity Jun 1, 2026
fb51cfa
refactor: add noinspection directive to spam-check test file
Producdevity Jun 1, 2026
75f19a6
chore: use pnpm in git hooks
Producdevity Jun 2, 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
10 changes: 7 additions & 3 deletions .env.docker.example
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ TUNNEL_TOKEN="your_cloudflare_tunnel_token_here"
# CLOUDFLARE TURNSTILE (Optional)
# ===========================================
# Human verification
NEXT_PUBLIC_TURNSTILE_SITE_KEY="your_turnstile_site_key_here"
TURNSTILE_SECRET_KEY="your_turnstile_secret_key_here"
NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA

# ===========================================
# EMAIL SERVICES (Optional)
Expand All @@ -61,9 +61,14 @@ NEXT_PUBLIC_GA_ID="your_google_analytics_id_here"
# APPLICATION CONFIGURATION
# ===========================================
# Public app configuration
# local | test | preview | staging | production
NEXT_PUBLIC_APP_ENV=local
NEXT_PUBLIC_LOCAL_STORAGE_PREFIX="@DockerEmuReady_"
NEXT_PUBLIC_EMUREADY_BETA_URL="https://play.google.com/store/apps/details?id=com.producdevity.emureadyapp"
NEXT_PUBLIC_VERCEL_ANALYTICS_ENABLED=false
NEXT_PUBLIC_ENABLE_ANALYTICS=false
NEXT_PUBLIC_ENABLE_KOFI_WIDGET=false
NEXT_PUBLIC_ENABLE_SENTRY=false
NEXT_PUBLIC_DISCORD_LINK="https://discord.gg/CYhCzApXav"
NEXT_PUBLIC_PATREON_LINK="https://www.patreon.com/Producdevity"
NEXT_PUBLIC_KOFI_LINK="https://ko-fi.com/producdevity"
Expand All @@ -72,7 +77,6 @@ NEXT_PUBLIC_GITHUB_URL="https://github.com/Producdevity/EmuReady"
NEXT_PUBLIC_EMUREADY_LITE_GITHUB_URL="https://github.com/Producdevity/EmuReadyLite/releases"
NEXT_PUBLIC_APP_URL="https://dev.emuready.com"
NEXT_PUBLIC_ENABLE_SW=false
NEXT_PUBLIC_IS_BETA=false
NEXT_PUBLIC_ENABLE_ASYNC_LISTINGS_FILTERS=false
NEXT_PUBLIC_ENABLE_V2_LISTINGS=false
NEXT_TELEMETRY_DISABLED=1
Expand Down
10 changes: 7 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ NEXT_PUBLIC_IGDB_CLIENT_ID="IGDB-Client-ID"
IGDB_CLIENT_KEY="IGDB-Client-Secret"

# Cloudflare Turnstile
NEXT_PUBLIC_TURNSTILE_SITE_KEY=0x4XXXXXXXXXXXXXXXXXXXXX
TURNSTILE_SECRET_KEY=0x4XXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXX
NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA

# Email Providers (For the future)
EMAIL_ENABLED=false
Expand All @@ -34,10 +34,15 @@ EMAIL_FROM_NAME="EmuReady Team"
# EMAIL_API_KEY="your-mailersend-api-key-here"

# Public Variables
# local | test | preview | staging | production
NEXT_PUBLIC_APP_ENV=local
NEXT_PUBLIC_GA_ID="Google-Analytics-ID"
NEXT_PUBLIC_LOCAL_STORAGE_PREFIX="@LocalEmuReady_"
NEXT_PUBLIC_EMUREADY_BETA_URL="https://play.google.com/store/apps/details?id=com.producdevity.emureadyapp"
NEXT_PUBLIC_VERCEL_ANALYTICS_ENABLED=false
NEXT_PUBLIC_ENABLE_ANALYTICS=false
NEXT_PUBLIC_ENABLE_KOFI_WIDGET=false
NEXT_PUBLIC_ENABLE_SENTRY=false
NEXT_PUBLIC_DISCORD_LINK="https://discord.gg/CYhCzApXav"
NEXT_PUBLIC_PATREON_LINK="https://www.patreon.com/Producdevity"
NEXT_PUBLIC_KOFI_LINK="https://ko-fi.com/producdevity"
Expand All @@ -46,7 +51,6 @@ NEXT_PUBLIC_GITHUB_URL="https://github.com/Producdevity/EmuReady"
NEXT_PUBLIC_EMUREADY_LITE_GITHUB_URL="https://github.com/Producdevity/EmuReadyLite/releases"
NEXT_PUBLIC_APP_URL="http://localhost:3000" # Make sure to change this if you are using a tunnel
NEXT_PUBLIC_ENABLE_SW=false
NEXT_PUBLIC_IS_BETA=false
NEXT_PUBLIC_ENABLE_PATREON_VERIFICATION=true
NEXT_PUBLIC_ENABLE_ASYNC_LISTINGS_FILTERS=false
NEXT_PUBLIC_ENABLE_V2_LISTINGS=false
Expand Down
9 changes: 6 additions & 3 deletions .env.test.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
CLERK_SECRET_KEY="sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Cloudflare Turnstile
NEXT_PUBLIC_TURNSTILE_SITE_KEY=
TURNSTILE_SECRET_KEY=
NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA

# Email (For the future)
EMAIL_ENABLED=false
Expand All @@ -26,17 +26,20 @@ EMAIL_FROM_NAME="EmuReady Test Team"
# Services

RAWG_API_KEY=""
NEXT_PUBLIC_APP_ENV=test
NEXT_PUBLIC_GA_ID=""
NEXT_PUBLIC_LOCAL_STORAGE_PREFIX="@TestEmuReady_"
NEXT_PUBLIC_EMUREADY_BETA_URL="https://play.google.com/store/apps/details?id=com.producdevity.emureadyapp"
NEXT_PUBLIC_VERCEL_ANALYTICS_ENABLED=false
NEXT_PUBLIC_ENABLE_ANALYTICS=false
NEXT_PUBLIC_ENABLE_KOFI_WIDGET=false
NEXT_PUBLIC_ENABLE_SENTRY=false
NEXT_PUBLIC_DISCORD_LINK="https://discord.gg/CYhCzApXav"
NEXT_PUBLIC_PATREON_LINK="https://www.patreon.com/Producdevity"
NEXT_PUBLIC_KOFI_LINK="https://ko-fi.com/producdevity"
NEXT_PUBLIC_APP_URL="https://dev.emuready.com"
NEXT_PUBLIC_ENABLE_PATREON_VERIFICATION=true
NEXT_PUBLIC_ENABLE_SW=false
NEXT_PUBLIC_IS_BETA=false
NEXT_PUBLIC_DISABLE_COOKIE_BANNER=true
NEXT_PUBLIC_ENABLE_ASYNC_LISTINGS_FILTERS=false
NEXT_PUBLIC_ENABLE_V2_LISTINGS=false
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
NEXT_PUBLIC_GA_ID: ${{ secrets.NEXT_PUBLIC_GA_ID }}
NEXT_PUBLIC_IGDB_CLIENT_ID: ${{ secrets.NEXT_PUBLIC_IGDB_CLIENT_ID }}
NEXT_PUBLIC_LOCAL_STORAGE_PREFIX: ${{ secrets.NEXT_PUBLIC_LOCAL_STORAGE_PREFIX }}
NEXT_PUBLIC_LOCAL_STORAGE_PREFIX: "@TestEmuReady_"
RAWG_API_KEY: ${{ secrets.RAWG_API_KEY }}
THE_GAMES_DB_API_KEY: ${{ secrets.THE_GAMES_DB_API_KEY }}
# Test configuration
Expand Down
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
npm exec lint-staged
pnpm exec lint-staged
6 changes: 3 additions & 3 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
npm run lint
npm run types
npm run test
pnpm lint
pnpm types
pnpm test
27 changes: 12 additions & 15 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ This file is the source of working guidance for AI coding agents in this reposit
- `pnpm prisma validate` validates the schema.
- Database-backed Prisma commands must use the project scripts that wrap `scripts/db-cmd.sh` when available.
- Do not run `pnpm dev`, `pnpm build`, `pnpm start`, `pnpm run deploy`, migrations, seeds, or data scripts unless the user explicitly asks.
- Never deploy, commit, or push unless the user explicitly asks.
- Never deploy, commit, or push unless the user explicitly asks for that exact
action. Requests to fix a PR, update a PR, address review comments, check CI,
or prepare changes do not imply permission to commit or push.
- Use the current git user as commit author; never add Codex/AI authorship or AI-themed branch names.

## Domain Rules
Expand Down Expand Up @@ -60,6 +62,8 @@ This file is the source of working guidance for AI coding agents in this reposit
- Use generated Prisma types where appropriate.
- Do not add unused functions, exports, or speculative helpers.
- Remove dead code when refactoring.
- Do not remove or rewrite existing TODO comments unless the user explicitly
asks, or unless the TODO is directly made obsolete by the code change.
- Prefer function declarations for top-level functions/components.
- Component props interfaces should be named `Props`.
- Do not destructure component props in function parameters; use `props.foo`.
Expand All @@ -81,21 +85,14 @@ This file is the source of working guidance for AI coding agents in this reposit
- Never use `window.confirm()`. Use `useConfirmDialog` from `@/components/ui`.
- Keep admin pages consistent: table controls, search/filtering, pagination, statistics, and bulk actions should follow existing admin patterns.

## Filters
## Filters And Selects

- Controllers own filter behavior: interactions, analytics, collapsed badges, active summaries, and calls into presentational content.
- Content components should only render fields and call handlers passed by controllers.
- URL/state hooks own URL sync and local UI state; they must not emit per-filter analytics.
- Filter analytics should be emitted once from controllers, using `filterAnalytics` and `selectedLabels`.
- Call `onChange` before emitting analytics.
- Use shared filter UI pieces: `FilterSidebarShell`, `CollapsedBadges`, `ActiveFiltersSummary`, and `MobileFilterSheet`.
- Use shared option mappers from `src/utils/options.ts`.

## Async Multi-Selects

- Use `src/components/ui/form/async-multi-select/AsyncMultiSelect.tsx` as the base.
- Entity wrappers such as CPU, GPU, Device, and SoC selects should stay thin: call TRPC, map to `Option[]`, manage pagination state, and pass data to the base component.
- Selected chips must persist by deriving them from `options` plus `selectedByIds`.
- Filter controllers own behavior and analytics: interaction handlers, collapsed badges, active summaries, and calls into presentational content.
- Filter content components should stay presentational. URL/state hooks own URL sync and local UI state, and must not emit per-filter analytics.
- Emit filter analytics once from controllers after calling `onChange`, using `filterAnalytics` and `selectedLabels`.
- Reuse shared filter primitives (`FilterSidebarShell`, `CollapsedBadges`, `ActiveFiltersSummary`, `MobileFilterSheet`) and option mappers from `src/utils/options.ts`.
- Async entity filters must wrap `src/components/ui/form/async-multi-select/AsyncMultiSelect.tsx`. CPU, GPU, Device, and SoC wrappers should only query, map options, manage pagination, and pass data to the base component.
- Selected async chips must derive from `options` plus `selectedByIds` so URL-loaded selections survive when their option is not on the current page.

## Security

Expand Down
Loading
Loading