Skip to content
Open
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
12 changes: 6 additions & 6 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import './globals.css'
import 'katex/dist/katex.min.css';
import { cn } from '@/lib/utils'
import { ThemeProvider } from '@/components/theme-provider'
import Header from '@/components/header'
import Footer from '@/components/footer'
import { Sidebar } from '@/components/sidebar'
// import Header from '@/components/header'
// import Footer from '@/components/footer'
// import { Sidebar } from '@/components/sidebar'
Comment on lines +7 to +9
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove the commented-out layout branches.

These placeholders are dead code now and will drift from the real layout. Deleting them is cleaner than keeping commented imports/render sites around.

Also applies to: 112-116

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/layout.tsx` around lines 7 - 9, Remove the dead commented-out layout
branches in app/layout.tsx by deleting the unused commented import lines
referencing Header, Footer, and Sidebar and any corresponding commented render
sites (including the block noted around lines 112-116); ensure no other code
relies on those commented placeholders and keep the active layout imports/JSX
only so the file contains only actual imports and render logic.

import { Analytics } from "@vercel/analytics/next"
import { SpeedInsights } from "@vercel/speed-insights/next"
import { Toaster } from '@/components/ui/sonner'
Expand Down Expand Up @@ -109,11 +109,11 @@ export default function RootLayout({
>
<MapContextProvider>
<MapLoadingProvider>
<Header />
{/* <Header /> */}
<ConditionalLottie />
{children}
<HistorySidebar />
<Footer />
{/* <HistorySidebar /> */}
{/* <Footer /> */}
<Toaster />
</MapLoadingProvider>
</MapContextProvider>
Expand Down
15 changes: 4 additions & 11 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import { Chat } from '@/components/chat'
import { nanoid } from '@/lib/utils'
import { AI } from './actions'
import { JSpaceUI } from '@/components/j-space-ui'

export const maxDuration = 60

import { MapDataProvider } from '@/components/map/map-data-context'

export default function Page() {
const id = nanoid()
return (
<AI initialAIState={{ chatId: id, messages: [] }}>
<MapDataProvider>
<Chat id={id} />
</MapDataProvider>
</AI>
<main>
<JSpaceUI />
Comment on lines +7 to +8
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This replaces the QCX entry point instead of integrating with it.

Page now mounts only JSpaceUI, and that component is fed by hard-coded portfolio data from components/j-space-content.ts. The existing QCX dashboard surface is no longer reachable from /, so this is a functional swap, not just a visual redesign.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/page.tsx` around lines 7 - 8, The Page component currently mounts only
JSpaceUI (which uses hard-coded data from components/j-space-content.ts),
replacing the QCX dashboard entrypoint; revert this functional swap by restoring
the original QCX entrypoint and integrating JSpaceUI into it instead of
replacing it: update the Page render to include the original QCX root/component
(restore whatever component you removed) and either embed JSpaceUI within the
QCX layout or feed JSpaceUI its data via the QCX data pipeline (avoid hard-coded
portfolio data), referencing the Page component and the JSpaceUI component plus
components/j-space-content.ts so you can locate and merge the UI while keeping
the QCX dashboard reachable at "/".

