Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
3111af2
simple 'useClient' + updaated env var
Alessandro100 Jan 6, 2026
281edd0
more env var name change
Alessandro100 Jan 6, 2026
1c61928
nextjs configs + react update
Alessandro100 Jan 6, 2026
b7c961b
updated to MUI 7.3.6
Alessandro100 Jan 6, 2026
529c7c0
small adjustments
Alessandro100 Jan 6, 2026
b9a4098
footer styling
Alessandro100 Jan 6, 2026
478df83
updated components
Alessandro100 Jan 6, 2026
ef7b952
initial working code
Alessandro100 Jan 6, 2026
772a9d9
configs to deploy nextjs to cloud run
Alessandro100 Jan 7, 2026
c48c7d9
Map away from leaflet (not working)
Alessandro100 Jan 7, 2026
281a0a1
fetching datasets
Alessandro100 Jan 7, 2026
31c5c43
about page as SSR (not quite)
Alessandro100 Jan 7, 2026
9a0ae43
commenting out old code
Alessandro100 Jan 7, 2026
658bb0b
theme updates
Alessandro100 Jan 7, 2026
a62277f
about page ssr friendly (not done looking)
Alessandro100 Jan 7, 2026
2afb96f
updated files with new i18n settings
Alessandro100 Jan 8, 2026
6abc1ea
SSR i18n setup config
Alessandro100 Jan 8, 2026
bf4a0f8
firebase remote config -> to re-look at
Alessandro100 Jan 8, 2026
fdd85ef
associated feeds + structured data
Alessandro100 Jan 8, 2026
c37be9a
updated i18n keys for feedview
Alessandro100 Jan 8, 2026
a331988
updated styling of h1 consistent tag
Alessandro100 Jan 8, 2026
d41aeb6
feeds search page update to nextjs
Alessandro100 Jan 9, 2026
0cb996e
i18n fix
Alessandro100 Jan 9, 2026
57bf260
client access token on init fix
Alessandro100 Jan 9, 2026
b7a29a2
fixed account state
Alessandro100 Jan 9, 2026
75b9e2b
i18n keys common update
Alessandro100 Jan 9, 2026
8407ca0
fixed env usage
Alessandro100 Jan 9, 2026
7a31a1e
bug fixes
Alessandro100 Jan 9, 2026
93f9547
comments and package update
Alessandro100 Jan 12, 2026
cdf3802
feed detail page: routes data
Alessandro100 Jan 13, 2026
92af308
map fixes
Alessandro100 Jan 13, 2026
600969a
multiple datasets loading fix
Alessandro100 Jan 13, 2026
f64a051
feed detail page gtfs rt related feeds fix
Alessandro100 Jan 13, 2026
7352b81
feed detail page gbfs autodiscovery link fix
Alessandro100 Jan 13, 2026
2a38f7c
about page temp styling
Alessandro100 Jan 14, 2026
db361e4
reverted footer to client component to use theme
Alessandro100 Jan 14, 2026
ac3d599
updated readme
Alessandro100 Jan 14, 2026
5bda17d
feed view update and gbfs map
Alessandro100 Jan 14, 2026
5e3ded3
update start prod script
Alessandro100 Jan 15, 2026
e63f8e7
fixed footer displacement
Alessandro100 Jan 15, 2026
cd2703a
i18n keys fix
Alessandro100 Jan 15, 2026
d1e173c
updated eslint rules to nextjs relevant
Alessandro100 Jan 15, 2026
1c5ea2b
lint fixes
Alessandro100 Jan 15, 2026
06b138c
app loading state
Alessandro100 Jan 15, 2026
285cbcc
lint fixes
Alessandro100 Jan 15, 2026
4a1dd44
route hack: feeds/id for backwards compatible
Alessandro100 Jan 15, 2026
6e298b5
gitignore next type gen
Alessandro100 Jan 16, 2026
d68e5bd
documentation
Alessandro100 Jan 16, 2026
12c5c26
cleanup
Alessandro100 Jan 16, 2026
df7535e
map types and cleanup
Alessandro100 Jan 16, 2026
3bf37a9
extra font weights
Alessandro100 Jan 19, 2026
33fcc80
comments and documentation
Alessandro100 Jan 19, 2026
c402813
feeds/id clarification
Alessandro100 Jan 19, 2026
cd911c9
cleanup
Alessandro100 Jan 19, 2026
7a8cc2b
updated test setup
Alessandro100 Jan 19, 2026
c60ed28
fixed tests
Alessandro100 Jan 19, 2026
3fe5a98
cleanup
Alessandro100 Jan 19, 2026
7cdd2a1
e2e test fixes
Alessandro100 Jan 20, 2026
046e51f
e2e config for rsc
Alessandro100 Jan 20, 2026
8c814dc
cleanup
Alessandro100 Jan 20, 2026
a0c909c
lint fix
Alessandro100 Jan 20, 2026
5de645c
lint fixes
Alessandro100 Jan 20, 2026
1e8f257
lint fixes
Alessandro100 Jan 21, 2026
877f723
react types + removal of react-scripts
Alessandro100 Jan 21, 2026
56b4cad
nextjs optimized svg import
Alessandro100 Jan 21, 2026
1d1caa1
gbfs validator env variable fix
Alessandro100 Jan 21, 2026
0e69370
small cleanup
Alessandro100 Jan 21, 2026
c36feb4
removed docker files for cloud run
Alessandro100 Jan 21, 2026
ceacd70
updated gitignore
Alessandro100 Jan 21, 2026
f8be05d
lint fixes
Alessandro100 Jan 21, 2026
27dcf75
package update
Alessandro100 Jan 21, 2026
b4558f6
included Vercel analytics
Alessandro100 Jan 23, 2026
e6f84d4
package versioning + yarn.lock fix
Alessandro100 Jan 26, 2026
08fda1b
removed MUI 5 dependency
Alessandro100 Jan 26, 2026
45d492c
removal of mcp
Alessandro100 Jan 26, 2026
93c7926
type generation update for new repo
Alessandro100 Jan 26, 2026
1784e0a
tidying up next.config
Alessandro100 Jan 26, 2026
f1e117c
page cleanup
Alessandro100 Jan 26, 2026
518a25b
Added agent skill for copilot: vercel-react-best-practices
Alessandro100 Jan 26, 2026
542d449
feed detail page loading state
Alessandro100 Jan 26, 2026
32a8b6b
tidy up
Alessandro100 Jan 26, 2026
0947b28
detailed copilot instructions
Alessandro100 Jan 27, 2026
85bcaae
translation test
Alessandro100 Jan 27, 2026
cffcf31
documentation
Alessandro100 Jan 27, 2026
71ce965
lint fix
Alessandro100 Jan 27, 2026
64e1e40
more specific selection of admin app
Alessandro100 Jan 27, 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
2 changes: 0 additions & 2 deletions .eslintignore

