Skip to content

feat: Phase 1 - Scaffold React + TypeScript + Vite project (Angular-to-React migration)#196

Open
devin-ai-integration[bot] wants to merge 2 commits intomasterfrom
devin/1772639290-react-migration-phase1
Open

feat: Phase 1 - Scaffold React + TypeScript + Vite project (Angular-to-React migration)#196
devin-ai-integration[bot] wants to merge 2 commits intomasterfrom
devin/1772639290-react-migration-phase1

Conversation

@devin-ai-integration
Copy link

@devin-ai-integration devin-ai-integration bot commented Mar 4, 2026

Summary

Phase 1 of the Angular-to-React migration for the Hacker News PWA. This PR replaces the Angular build toolchain with a Vite-based React + TypeScript setup while preserving the existing Angular source code (src/app/) as reference for subsequent migration phases.

Key changes:

  • Build tooling: Replaced Angular CLI with Vite + @vitejs/plugin-react + vite-plugin-pwa
  • Dependencies: Swapped all @angular/*, rxjs, zone.js, unfetch packages for react, react-dom, react-router-dom
  • TypeScript config: New tsconfig.json targeting react-jsx, with src/app excluded to avoid Angular type errors
  • Entry points: New index.html (repo root), src/main.tsx, src/App.tsx (placeholder)
  • Directory scaffolding: Empty src/{components,pages,hooks,context,models,utils}/ with .gitkeep files
  • SCSS: Copied theme files from src/app/shared/scss/src/styles/, created global.scss with combined global styles
  • Static assets: Copied src/assets/ and src/favicon.icopublic/ for Vite static serving
  • PWA manifest: Single source of truth via vite-plugin-pwa config (no static manifest.webmanifest or hardcoded <link> tag)
  • Removed: angular.json, karma.conf.js, e2e/, browserslist, tslint.json, ngsw-config.json, tsconfig.app.json, tsconfig.spec.json, yarn.lock
  • Package manager: Switched from Yarn (yarn.lock) to npm (package-lock.json)

Screenshot of running app:

React placeholder app running locally

Updates since last revision

  • Fixed duplicate manifest sources: Removed hardcoded <link rel="manifest"> from index.html (vite-plugin-pwa injects it automatically), deleted public/manifest.webmanifest (vite-plugin-pwa generates it from config), and aligned short_name to "Angular 2 HN" in vite.config.ts to match the original.

Review & Testing Checklist for Human

  • Confirm TypeScript exclusions don't bite latertsconfig.json excludes src/app, src/main.ts, src/test.ts, src/polyfills.ts, src/environments. Verify that new React files added in future phases (e.g. src/pages/Home.tsx) are not caught by these exclusions.
  • Verify SCSS themes render correctly — The SCSS files use deprecated @import syntax and darken() (produces build warnings). Check that themes still work visually and don't break with future Sass updates.
  • Check PWA manifest in production build — Run npm run build and inspect dist/manifest.webmanifest to verify vite-plugin-pwa generates the correct manifest values (name, icons, theme color).
  • Verify old Angular code is preserved — Confirm src/app/ directory is intentionally kept as reference for later phases (excluded from TypeScript but not deleted).

Test Plan

# Install dependencies
npm install

# Type check
npx tsc --noEmit

# Dev server
npm run dev
# → Visit http://localhost:5173 and verify "Hacker News" placeholder renders

# Production build
npm run build
npm run preview
# → Verify build succeeds, inspect dist/manifest.webmanifest, and preview works

Notes

  • The old src/app/ Angular code is intentionally preserved as reference for future migration phases.
  • Static assets are duplicated (src/assets/ + public/assets/) because the old src/ tree is kept intact.
  • SCSS deprecation warnings (Sass @import, / division, darken()) are carried over from the original Angular project. These are non-blocking but should be addressed in a future cleanup PR.
  • Package manager switched from Yarn to npm (reflected in lockfile change).
  • The App.tsx is a minimal placeholder; actual component migration happens in subsequent phases.

Link to Devin Session: https://app.devin.ai/sessions/4cdbb2606f7748dc8a756278bf761179
Requested by: @piyushpuri96


Open with Devin

- Replace Angular dependencies with React (react, react-dom, react-router-dom)
- Add Vite build tooling with @vitejs/plugin-react and vite-plugin-pwa
- Create React-compatible tsconfig.json with jsx: react-jsx
- Add Vite entry point (index.html) with GA snippet and PWA meta tags
- Create src/main.tsx and src/App.tsx placeholder components
- Set up directory structure: components, pages, hooks, context, models, utils, styles
- Copy SCSS theme files (_themes, _theme_variables, _media) to src/styles/
- Create global.scss with imported themes and global styles
- Copy static assets to public/ directory for Vite serving
- Remove Angular-specific configs: angular.json, karma.conf.js, e2e/, etc.
- Keep src/app/ as reference for subsequent migration phases

Co-Authored-By: piyush@cognition.ai <piyush.b.puri@gmail.com>
@devin-ai-integration
Copy link
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review

index.html Outdated
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">

<link rel="manifest" href="/manifest.webmanifest">
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Duplicate manifest link tag and conflicting manifest sources from VitePWA + static file + hardcoded HTML link

The index.html has a hardcoded <link rel="manifest" href="https://github.com/manifest.webmanifest"> at line 35, while vite-plugin-pwa is configured with a manifest object in vite.config.ts:10-39 which causes it to also generate a manifest.webmanifest file and inject its own <link rel="manifest"> tag into the HTML during build. On top of that, there is a static public/manifest.webmanifest that Vite copies into dist/ verbatim.

Root Cause and Impact

Three conflicting manifest sources exist:

  1. Hardcoded link in index.html:35: <link rel="manifest" href="https://github.com/manifest.webmanifest">
  2. VitePWA plugin in vite.config.ts:10-39: generates a manifest file and injects its own <link> tag
  3. Static file at public/manifest.webmanifest: copied by Vite to dist/manifest.webmanifest

The values also conflict — the static public/manifest.webmanifest has "short_name": "Angular 2 HN" while the VitePWA config has short_name: 'Hacker News'.

During production build, the output HTML will contain two <link rel="manifest"> tags (the hardcoded one plus the injected one), and the generated manifest file may collide with the static copy from public/. The result is unpredictable PWA install behavior and manifest metadata.

Fix: Remove either the hardcoded <link> from index.html (since VitePWA injects it) or the manifest config from vite.config.ts. Also remove or reconcile public/manifest.webmanifest to avoid file-level conflicts.

Prompt for agents
There are three conflicting manifest sources that need to be reconciled:

1. index.html line 35 has a hardcoded <link rel="manifest" href="https://github.com/manifest.webmanifest">.
2. vite.config.ts lines 10-39 configure vite-plugin-pwa with a manifest object, which causes the plugin to both generate a manifest.webmanifest file AND inject its own <link rel="manifest"> tag into the HTML.
3. public/manifest.webmanifest is a static file that Vite copies to dist/ as-is.

The short_name values also conflict: public/manifest.webmanifest has "Angular 2 HN" while vite.config.ts has "Hacker News".

To fix:
- Remove the hardcoded <link rel="manifest" href="https://github.com/manifest.webmanifest"> from index.html line 35, since vite-plugin-pwa injects it automatically.
- Delete public/manifest.webmanifest since vite-plugin-pwa generates the manifest from the config in vite.config.ts.
- Alternatively, if you want to use the static manifest only, remove the manifest property from the VitePWA config in vite.config.ts and keep the static file and HTML link.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Fixed in 8ff3878:

  • Removed the hardcoded <link rel="manifest"> from index.html (vite-plugin-pwa injects it automatically)
  • Deleted public/manifest.webmanifest (vite-plugin-pwa generates it from the config)
  • Aligned short_name to "Angular 2 HN" in vite.config.ts to match the original manifest

- Remove hardcoded <link rel='manifest'> from index.html (vite-plugin-pwa injects it)
- Delete public/manifest.webmanifest (vite-plugin-pwa generates it from config)
- Align short_name to 'Angular 2 HN' in vite.config.ts to match original

Co-Authored-By: piyush@cognition.ai <piyush.b.puri@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants