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
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
pull_request:
push:
branches:
- main
- master

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

jobs:
quality-gate:
name: Typecheck, Test, Build
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: yarn

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Typecheck
run: npx tsc --noEmit

- name: Test
run: CI=true yarn test --watchAll=false

- name: Build
run: yarn build
23 changes: 23 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Release

on:
push:
tags:
- '*'
- '**'
workflow_dispatch:

permissions:
contents: write

jobs:
publish-release:
name: Publish GitHub Release
runs-on: ubuntu-latest

steps:
- name: Publish release for pushed tag
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
generate_release_notes: true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.log

#environment variables
.env
39 changes: 39 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Repository Guidelines

## Project Structure & Module Organization
- `src/components/`: UI modules grouped by feature (`App`, `Gallery`, `Layout`, `Login`, shared `Common`).
- `src/state/`: Redux store setup, action types/creators, and reducers.
- `src/api/`: client calls for images/users APIs.
- `src/utils/` and `src/utillity/`: helpers (logging, idle timer, UUID helpers).
- `public/`: static assets used by CRA.
- `src/assets/`: bundled fonts and CSS icon assets.
- Tests currently live beside components (example: `src/components/App/App.test.tsx`).

## Build, Test, and Development Commands
- `yarn start`: run the app locally on `http://localhost:3000`.
- `yarn build`: generate the production bundle in `build/`.
- `yarn test`: run Jest + React Testing Library in watch mode.
- `npm run <script>` is equivalent, but this repo is Yarn-first (`yarn.lock` is committed).

## Coding Style & Naming Conventions
- Language: TypeScript + React functional components.
- Use PascalCase for components/files (`UploadImage.tsx`), camelCase for functions/variables, and UPPER_SNAKE_CASE for constants (`MAX_UPLOAD_BYTES`).
- Keep feature entrypoints as `index.tsx` re-export files.
- Follow existing formatting in touched files (many `.tsx` files use tabs; keep changes consistent with local style).
- Linting is provided by CRA ESLint config (`react-app`, `react-app/jest`) and enforced during normal `react-scripts` workflows.

## Testing Guidelines
- Frameworks: Jest + React Testing Library (`src/setupTests.ts`).
- Name tests `*.test.tsx` next to the component under test.
- Prefer user-focused assertions (`screen.getBy...`) over implementation details.
- Add or adjust tests for behavior changes in routing, gallery state, and upload flows.

## Commit & Pull Request Guidelines
- Prefer Conventional Commit prefixes used in history: `feat:`, `fix:` (example: `feat: improve modal image loading`).
- Keep commits scoped and atomic; include issue/PR references when relevant (for example `(#26)`).
- PRs should include a concise behavior summary, test evidence (`yarn test` plus manual UI checks), and screenshots/video for UI changes.
- Link issues when available and call out backend/API contract impacts explicitly.

## Security & Configuration Tips
- Keep secrets in `.env`; never hardcode Firebase/API credentials.
- Required env vars are `REACT_APP_*` keys consumed in `src/firebase.configuration.ts` and `src/config.ts`.
109 changes: 109 additions & 0 deletions CODEBASE_ANALYSIS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Photogram Codebase Analysis

## Scope and method
This review covers the frontend repository under `src/` (React + Redux + Firebase) plus build/test health checks.

Commands executed:
- `CI=true yarn test --watchAll=false` (failed)
- `yarn build` (succeeded with warnings)
- `npx tsc --noEmit` (passed)

## Executive summary
The project has a clear feature-oriented structure and a working core flow (auth, gallery listing, upload, archive/privacy toggles). Recent UX work in upload and modal components is solid.

Main technical debt is concentrated in runtime coupling, testability, and operational consistency:
- Firebase is initialized at module load with browser-only persistence, which breaks tests.
- Error handling is mostly console-based and not surfaced in app state/UI.
- A few flows can produce inconsistent data states (notably delete).
- Toolchain/dependency age and mixed package-manager artifacts increase maintenance risk.

