Initial commit from Orsiris
This commit is contained in:
parent
b2c40f4f3f
commit
0a19018ba4
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules\n.dockerignore\n.git\n*.log
|
||||||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
FROM node:18-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM node:18-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=builder /app ./
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["npm", "start"]
|
||||||
|
|
||||||
43
app/characters/[id]/page.tsx
Normal file
43
app/characters/[id]/page.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { promises as fs } from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
// ✅ Tell Next.js to render dynamically on every request
|
||||||
|
export const dynamic = "force-dynamic"
|
||||||
|
|
||||||
|
export default async function Page({ params }: { params: any }) {
|
||||||
|
const filePath = path.join(process.cwd(), 'data', 'characters', `${params.id}.json`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const raw = await fs.readFile(filePath, 'utf-8')
|
||||||
|
const character = JSON.parse(raw)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="p-8">
|
||||||
|
<h1 className="text-3xl font-bold mb-2">
|
||||||
|
{character.name} ({character.codename})
|
||||||
|
</h1>
|
||||||
|
<p>Age: {character.age}</p>
|
||||||
|
<p>Rank: {character.rank}</p>
|
||||||
|
<p>Affiliation: {character.affiliation}</p>
|
||||||
|
|
||||||
|
<h2 className="mt-4 font-semibold">Quotes:</h2>
|
||||||
|
<ul className="list-disc ml-6">
|
||||||
|
{character.quotes.map((q: string, i: number) => (
|
||||||
|
<li key={i}>{q}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
return (
|
||||||
|
<main className="p-8">
|
||||||
|
<h1 className="text-red-600 font-bold text-2xl">
|
||||||
|
Character not found: {params.id}
|
||||||
|
</h1>
|
||||||
|
<p className="text-sm mt-4 text-gray-500">
|
||||||
|
Tried to read: <code>{filePath}</code>
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
16
data/characters/CC-CHR-0001.json
Normal file
16
data/characters/CC-CHR-0001.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"id": "CC-CHR-0001",
|
||||||
|
"codename": "Soupfork",
|
||||||
|
"name": "Cadet Captain Tsai",
|
||||||
|
"age": 17,
|
||||||
|
"rank": "Naval Cadet Captain",
|
||||||
|
"affiliation": "Troy High NJROTC",
|
||||||
|
"quotes": [
|
||||||
|
"Discipline first. Emotions after.",
|
||||||
|
"I'm not a princess. I'm a commanding officer."
|
||||||
|
],
|
||||||
|
"food_likes": ["Unagi don", "Salmon sushi", "Cucumber", "Japanese curry"],
|
||||||
|
"food_dislikes": ["Eggplant"],
|
||||||
|
"signature_equipment": "Prototype Silver Combat Boots"
|
||||||
|
}
|
||||||
|
|
||||||
22
docker-compose.yml
Normal file
22
docker-compose.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
services:
|
||||||
|
cc-web:
|
||||||
|
build: .
|
||||||
|
container_name: cc-web
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- VIRTUAL_HOST=cc.johntsai.online
|
||||||
|
- LETSENCRYPT_HOST=cc.johntsai.online
|
||||||
|
- LETSENCRYPT_EMAIL=john@johntsai.online
|
||||||
|
expose:
|
||||||
|
- "3000"
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./public/images:/app/public/images
|
||||||
|
networks:
|
||||||
|
- proxy
|
||||||
|
|
||||||
|
networks:
|
||||||
|
proxy:
|
||||||
|
external: true
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user