This file was deleted.

69 changes: 37 additions & 32 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"standard-with-typescript",
"plugin:react/recommended",
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"plugin:prettier/recommended"
],
"parserOptions": {
"ecmaVersion": "latest"
},
"plugins": [
"react",
"@typescript-eslint",
"unused-imports",
"prettier"
],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"no-console": "warn",
"unused-imports/no-unused-imports": "error",
"react/react-in-jsx-scope": "off",
"prettier/prettier": "error",
"@typescript-eslint/ban-tslint-comment": "off",
"react/prop-types": "off",
"eqeqeq": "off"
"ignorePatterns": [
"dist/",
"build/",
"node_modules/",
".next/",
"coverage/",
"*.config.js"
],
"env": { "browser": true, "es2021": true },
"extends": [
"standard-with-typescript",
"plugin:react/recommended",
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"plugin:prettier/recommended"
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"project": "./tsconfig.json",
"ecmaFeatures": {
"jsx": true
}
},
"parser": "@typescript-eslint/parser",
"plugins": ["react", "@typescript-eslint", "unused-imports", "prettier"],
"settings": { "react": { "version": "detect" } },
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"unused-imports/no-unused-imports": "error",
"react/react-in-jsx-scope": "off",
"prettier/prettier": "error",
"@typescript-eslint/ban-tslint-comment": "off",
"react/prop-types": "off",
"eqeqeq": "off"
}
}
162 changes: 162 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Mobility Database Web - AI Agent Instructions