</main>
)
}
7 changes: 7 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions components/j-space-content.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
export const content = {
aboutMe: {
name: "Jeremy Liu",
title: "Computer Engineer Undergrad @ UofT",
bio: "I am dedicated to inspiring people and creating positive spaces around the world.",
currentActivities: [
"Building personal tools & student projects",
"Expanding my knowledge in object-oriented programming",
"Learning full-stack web dev",
"Exploring robotics and AI",
],
},
skills: {
programmingLanguages: "Python, C, JavaScript, TypeScript, MATLAB, SQL",
webUI: "React, Next.js, HTML, CSS, Bootstrap, Tailwind, Vite",
roboticsSystems: "ROS2, Linux (Ubuntu), Arduino, OpenCV",
dataML: "Pytorch, Scikit-learn, Matplotlib, Pandas, NumPy, OpenCV, BeautifulSoup, Selenium",
developerTools: "Git, Node.js, AWS, PostgreSQL, Postman, VS Code, Claude, Cursor.ai",
},
projects: [
{
title: "Sinatra",
description: "A DAW that turns your voice into any instrument of your choice.",
image: "sinatra",
github: "https://github.com/e-yang6/sinatra",
website: "https://sinatra-daw.vercel.app/",
},
{
title: "LockBlock",
description: "A smart security system using Arduino and computer vision to block deadbolts when unknown faces are detected.",
image: "lockblock",
github: "https://github.com/Jeremyliu-621/lockblock",
},
{
title: "UFC Index website",
description: "A website that shows scraped stats for UFC Fighters.",
image: "ufc-search",
github: "https://github.com/Jeremyliu-621/UFC-Elo-Calculator",
website: "https://ufc-elo-calculator.vercel.app/",
},
{
title: "Binder",
description: "A swipe-based interface for thrifting.",
image: "binder_action",
github: "https://github.com/Jeremyliu-621/binder",
},
{
title: "stop! don't go on.",
description: "Water Sprayer that stops bad habits.",
image: "stop_dont_go_on_grey",
website: "https://stop-dont-go-on.vercel.app/",
github: "https://github.com/Jeremyliu-621/stop-dont-go-on",
},
{
title: "j-space",
description: "A space that focuses on my creativity and ideas.",
image: "j-gif-space",
website: "https://j-space.vercel.app/",
github: "https://github.com/Jeremyliu-621/j-space",
},
],
};
146 changes: 146 additions & 0 deletions components/j-space-ui.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
'use client'

import React, { useEffect, useState } from 'react'
import '98.css'
import { content } from './j-space-content'

export function JSpaceUI() {
const [isLoaded, setIsLoaded] = useState(false)

useEffect(() => {
// Import 98-components only on the client side
import('98-components').then(() => {
setIsLoaded(true)
})
}, [])

if (!isLoaded) return null
Comment on lines +10 to +17
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't blank the page while the client-only import resolves.

isLoaded starts as false, so the initial render is null, and / stays blank forever if the 98-components import rejects. Render the markup immediately and treat the import as enhancement, or show an explicit loading/error fallback.

Possible direction
-  const [isLoaded, setIsLoaded] = useState(false)
-
   useEffect(() => {
-    // Import 98-components only on the client side
-    import('98-components').then(() => {
-      setIsLoaded(true)
-    })
+    void import('98-components').catch((error) => {
+      console.error('Failed to load 98-components', error)
+    })
   }, [])
-
-  if (!isLoaded) return null
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/j-space-ui.tsx` around lines 10 - 17, The component currently
returns null until isLoaded becomes true, which blanks the page if
import('98-components') rejects; change the pattern so the component renders its
normal markup immediately and treats the dynamic import as an enhancement: keep
the initial render from useEffect and setIsLoaded via
import('98-components').then(() => setIsLoaded(true)).catch(err => {
setIsLoaded(true); setImportError(err); }) or set a separate error flag so you
can show a non-blocking error UI while still rendering the main markup; update
any code around useEffect, isLoaded, and setIsLoaded to remove the early "if
(!isLoaded) return null" and instead conditionally enable features that depend
on the loaded module (e.g., only render 98-components-specific parts when
isLoaded is true).


const getImageUrl = (filename: string) => {
return `/j-space/assets/${filename}`
}

return (
<div className="j-space-container" style={{
fontFamily: '"Jersey 10", sans-serif',
backgroundColor: '#c0c0c0',
width: '100vw',
height: '100vh',
overflow: 'hidden',
position: 'relative'
}}>
Comment on lines +24 to +31
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

The window layout is not usable on small viewports.

All three panes use fixed vw/vh sizes and absolute positioning inside a container that hides overflow. On phone-sized screens the columns collapse/overlap and clipped content cannot be reached. Add a mobile breakpoint that stacks the windows and allows scrolling.

Also applies to: 36-94

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/j-space-ui.tsx` around lines 24 - 31, The layout in the
j-space-container uses fixed vw/vh and absolute positioning which breaks on
small viewports; update the styles in components/j-space-ui.tsx so that
.j-space-container becomes a responsive flex container with a mobile breakpoint
(e.g., `@media` max-width: 768px) that switches to flex-direction: column, removes
overflow: hidden (or sets overflow: auto) and converts the three pane elements
(the child elements currently using fixed width/height and absolute positioning)
to percent or auto heights with min-height and full-width so they stack and can
scroll; locate the styles applied to "j-space-container" and the three pane
elements (the blocks referenced in the diff and lines 36-94) and replace fixed
vw/vh/absolute positioning with responsive rules as described.

{/* @ts-ignore */}
<win98-desktop style={{ height: '100%', width: '100%' }}>
{/* About Me Window */}
{/* @ts-ignore */}
<win98-window title="About_Me.exe" resizable show-minimize class="window-about-me" style={{
position: 'absolute',
top: '10vh',
left: '10vw',
width: '22vw',
height: '55vh',
zIndex: 10
}}>
<div className="window-body">
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: '10px' }}>
<img src={getImageUrl('Jeremypixel.png')} alt="Jeremy Pixel" style={{ width: '100px', border: '2px solid #808080' }} />
</div>
<h2 style={{ textAlign: 'center', margin: '5px 0' }}>{content.aboutMe.name}</h2>
<p style={{ textAlign: 'center', fontWeight: 'bold' }}>{content.aboutMe.title}</p>
<p>{content.aboutMe.bio}</p>
<hr />
<h3>Current Activities:</h3>
<ul>
{content.aboutMe.currentActivities.map((activity, i) => (
<li key={i}>{activity}</li>
))}
</ul>
</div>
{/* @ts-ignore */}
</win98-window>

