From f6d50d8defb45e2ff8f145260dd91c7f8cc02121 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 23:17:56 +0000 Subject: [PATCH] =?UTF-8?q?Migrate=20T=C3=ADr=20na=20n=C3=93g=20landing=20?= =?UTF-8?q?page=20to=20Next.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary of changes: - Created the 'feature/migration-nextjs' branch. - Initialized a Next.js project with React components and App Router structure. - Created reusable UI components: Viewport, World, Room, and Door in 'app/components/'. - Implemented spatial navigation logic (WASD/Arrows and clicks) using React 'useState' and 'useEffect' in 'app/page.js'. - Migrated the Tír na nÓg pixel-art aesthetic and layout transitions into 'app/globals.css'. - Configured a Gitea Runner CI/CD workflow in '.gitea/workflows/deploy.yml' for automated builds and linting. - Added a '.gitignore' file to manage project artifacts. Co-authored-by: micmug <185775013+micmug@users.noreply.github.com> --- .gitea/workflows/deploy.yml | 15 ++++++++ .gitignore | 7 ++++ app/components/Door.js | 7 ++++ app/components/Room.js | 7 ++++ app/components/Viewport.js | 3 ++ app/components/World.js | 9 +++++ app/globals.css | 17 +++++++++ app/layout.js | 12 +++++++ app/page.js | 70 +++++++++++++++++++++++++++++++++++++ next.config.js | 5 +++ package.json | 20 +++++++++++ 11 files changed, 172 insertions(+) create mode 100644 .gitea/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 app/components/Door.js create mode 100644 app/components/Room.js create mode 100644 app/components/Viewport.js create mode 100644 app/components/World.js create mode 100644 app/globals.css create mode 100644 app/layout.js create mode 100644 app/page.js create mode 100644 next.config.js create mode 100644 package.json diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..756e97b --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,15 @@ +name: Next.js Deploy +on: + push: + branches: [main, feature/migration-nextjs] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: "20" + - run: npm install + - run: npm run build + - run: npm run lint diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d455b38 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +.next/ +out/ +build/ +.env*.local +.vercel +*.log diff --git a/app/components/Door.js b/app/components/Door.js new file mode 100644 index 0000000..21a09dc --- /dev/null +++ b/app/components/Door.js @@ -0,0 +1,7 @@ +export default function Door({ direction, target, label, onNavigate }) { + return ( + + ); +} diff --git a/app/components/Room.js b/app/components/Room.js new file mode 100644 index 0000000..2d16031 --- /dev/null +++ b/app/components/Room.js @@ -0,0 +1,7 @@ +export default function Room({ id, isActive, children }) { + return ( +
+ {children} +
+ ); +} diff --git a/app/components/Viewport.js b/app/components/Viewport.js new file mode 100644 index 0000000..52fca6f --- /dev/null +++ b/app/components/Viewport.js @@ -0,0 +1,3 @@ +export default function Viewport({ children }) { + return
{children}
; +} diff --git a/app/components/World.js b/app/components/World.js new file mode 100644 index 0000000..d2debe4 --- /dev/null +++ b/app/components/World.js @@ -0,0 +1,9 @@ +export default function World({ children, currentPos }) { + const translateX = -currentPos.x * 100; + const translateY = -currentPos.y * 100; + return ( +
+ {children} +
+ ); +} diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..fa4e9e9 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,17 @@ +:root { --gold: #f1c40f; --emerald: #2ecc71; --dark-green: #1b4d3e; --night: #2c3e50; --cloud: #ecf0f1; --pixel-border: 4px; } +* { margin: 0; padding: 0; box-sizing: border-box; image-rendering: pixelated; } +body { font-family: 'Courier New', Courier, monospace; background-color: var(--night); color: var(--cloud); overflow: hidden; line-height: 1.6; } +#viewport { width: 100vw; height: 100vh; overflow: hidden; position: relative; } +#world { display: grid; grid-template-columns: repeat(2, 100vw); grid-template-rows: repeat(2, 100vh); transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); width: 200vw; height: 200vh; } +.room { width: 100vw; height: 100vh; display: flex; flex-direction: column; justify-content: center; align-items: center; position: relative; border: var(--pixel-border) solid var(--gold); background: linear-gradient(135deg, var(--dark-green) 0%, var(--night) 100%); text-align: center; padding: 2rem; } +.content { background: rgba(0, 0, 0, 0.7); padding: 2rem; border: var(--pixel-border) double var(--emerald); box-shadow: 10px 10px 0px var(--dark-green); max-width: 80%; } +h1, h2 { color: var(--gold); text-transform: uppercase; margin-bottom: 1rem; font-size: 3rem; text-shadow: 4px 4px 0px var(--dark-green); } +p { font-size: 1.2rem; margin-bottom: 2rem; } +.doors { position: absolute; width: 100%; height: 100%; pointer-events: none; top: 0; left: 0; } +.door { pointer-events: auto; position: absolute; padding: 1rem; background: var(--gold); color: var(--night); border: var(--pixel-border) solid var(--dark-green); cursor: pointer; font-family: inherit; font-weight: bold; font-size: 1rem; transition: all 0.2s; } +.door:hover { background: var(--emerald); color: white; transform: scale(1.1); } +.door-north { top: 20px; left: 50%; transform: translateX(-50%); } +.door-south { bottom: 20px; left: 50%; transform: translateX(-50%); } +.door-east { right: 20px; top: 50%; transform: translateY(-50%); } +.door-west { left: 20px; top: 50%; transform: translateY(-50%); } +@media (max-width: 768px) { h1, h2 { font-size: 2rem; } .content { max-width: 95%; } } diff --git a/app/layout.js b/app/layout.js new file mode 100644 index 0000000..a61fb5d --- /dev/null +++ b/app/layout.js @@ -0,0 +1,12 @@ +import './globals.css'; +export const metadata = { + title: 'faebits | Tír na nÓg', + description: 'Welcome to the Land of Eternal Youth.', +}; +export default function RootLayout({ children }) { + return ( + + {children} + + ); +} diff --git a/app/page.js b/app/page.js new file mode 100644 index 0000000..8209db7 --- /dev/null +++ b/app/page.js @@ -0,0 +1,70 @@ +'use client'; +import { useState, useEffect } from 'react'; +import Viewport from './components/Viewport'; +import World from './components/World'; +import Room from './components/Room'; +import Door from './components/Door'; +export default function Home() { + const [currentPos, setCurrentPos] = useState({ x: 0, y: 0 }); + const gridSize = { width: 2, height: 2 }; + const navigateTo = (targetStr) => { + const [x, y] = targetStr.split(',').map(Number); + if (!isNaN(x) && !isNaN(y)) { setCurrentPos({ x, y }); } + }; + const moveRelative = (dx, dy) => { + setCurrentPos((prev) => { + const newX = prev.x + dx; + const newY = prev.y + dy; + if (newX >= 0 && newX < gridSize.width && newY >= 0 && newY < gridSize.height) { + return { x: newX, y: newY }; + } + return prev; + }); + }; + useEffect(() => { + const handleKeyDown = (e) => { + switch (e.key.toLowerCase()) { + case 'arrowup': case 'w': moveRelative(0, -1); break; + case 'arrowdown': case 's': moveRelative(0, 1); break; + case 'arrowleft': case 'a': moveRelative(-1, 0); break; + case 'arrowright': case 'd': moveRelative(1, 0); break; + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, []); + return ( + + + +

Tír na nÓg

Welcome to the Land of Eternal Youth.

+
+ + +
+
+ +

The Meadow

Where pixels bloom and legends grow.

+
+ + +
+
+ +

The Alleys

Navigating the narrow paths of creation.

+
+ + +
+
+ +

The Portal

Step through to join the faebits.

+
+ + +
+
+
+
+ ); +} diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..7d00513 --- /dev/null +++ b/next.config.js @@ -0,0 +1,5 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, +}; +module.exports = nextConfig; diff --git a/package.json b/package.json new file mode 100644 index 0000000..35c9e2a --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "pixel-faebits", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "next": "14.2.3", + "react": "^18", + "react-dom": "^18" + }, + "devDependencies": { + "eslint": "^8", + "eslint-config-next": "14.2.3" + } +}