## Project Overview
Next.js 16 (App Router) web application for browsing and managing mobility transit feeds (GTFS, GTFS-RT, GBFS). Uses Firebase Auth, Redux Toolkit for state management, Material-UI (MUI), and TypeScript. Internationalized with next-intl (English/French).

## Architecture Patterns

### Hybrid Next.js Architecture (Migration in Progress)
- **Next.js App Router**: New pages in `src/app/` with Server Components by default ([layout.tsx](src/app/layout.tsx), [feeds/[feedDataType]/page.tsx](src/app/feeds/[feedDataType]/page.tsx))
- **Legacy React Router**: Still active via `<BrowserRouter>` in [App.tsx](src/app/App.tsx) - **will be deprecated**
- When adding features, prefer App Router patterns over React Router

### Client vs Server Components
- **Server Components** (default): Data fetching, API calls, Firebase Admin operations. No `'use client'` directive
- **Client Components**: Interactive UI with hooks, state, events. Mark with `'use client'` at top ([providers.tsx](src/app/providers.tsx), [Header.tsx](src/app/components/Header.tsx))
- **Rule**: Server actions and data fetching happen in server components or API services, client components handle interactivity

### API Integration via OpenAPI-Fetch
- Type-safe API client generated from OpenAPI specs in `external_types/`
- Main client: [src/app/services/feeds/index.ts](src/app/services/feeds/index.ts) - uses `openapi-fetch` with auto-typed paths
- Generate types: `yarn generate:api-types` (DatabaseCatalogAPI) or `yarn generate:gbfs-validator-types`
- Always use generated types from `services/feeds/types.ts` - never duplicate API response types
- Auth via Bearer token middleware: `generateAuthMiddlewareWithToken(accessToken)`

### Firebase Authentication Patterns
- **Client-side**: Firebase compat SDK ([firebase.ts](src/firebase.ts)) with emulator support for Cypress
- **Server-side**: Firebase Admin SDK ([firebase-admin.ts](src/lib/firebase-admin.ts)) for token verification
- Auth state managed via Redux ([profile-reducer.ts](src/app/store/profile-reducer.ts)) with status: `authenticated|unauthenticated|anonymous_login|...`
- Access tokens: `getSSRAccessToken()` for server, Redux state for client
- Cypress tests auto-use Firebase emulator on port 9099

### Internationalization (i18n)
- Next-intl with messages in `messages/{en,fr}.json`
- Use `useTranslations('namespace')` in client components: `const t = useTranslations('feeds')`
- Server components: import from `next-intl/server` - `getLocale()`, `getMessages()`
- Locale from subdomain: `fr.mobilitydatabase.org` → French, else English ([config.ts](src/i18n/config.ts))

### State Management
- **Redux Toolkit**: Global state for auth, profile ([store/profile-reducer.ts](src/app/store/profile-reducer.ts))
- **React Context**: Theme, Remote Config ([providers.tsx](src/app/providers.tsx))
- **Server-side**: React `cache()` for per-request memoization ([remote-config.server.ts](src/lib/remote-config.server.ts))

### Firebase Remote Config
- Server-side fetch cached for 5 min (dev) / 1 hour (prod) in [remote-config.server.ts](src/lib/remote-config.server.ts)
- Passed from server → client via `<Providers remoteConfig={...}>` in [layout.tsx](src/app/layout.tsx)
- Default values in `src/app/interface/RemoteConfig.ts`

## Key Conventions

### Material-UI (MUI) Usage
- Use direct imports: `import { Box, Typography } from '@mui/material'` (NOT barrel file `@mui/material/*`)
- Theme via Emotion + `ThemeRegistry` in [registry.tsx](src/app/registry.tsx)
- Fonts loaded via next/font: Mulish (body), IBM Plex Mono (mono) defined in [layout.tsx](src/app/layout.tsx)

### File Organization
- **Screens**: `src/app/screens/{ScreenName}/` - page-level components
- **Components**: `src/app/components/` - shared UI components
- **Services**: `src/app/services/` - API clients and external integrations
- **Utils**: `src/app/utils/` - helper functions (config, auth, formatting)
- **Functions files**: Logic separated into `*.functions.tsx` ([Feed.functions.tsx](src/app/screens/Feed/Feed.functions.tsx))