{/* Skills Window */}
{/* @ts-ignore */}
<win98-window title="Skills.exe" resizable show-minimize class="window-skills" style={{
position: 'absolute',
top: '13vh',
right: '6vw',
width: '18vw',
height: '35vh',
zIndex: 10
}}>
<div className="window-body">
<h3>Programming Languages</h3>
<p>{content.skills.programmingLanguages}</p>
<hr />
<h3>Web & UI</h3>
<p>{content.skills.webUI}</p>
<hr />
<h3>Developer Tools</h3>
<p>{content.skills.developerTools}</p>
Comment on lines +72 to +80
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Two content.skills fields never surface.

roboticsSystems and dataML are defined in components/j-space-content.ts, but this window only renders three sections, so part of the new content payload is silently dropped.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/j-space-ui.tsx` around lines 72 - 80, The UI currently renders
only Programming Languages, Web & UI, and Developer Tools, so
content.skills.roboticsSystems and content.skills.dataML never appear; update
the JSpace UI render (the block that outputs the three <h3>/<p> pairs) to also
render roboticsSystems and dataML — either by adding two new sections with
headings (e.g., "Robotics Systems" and "Data & ML") and corresponding
<p>{content.skills.roboticsSystems}</p> / <p>{content.skills.dataML}</p> plus
separators, or by refactoring to iterate over content.skills keys and render all
entries dynamically so no new skill fields are dropped.

</div>
{/* @ts-ignore */}
</win98-window>

{/* Projects Window */}
{/* @ts-ignore */}
<win98-window title="Projects.exe" resizable show-minimize class="window-projects" style={{
position: 'absolute',
top: '2vh',
left: '33vw',
width: '42vw',
height: '88vh',
zIndex: 10
}}>
<div className="window-body" style={{ overflowY: 'auto', height: 'calc(100% - 40px)' }}>
{content.projects.map((project, i) => (
<div key={i} style={{ marginBottom: '20px', borderBottom: '1px solid #808080', paddingBottom: '10px' }}>
<h3>{project.title}</h3>
<p>{project.description}</p>
{project.image && (
<img src={getImageUrl(`${project.image}.png`)} alt={project.title} style={{ width: '100%', border: '1px solid #808080' }}
onError={(e) => { (e.target as HTMLImageElement).src = getImageUrl(`${project.image}.gif`) }} />
)}
<div style={{ marginTop: '10px' }}>
{project.github && <a href={project.github} target="_blank" rel="noreferrer"><button>GitHub</button></a>}
{project.website && <a href={project.website} target="_blank" rel="noreferrer"><button style={{ marginLeft: '5px' }}>Website</button></a>}
Comment on lines +104 to +106
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid nesting buttons inside links.

Each action is rendered as two interactive controls for one destination. That hurts keyboard/screen-reader behavior and is also why the lint rule is complaining about the inner <button>. Make the <a> look like a button instead of wrapping a button inside it.

🧰 Tools
🪛 Biome (2.4.6)

[error] 105-105: Provide an explicit type prop for the button element.

(lint/a11y/useButtonType)


[error] 106-106: Provide an explicit type prop for the button element.

(lint/a11y/useButtonType)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/j-space-ui.tsx` around lines 104 - 106, The JSX currently nests
<button> inside <a> for project.github and project.website; remove the inner
<button> and make the anchor itself look and behave like a button (apply the
button styles/classes instead of the nested element), keep target="_blank" and
rel="noreferrer", and add accessibility attributes such as role="button" and an
appropriate aria-label on the <a> elements to preserve keyboard and
screen-reader behavior in the component that renders
project.github/project.website.