## Architecture summary
- Entry and composition: `src/index.tsx`, `src/components/App/App.tsx`.
- Auth lifecycle: `src/components/App/AppInitializer.tsx` and `src/firebase.configuration.ts`.
- State: Redux with thunk actions in `src/state/actionCreators/index.tsx`, reducers in `src/state/reducers/`.
- Data access: Firebase/HTTP operations in `src/api/images.ts` and `src/api/users.ts`.
- UI features: gallery in `src/components/Gallery/`, auth in `src/components/Login/`, layout in `src/components/Layout/`.

## Strengths
- Feature grouping is intuitive and easy to navigate.
- Upload UX includes validation, progress, stage messaging, and reset (`src/components/Gallery/UploadImage/UploadImage.tsx`).
- TypeScript strict mode is enabled (`tsconfig.json`), and `npx tsc --noEmit` currently passes.
- Build succeeds and outputs optimized assets.

## Findings and technical debt

### High priority
1. Test suite is currently broken by Firebase persistence setup.
- Evidence: `src/firebase.configuration.ts:28` sets `Auth.Persistence.LOCAL` at import time.
- Impact: Jest/jsdom cannot support that persistence type; `yarn test` fails before running tests.
- Result seen: `auth/unsupported-persistence-type` and `0 tests` executed.

2. Test coverage is effectively absent and currently stale.
- Evidence: only one test file, `src/components/App/App.test.tsx`, still checks for “learn react” text that no longer exists.
- Impact: no safety net for core flows (auth redirect, gallery loading, upload state, reducers).

3. Delete flow is not atomic and can orphan storage objects.
- Evidence: `src/api/images.ts:148` deletes Firestore first, then calls backend delete at `src/api/images.ts:152`.
- Impact: if backend delete fails, metadata is gone while file may remain in storage; recovery is manual.

### Medium priority
1. Error handling and observability are fragmented.
- Evidence: widespread `console.error` in action creators/components (`src/state/actionCreators/index.tsx:20`, `src/components/Gallery/ShowGallery/ShowGallery.tsx:39`, `src/components/Login/Login.tsx:36`).
- Impact: errors are hard to track, not normalized, and mostly invisible to users.

2. Redux action model includes error action but no error state.
- Evidence: `LOAD_IMAGES_ERROR` exists (`src/state/actionTypes/index.ts`) but reducers mostly keep old state and discard error payload (`src/state/reducers/imagesReducer.ts:14`).
- Impact: UI cannot reliably show request failures.

3. Type safety is diluted in key integration points.
- Evidence: `useDispatch<any>` in `src/components/App/AppInitializer.tsx:8`, `getState: () => any` in `src/state/actionCreators/index.tsx:9`, `Promise<any>` and `(uploadDateRaw as any)` in `src/api/images.ts:96` and `src/api/images.ts:27`.
- Impact: regressions can slip through despite strict TS config.

4. Unused/dead code paths exist.
- Evidence: `DeleteImage` component is exported but not used in gallery rendering (`src/components/Gallery/DeleteImage/DeleteImage.tsx`; no usages in `ShowGallery`).
- Evidence: legacy `src/utillity/` module appears unused and duplicates idle-timer concern.
- Impact: cognitive overhead and drift.

5. Route access control is UI-level only.
- Evidence: `/upload` route is always registered (`src/components/App/App.tsx:23`), with guard only inside component.
- Impact: users can access protected routes and then be told they cannot proceed; better handled with route guards.

### Low priority
1. Modal and accessibility ergonomics can improve.
- Evidence: `Modal.setAppElement('#root')` is called on every render in `src/components/App/App.tsx:11`.
- Evidence: close icon in `CoreModal` is an `<i>` click target, not a button (`src/components/Common/CoreModal/CoreModal.tsx:44`).
- Impact: minor performance/accessibility debt.

2. Toolchain age and compatibility workarounds increase risk.
- Evidence: scripts require `NODE_OPTIONS=--openssl-legacy-provider` in `package.json`.
- Evidence: old dependency stack (CRA 5, React 17, Firebase v7) and build warnings around sourcemaps.
- Impact: slower upgrades, more ecosystem friction over time.

3. Documentation drift and repo hygiene issues.
- Evidence: `README.md` includes conversational preface and references a `backend` folder not present in this repo (`README.md:1`, `README.md:72`, `README.md:131`).
- Evidence: both `yarn.lock` and `package-lock.json` are committed, increasing install nondeterminism.

## Recommended improvement plan

### Phase 1 (stability, 1-2 days)
- Move auth persistence setup behind environment-aware bootstrap (or mock Firebase in tests).
- Replace `App.test.tsx` with meaningful tests and add baseline reducer/API mocking tests.
- Standardize one package manager (Yarn or npm) and remove the other lockfile.

### Phase 2 (correctness, 2-4 days)
- Refactor delete flow to backend-first or compensating transaction strategy.
- Introduce request status + error slices in Redux for gallery/upload/auth flows.
- Replace `any` with typed thunk helpers and typed API response models.

### Phase 3 (maintainability, 3-5 days)
- Add route guards for authenticated-only pages.
- Remove/merge unused modules (`src/utillity`, unused exports).
- Modernize docs and define a minimal CI gate (`tsc`, tests, build).

## Suggested quality gate
Add CI checks so regressions are caught early:
- `npx tsc --noEmit`
- `CI=true yarn test --watchAll=false`
- `yarn build`

At the moment, the gate would fail on tests until Firebase initialization is made test-safe.
83 changes: 83 additions & 0 deletions MODERNIZATION_RFC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Modernization RFC (TD-011)

## Objective
Reduce platform risk and maintenance drag by modernizing the frontend stack while preserving behavior and release velocity.

## Current Baseline
- React 17 + `react-dom` 17
- CRA (`react-scripts` 5)
- Firebase v7 namespaced SDK
- Redux + `redux-thunk`
- TypeScript 4.1
- Runtime workaround: `NODE_OPTIONS=--openssl-legacy-provider`

## Why Modernize
- Security and ecosystem drift (older transitive dependencies and tooling warnings)
- Increased compatibility friction on current Node/toolchains
- Slower onboarding and CI reliability due to legacy stack constraints

## Options Evaluated
1. Keep current stack and patch only
- Pros: low immediate effort
- Cons: debt compounds; compatibility risk increases

2. Incremental modernization in place (recommended)
- Pros: controlled risk, easier rollback, minimal product disruption
- Cons: requires multiple phases and temporary dual patterns

3. Big-bang migration (framework/tooling + runtime in one move)
- Pros: fastest end-state
- Cons: highest risk, larger freeze window, harder debugging

## Recommended Path (Option 2)
### Phase A: Foundation hardening
- Target: Node LTS current, TypeScript 5.x, dependency cleanup
- Remove `openssl-legacy-provider` dependency in scripts
- Keep CRA initially to limit blast radius

### Phase B: Runtime and library upgrades
- React 18 migration (`createRoot`, strict compatibility checks)
- Firebase move from namespaced v7 API to modular API (`firebase/app`, auth/firestore modular imports)
- Validate auth persistence, upload/delete flows, gallery queries

### Phase C: Tooling migration
- Replace CRA with Vite (or equivalent modern bundler)
- Port env conventions, test runner integration, and build output settings
- Keep route/auth behavior and API contracts unchanged

### Phase D: Stabilization and cleanup
- Remove dead shims/polyfills and obsolete dependencies
- Tighten CI gates and dependency update policy
- Document operational runbooks and rollback steps

## Risk Matrix
- High: Firebase modular migration touches auth/firestore APIs across app
- Medium: React 18 behavior differences under Strict Mode
- Medium: CRA -> Vite config parity (env vars, assets, tests)
- Low: TypeScript and lint/tooling upgrades

## Dependency/Compatibility Blockers
- Firebase query and auth API rewrite scope
- Test harness updates for router + modal + auth initialization
- Build pipeline parity in deployment environment

## Success Criteria
- CI green for typecheck, tests, and production build
- No `openssl-legacy-provider` requirement
- No regressions in login, gallery load, upload, archive/private toggle, delete
- Documented upgrade path for future dependency updates

## Estimated Effort
- Phase A: 1-2 days
- Phase B: 3-5 days
- Phase C: 2-4 days
- Phase D: 1-2 days
- Total: ~7-13 engineering days

## Go/No-Go Recommendation
Go, with phased incremental execution.

Rationale:
- Current stack is functional but increasingly costly to maintain.
- Incremental delivery keeps risk manageable and preserves product momentum.
- Existing CI/test gates now provide enough safety to execute upgrades in slices.
Loading