Conversation
Co-authored-by: john20xdoe <14521605+john20xdoe@users.noreply.github.com>
Fix npm scripts by aligning project structure with Vite conventions
Co-authored-by: john20xdoe <14521605+john20xdoe@users.noreply.github.com>
Co-authored-by: john20xdoe <14521605+john20xdoe@users.noreply.github.com>
Co-authored-by: john20xdoe <14521605+john20xdoe@users.noreply.github.com>
Co-authored-by: john20xdoe <14521605+john20xdoe@users.noreply.github.com>
Update copyright to 2026 and serve JSON from deployed domain only
There was a problem hiding this comment.
Pull request overview
This PR migrates the site to a React + Vite setup (JSX entrypoint) and updates deployment/build configuration to publish the Vite dist/ output to GitHub Pages.
Changes:
- Introduces a Vite + React app entry (
src/main.jsx) and reimplements the page insrc/App.jsxwith runtime JSON fetching. - Adds build-time copying of root
data/*.jsonintodist/data/via a Vite plugin. - Adds a GitHub Pages deployment workflow and updates project metadata/ignores.
Reviewed changes
Copilot reviewed 9 out of 12 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.js | Adds Vite config + plugin to copy data/ JSON into dist/data/. |
| src/main.jsx | Adds React root bootstrap. |
| src/App.jsx | Implements the full page UI in React + fetches data/*.json. |
| index.html | Converts static HTML page into Vite root + module entry script. |
| package.json | Switches to Vite/React dependencies and build/dev scripts. |
| package-lock.json | Locks dependency tree for Vite/React toolchain. |
| deploy.yml | Adds GitHub Pages deployment workflow (currently misplaced). |
| robots.txt | Adds crawler rules + sitemap reference (currently not deployed by Vite as-is). |
| data/skills.json | Adds runtime skills data used by the app. |
| data/links.json | Adds runtime links data used by the app. |
| .gitignore | Adds dist and .DS_Store ignores. |
| .DS_Store | (Should not be committed) macOS metadata file added. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const dataDir = resolve(__dirname, "data"); | ||
| const distData = resolve(__dirname, "dist/data"); | ||
|
|
There was a problem hiding this comment.
vite.config.js is treated as an ES module (package.json sets "type": "module"), so __dirname is not defined and the build will crash when the copy plugin runs. Use an ESM-safe path resolution approach (e.g., derive a directory from import.meta.url / fileURLToPath, or use process.cwd() if appropriate) before calling resolve().
| name: Deploy to GitHub Pages | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
|
|
There was a problem hiding this comment.
This GitHub Actions workflow file won’t run from the repository root. GitHub only loads workflows from .github/workflows/*.yml. Move this file into .github/workflows/ (or adjust the PR to add it there) so the Pages deployment actually triggers on pushes to main.
| User-agent: Googlebot | ||
| Allow: / | ||
|
|
There was a problem hiding this comment.
robots.txt is added at the repo root, but Vite only copies static files from public/ into dist/ by default. Since the Pages artifact is dist, this robots.txt likely won’t be deployed. Move it under public/robots.txt (or configure publicDir / add a copy step) so it ends up in the deployed site root.
| return ( | ||
| <> | ||
| <style>{` | ||
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@200,400,600,700,800&family=Open+Sans:ital,wght@0,400;0,500;0,600;1,400;1,500&display=swap'); | ||
|
|
||
| *, *::before, *::after { box-sizing: border-box; } | ||
|
|
There was a problem hiding this comment.
The large CSS string is embedded inside the App component’s render output. Because App re-renders on state changes (e.g., accordion open/close), this will re-render/re-apply the <style> contents repeatedly and can cause unnecessary style recalculation. Consider moving these styles to a static CSS file (preferred with Vite) or at least hoisting the string outside the component so it isn’t recreated on every render.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 11 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| useEffect(() => { | ||
| const controller = new AbortController(); | ||
|
|
||
| setLoading(true); | ||
| fetch(url, { signal: controller.signal }) | ||
| .then((r) => { | ||
| if (!r.ok) throw new Error(`HTTP ${r.status}`); | ||
| return r.json(); |
There was a problem hiding this comment.
useFetch never resets error when a new request starts. If a previous request errors and a subsequent one succeeds (or url changes), the stale error value will remain set. Consider clearing error (and optionally data) when starting a new fetch (before calling fetch).
| // Safely renders label strings that contain inline <b> tags | ||
| function InlineHTML({ html }) { | ||
| return <span dangerouslySetInnerHTML={{ __html: html }} />; | ||
| } |
There was a problem hiding this comment.
InlineHTML uses dangerouslySetInnerHTML with content coming from JSON. Even if it's currently intended to only include <b>, this is still an XSS footgun if the JSON ever becomes user-controlled (or is modified unintentionally). Prefer representing emphasis as structured data (no HTML), or sanitize/whitelist allowed tags/attributes before rendering. Also, the comment says "Safely" but there is no sanitization here.
| return ( | ||
| <> | ||
| <style>{` | ||
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@200,400,600,700,800&family=Open+Sans:ital,wght@0,400;0,500;0,600;1,400;1,500&display=swap'); | ||
|
|
||
| *, *::before, *::after { box-sizing: border-box; } | ||
|
|
||
| body { | ||
| margin: 0; | ||
| width: 100%; | ||
| font-family: "Inter", "Open Sans", sans-serif; |
There was a problem hiding this comment.
Large CSS is inlined inside the component render via a template literal. This string is recreated on every re-render (e.g., when toggling accordions), and it makes styling harder to maintain. Consider moving these styles to a dedicated CSS file (and importing it), or at least hoisting the CSS string outside the component so it isn't reallocated each render.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@john20xdoe I've opened a new pull request, #10, to work on those changes. Once the pull request is ready, I'll request review from you. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
No description provided.