### Testing Strategy
- **Unit Tests**: Jest + React Testing Library (files: `*.spec.tsx` or `*.test.tsx`)
- **E2E Tests**: Cypress in `cypress/e2e/` with MSW mocks in [src/mocks/handlers.ts](src/mocks/handlers.ts)
- Run E2E: `yarn e2e:setup` (starts dev + Firebase emulator + MSW), then `yarn e2e:run` or `yarn e2e:open`
- Mock API responses using fixtures from `cypress/fixtures/`

### Environment Variables
- Prefix with `NEXT_PUBLIC_` for client-side access
- Dev env: `.env.development`, prod: `.env`, CI: `.env.test`
- Key vars: `NEXT_PUBLIC_FEED_API_BASE_URL`, `NEXT_PUBLIC_FIREBASE_*`, `NEXT_PUBLIC_API_MOCKING`
- Mock mode: `NEXT_PUBLIC_API_MOCKING=enabled yarn start:dev:mock` (port 3001)

## Development Workflows

### Starting Development
```bash
yarn install # Prefer yarn over npm
yarn start:dev # Dev server on :3000 with hot reload
yarn start:dev:mock # Dev server with MSW mocks on :3001
```

### Testing Commands
```bash
yarn test # Unit tests
yarn test:watch # Watch mode
yarn e2e:setup # Start dev + Firebase emulator for E2E
yarn e2e:open # Cypress interactive mode
```

### Building & Deploying
```bash
yarn build:prod # Production build (standalone output)
yarn start:prod # Build + start locally
yarn lint # ESLint check
yarn lint:fix # Auto-fix linting issues
```

### Regenerating API Types
```bash
yarn generate:api-types # DatabaseCatalogAPI → types.ts
yarn generate:gbfs-validator-types # GbfsValidator → gbfs-validator-types.ts
```
Run after updating OpenAPI specs in `external_types/`

## Common Patterns

### Data Fetching in Server Components
```tsx
// pages fetch data directly with access token
export default async function FeedPage({ params }) {
const accessToken = await getSSRAccessToken();
const feed = await getFeed(feedId, accessToken);
return <FeedDetails feed={feed} />;
}
```

### Parallel Data Loading
Use `Promise.all` in server components ([layout.tsx](src/app/layout.tsx)):
```tsx
const [locale, messages, remoteConfig] = await Promise.all([
getLocale(), getMessages(), getRemoteConfigValues()
]);
```

### Client Component with Translations
```tsx
'use client';
import { useTranslations } from 'next-intl';

export function MyComponent() {
const t = useTranslations('feeds'); // namespace from messages/
return <div>{t('labelKey')}</div>;
}
```

### Conditional Rendering for Auth
Redux state for auth checks in client components, check `status` from profile reducer.

## Critical Notes

- **Route hack**: `/feeds/[feedDataType]` actually receives `feedId` for backward compatibility ([page.tsx](src/app/feeds/[feedDataType]/page.tsx)) - redirects to proper route
- **TypeScript strict mode enabled**: Handle nullish values explicitly
- **Cypress uses Firebase emulator**: Tests run against auth emulator, not production Firebase
- **Server-only code**: Mark with `import 'server-only'` for server utils ([remote-config.server.ts](src/lib/remote-config.server.ts))
- **Jest transform exceptions**: Some node_modules need manual transformation - see `transformIgnorePatterns` in [jest.config.ts](jest.config.ts)

## Resources
- Node v24.12.0 (npm v11.6.2, yarn v1.22.22)
- [Next.js App Router docs](https://nextjs.org/docs/app)
- [next-intl docs](https://next-intl-docs.vercel.app/)
- [openapi-fetch](https://openapi-ts.dev/openapi-fetch/)


Always load and apply the following project agent skills when reviewing or generating code:

- vercel-react-best-practices (from .github/skills/vercel-react-best-practices)

If the skill is available, prefer its guidance over generic Copilot heuristics.
If it is not available, emulate its rules as closely as possible.

Acknowledge when the skill is applied.
Loading