Skip to content

Commit ea6a547

Browse files
author
jacoknapp
committed
Merge pull request 'Fixing broken photos link + Changing the defualt layout' (#4) from dev into main
Reviewed-on: https://gitea.knapp/jacoknapp/EternalVows/pulls/4
2 parents 8dc9b1e + 22b33f4 commit ea6a547

File tree

5 files changed

+62
-23
lines changed

5 files changed

+62
-23
lines changed

.github/workflows/docker.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ jobs:
1717
- name: Checkout
1818
uses: actions/checkout@v4
1919

20+
- name: Set up Node.js
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: '22'
24+
cache: 'npm'
25+
26+
- name: Install NPM dependencies
27+
run: npm install
28+
2029
- name: Set up QEMU
2130
uses: docker/setup-qemu-action@v3
2231

config/photos/.gitkeep

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Placeholder to ensure the photos directory exists in the repo.
2+
# Place .jpg/.jpeg/.png/.webp/.avif files here to be served at /photos/ and listed by /api/photos.

docker-compose.yml

Lines changed: 0 additions & 19 deletions
This file was deleted.

index.html

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,19 @@
7171
box-shadow: 0 20px 60px rgba(0,0,0,.35);
7272
text-align: center; /* Center names, date, and location */
7373
}
74-
.monogram { display:block; width:max-content; margin-left:0; margin-right:auto; padding:.25rem 1rem; border-radius:999px; border:1px solid rgba(255,255,255,.25);
75-
background: radial-gradient(ellipse at top left, var(--accent-1) 0%, transparent 70%), radial-gradient(ellipse at bottom right, var(--accent-2) 0%, transparent 60%);
76-
font-family: "Playfair Display", serif; letter-spacing: 1px; opacity:.95; }
74+
.monogram {
75+
display: inline-block;
76+
/* center within the header (parent has text-align:center) */
77+
margin: 0 0 .25rem;
78+
/* remove pill/button styling */
79+
padding: 0;
80+
border: none;
81+
border-radius: 0;
82+
background: transparent;
83+
font-family: "Playfair Display", serif;
84+
letter-spacing: 1px;
85+
opacity:.95;
86+
}
7787
h1.names { margin: .35rem 0 .25rem; font-family: "Great Vibes", cursive; font-size: clamp(2.2rem, 8vw, 4.2rem); font-weight: 400; letter-spacing:.4px; text-shadow: 0 2px 18px rgba(0,0,0,.45); }
7888
.tagline { font-size: clamp(1rem, 2.6vw, 1.2rem); opacity:.96 }
7989
.date { display:inline-block; margin-top:.4rem; font-weight:600; letter-spacing:.8px; background: linear-gradient(90deg, var(--accent-3), var(--accent-1)); -webkit-background-clip: text; background-clip: text; color: transparent; }

server.mjs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,39 @@ const __filename = fileURLToPath(import.meta.url);
99
const __dirname = path.dirname(__filename);
1010
const app = express();
1111

12+
// Simple structured logger with optional DEBUG
13+
const LOG_LEVEL = (process.env.LOG_LEVEL || 'info').toLowerCase();
14+
const isDebug = LOG_LEVEL === 'debug' || LOG_LEVEL === 'trace' || process.env.DEBUG === '1';
15+
const ts = () => new Date().toISOString();
16+
const info = (...args) => console.log(ts(), '[INFO]', ...args);
17+
const warn = (...args) => console.warn(ts(), '[WARN]', ...args);
18+
const error = (...args) => console.error(ts(), '[ERROR]', ...args);
19+
const debug = (...args) => { if (isDebug) console.log(ts(), '[DEBUG]', ...args); };
20+
1221
const ROOT = __dirname;
1322
const CONFIG_DIR = path.join(ROOT, 'config');
1423
const PHOTO_DIR = path.join(CONFIG_DIR, 'photos');
1524
const FAVICON_DIR = path.join(ROOT, 'favicon');
1625
const ALLOWED = new Set(['.jpg','.jpeg','.png','.webp','.avif']);
1726

27+
// Request/response logger with timing
28+
app.use((req, res, next) => {
29+
const start = process.hrtime.bigint();
30+
debug('Incoming request', { method: req.method, url: req.originalUrl || req.url, ip: req.ip });
31+
res.on('finish', () => {
32+
const durMs = Number(process.hrtime.bigint() - start) / 1e6;
33+
const msg = `${req.method} ${req.originalUrl || req.url} -> ${res.statusCode} ${Math.round(durMs)}ms`;
34+
if (res.statusCode >= 500) error(msg);
35+
else if (res.statusCode >= 400) warn(msg);
36+
else info(msg);
37+
});
38+
next();
39+
});
40+
1841
app.use(express.static(ROOT, { extensions: ['html'], etag: true, lastModified: true }));
1942
app.use('/config', express.static(CONFIG_DIR, { etag: true, lastModified: true }));
43+
// Serve photos from config/photos under a stable /photos path used by the client
44+
app.use('/photos', express.static(PHOTO_DIR, { etag: true, lastModified: true }));
2045
// Serve favicons and related assets
2146
app.use('/favicon', express.static(FAVICON_DIR, { etag: true, lastModified: true }));
2247
app.get('/favicon.ico', (_req, res) => res.sendFile(path.join(FAVICON_DIR, 'wedding_bell_favicon.ico')));
@@ -25,17 +50,29 @@ app.get('/site.webmanifest', (_req, res) => res.sendFile(path.join(FAVICON_DIR,
2550

2651
app.get('/api/photos', async (_req, res) => {
2752
try {
53+
debug('Listing photos from', PHOTO_DIR, 'allowed extensions:', [...ALLOWED].join(','));
2854
const primary = await readdir(PHOTO_DIR, { withFileTypes: true });
2955
const files = primary
3056
.filter(f => f.isFile() && ALLOWED.has(extname(f.name).toLowerCase()))
3157
.map(f => f.name)
3258
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
59+
info(`/api/photos -> ${files.length} files`);
3360
res.set('Cache-Control', 'no-store');
3461
res.json({ files });
3562
} catch (e) {
63+
// If the photos directory doesn't exist yet, treat as empty set
64+
if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) {
65+
warn('Photos directory not found; returning empty list');
66+
return res.json({ files: [] });
67+
}
68+
error('Failed to list photos:', e && e.stack ? e.stack : e);
3669
res.status(500).json({ error: e.message });
3770
}
3871
});
3972

4073
const port = process.env.PORT || 5500;
41-
app.listen(port, () => console.log(`Wedding site running at http://localhost:${port}`));
74+
app.listen(port, () => {
75+
info(`Wedding site running at http://localhost:${port}`);
76+
info('Environment', { node: process.versions.node, platform: process.platform, arch: process.arch, logLevel: LOG_LEVEL });
77+
info('Paths', { ROOT, CONFIG_DIR, PHOTO_DIR, FAVICON_DIR });
78+
});

0 commit comments

Comments
 (0)