</div>
</div>
))}
</div>
{/* @ts-ignore */}
</win98-window>

{/* Taskbar */}
{/* @ts-ignore */}
<win98-taskbar slot="taskbar"></win98-taskbar>
</win98-desktop>

<style jsx global>{`
@import url('https://fonts.googleapis.com/css2?family=Jersey+10&display=swap');

.j-space-container * {
cursor: default !important;
}
.j-space-container a,
.j-space-container button,
.j-space-container [role="button"] {
cursor: pointer !important;
}

.window-body h3 {
font-size: 1.2em;
margin: 10px 0 5px 0;
}

.window-body p {
margin: 5px 0;
}

.window-body ul {
padding-left: 20px;
}
`}</style>
</div>
)
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"test:e2e:debug": "playwright test --debug"
},
"dependencies": {
"98-components": "^0.1.1",
"98.css": "^0.1.21",
"@ai-sdk/amazon-bedrock": "^1.1.6",
"@ai-sdk/anthropic": "^1.2.12",
"@ai-sdk/google": "^1.2.22",
Expand Down
Binary file added public/j-space/assets/Backgroundpixels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/Jeremypixel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/Rodney Mullen Skate GIF.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/all-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/ascii-gif.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/back-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/bear.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/binder_action.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/bjj-grappling.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/conormcgregor.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/cookie-clicker-bot.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/cruisesunset.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/daneilcaesar-gif.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/dark-Backgroundpixels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/devpost-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/directory_computer-0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/email-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/forward-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/github-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/instagram-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/j-gif-space.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/j-space/assets/linkedin-icon.png
Binary file added public/j-space/assets/lockblock.png
Binary file added public/j-space/assets/music-player.png
Binary file added public/j-space/assets/netshow_arrow-2.png
Binary file added public/j-space/assets/paint_old.png
Binary file added public/j-space/assets/picture-painting.png
Binary file added public/j-space/assets/pixelbjj.jpg
Binary file added public/j-space/assets/portfolio-works-gif.gif
Binary file added public/j-space/assets/qhacksbus.png
Binary file added public/j-space/assets/resume-icon.png
Binary file added public/j-space/assets/rref_calculator.PNG
Binary file added public/j-space/assets/sinatrademo.gif
Binary file added public/j-space/assets/slot-machine.PNG
Binary file added public/j-space/assets/specifics-icon.png
Binary file added public/j-space/assets/startupgif.gif
Binary file added public/j-space/assets/stop_action.gif
Binary file added public/j-space/assets/stop_dont_go_on_grey.jpg
Binary file added public/j-space/assets/ufc-elo-calculator-vid.mp4
Binary file not shown.
Binary file added public/j-space/assets/ufc-search.gif
Binary file added public/j-space/assets/ufc_elo.png
Binary file added public/j-space/assets/user-chatbox.png
Binary file added public/j-space/assets/user-world.png
Binary file added public/j-space/assets/website-icon.png
Binary file added public/j-space/favicon.png