chore(config): update .gitignore and enhance Next.js configuration

Added .superpowers directory to .gitignore to prevent tracking of specific Pocketbase data. Updated Next.js configuration to enable standalone output for optimized Docker image builds, reducing the need for the full node_modules tree.
This commit is contained in:
Dave 2026-09-19 07:52:09 +02:00
parent 616a6674c8
commit 2d87cd505b
11 changed files with 1499 additions and 1 deletions

13
.dockerignore Normal file
View file

@ -0,0 +1,13 @@
node_modules
.next
.git
.env*
!.env.example
docs
tests
.superpowers
pocketbase
*.md
.vscode
.DS_Store
npm-debug.log*

2
.gitignore vendored
View file

@ -4,4 +4,4 @@ node_modules/
next-env.d.ts
*.tsbuildinfo
pocketbase/pocketbase
pocketbase/pb_data/
pocketbase/pb_data/.superpowers/

View file

@ -0,0 +1,96 @@
<h2>B + C combined, with real metrics instead of placeholders</h2>
<p class="subtitle">Two things had to be nailed down before this could be real rather than a mockup: what the banner colour does with an arbitrary client hex, and what the progress bar / status line actually measure.</p>
<style>
.pm-tile { border: 1px solid #2a2a32; border-radius: 10px; padding: 12px; background: #1c1c22; }
.pm-name { font-size: 13px; font-weight: 600; color: #eee; }
.pm-sub { font-size: 11px; color: #8a8a94; margin-top: 2px; }
.pm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 14px; }
.pm-pill { font-size: 9px; padding: 1px 6px; border-radius: 999px; background: #3a2a20; color: #e2a25a; margin-left: 6px; }
.pm-bar-track { height: 4px; border-radius: 2px; background: #2a2a32; margin-top: 8px; overflow: hidden; }
.pm-bar-fill { height: 100%; border-radius: 2px; }
.pm-banner { border-radius: 8px 8px 0 0; padding: 7px 12px; font-size: 11px; font-weight: 600; display:flex; align-items:center; gap:6px; }
.pm-banner-dot { width:6px; height:6px; border-radius:50%; }
.pm-banner-body { border: 1px solid #2a2a32; border-top: none; border-radius: 0 0 8px 8px; padding: 10px; background: #16161b; }
</style>
<div class="mockup">
<div class="mockup-header">Preview: Projects, grouped with banners + activity cards</div>
<div class="mockup-body" style="padding:16px; background:#111116;">
<div style="margin-bottom:16px;">
<div class="pm-banner" style="background:rgba(61,123,217,0.14); color:#6ea3ea;">
<span class="pm-banner-dot" style="background:#3d7bd9;"></span>WF
</div>
<div class="pm-banner-body">
<div class="pm-grid">
<div class="pm-tile">
<div class="pm-name">WFDash Web App</div>
<div class="pm-sub">6 open · 14 done</div>
<div class="pm-bar-track"><div class="pm-bar-fill" style="width:70%; background:#3d7bd9;"></div></div>
<div class="pm-sub" style="margin-top:6px;">Active 2 days ago</div>
</div>
<div class="pm-tile">
<div class="pm-name">WFDASH Driver App</div>
<div class="pm-sub">0 open · 0 done</div>
<div class="pm-bar-track"><div class="pm-bar-fill" style="width:0%;"></div></div>
<div class="pm-sub" style="margin-top:6px;">No activity yet</div>
</div>
</div>
</div>
</div>
<div>
<div class="pm-banner" style="background:rgba(201,106,63,0.14); color:#dd8f66;">
<span class="pm-banner-dot" style="background:#c96a3f;"></span>RJBULK
</div>
<div class="pm-banner-body">
<div class="pm-grid" style="margin-bottom:0;">
<div class="pm-tile">
<div class="pm-name">RJ Bulk App</div>
<div class="pm-sub">0 open · 0 done</div>
<div class="pm-bar-track"><div class="pm-bar-fill" style="width:0%;"></div></div>
<div class="pm-sub" style="margin-top:6px;">No activity yet</div>
</div>
<div class="pm-tile">
<div class="pm-name">Diesel Depot App<span class="pm-pill">Prototype</span></div>
<div class="pm-sub">0 open · 0 done</div>
<div class="pm-bar-track"><div class="pm-bar-fill" style="width:0%;"></div></div>
<div class="pm-sub" style="margin-top:6px;">No activity yet</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="section">
<h3>What changed from the rough mockup, and why</h3>
<div class="pros-cons">
<div class="pros">
<h4>Banner</h4>
<ul>
<li>Soft tint (~14% of the client's colour) with the colour itself used for the text, not a solid fill — a client's arbitrary hex (say bright yellow, or near-white) would make banner text unreadable at full strength. This is a legibility fix, not a taste change.</li>
</ul>
</div>
<div class="cons">
<h4>Progress bar + status line</h4>
<ul>
<li><b>Bar</b> = done cards ÷ total cards on that project's board. Real, already computable, matches the "one honest metric" pattern used on the roadmap page's checklist %.</li>
<li><b>Status line</b> = time since the project's most recent commit ("Active 2 days ago" / "No activity yet") rather than "2 due this week" from the rough mockup — target dates are sparse (most cards have none), but commit activity is the one thing this app already tracks reliably for every ingested project.</li>
</ul>
</div>
</div>
</div>
<div class="options">
<div class="option" data-choice="approve" onclick="toggleSelect(this)">
<div class="letter">✓</div>
<div class="content"><h3>This is the direction</h3><p>Proceed to a full design write-up</p></div>
</div>
<div class="option" data-choice="adjust" onclick="toggleSelect(this)">
<div class="letter">✗</div>
<div class="content"><h3>Close, but adjust something</h3><p>Tell me what in the terminal</p></div>
</div>
</div>

View file

@ -0,0 +1,123 @@
<h2>Which direction for the Projects screen?</h2>
<p class="subtitle">Same real data (WF, RJBULK, Mega Infrastructure) — three different visual treatments. Click the one that's closest to what you want, even if it's not perfect yet.</p>
<style>
.pm-tile { border: 1px solid #2a2a32; border-radius: 10px; padding: 12px; background: #1c1c22; }
.pm-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 6px; }
.pm-name { font-size: 13px; font-weight: 600; color: #eee; }
.pm-sub { font-size: 11px; color: #8a8a94; margin-top: 2px; }
.pm-group { margin-bottom: 14px; }
.pm-group-label { font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; color: #8a8a94; margin-bottom: 6px; }
.pm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.pm-pill { font-size: 9px; padding: 1px 6px; border-radius: 999px; background: #3a2a20; color: #e2a25a; }
.pm-bar-track { height: 4px; border-radius: 2px; background: #2a2a32; margin-top: 8px; overflow: hidden; }
.pm-bar-fill { height: 100%; border-radius: 2px; }
.pm-banner { border-radius: 10px 10px 0 0; padding: 8px 12px; font-size: 11px; font-weight: 600; color: #fff; }
.pm-banner-body { border: 1px solid #2a2a32; border-top: none; border-radius: 0 0 10px 10px; padding: 10px; background: #1c1c22; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
</style>
<div class="cards">
<div class="card" data-choice="minimal" onclick="toggleSelect(this)">
<div class="card-image" style="padding:14px; background:#111116;">
<div class="pm-group">
<div class="pm-group-label"><span class="pm-dot" style="background:#3d7bd9"></span>WF</div>
<div class="pm-grid">
<div class="pm-tile" style="border-left:3px solid #3d7bd9;">
<div class="pm-name">WFDash Web App</div>
<div class="pm-sub">6 open cards</div>
</div>
<div class="pm-tile" style="border-left:3px solid #3d7bd9;">
<div class="pm-name">WFDASH Driver App</div>
<div class="pm-sub">0 open cards</div>
</div>
</div>
</div>
<div class="pm-group">
<div class="pm-group-label"><span class="pm-dot" style="background:#c96a3f"></span>RJBULK</div>
<div class="pm-grid">
<div class="pm-tile" style="border-left:3px solid #c96a3f;">
<div class="pm-name">RJ Bulk App</div>
<div class="pm-sub">0 open cards</div>
</div>
<div class="pm-tile" style="border-left:3px solid #c96a3f; opacity:0.75;">
<div class="pm-name">Diesel Depot App</div>
<div class="pm-sub">Prototype · 0 open</div>
</div>
</div>
</div>
</div>
<div class="card-body">
<h3>A — Minimal &amp; Spacious</h3>
<p>Client colour moves to a left-edge stripe on the tile itself, instead of a separate dot on both the header and the tile. Less border noise, more whitespace, one clean line of status text instead of pills.</p>
</div>
</div>
<div class="card" data-choice="rich" onclick="toggleSelect(this)">
<div class="card-image" style="padding:14px; background:#111116;">
<div class="pm-group">
<div class="pm-group-label"><span class="pm-dot" style="background:#3d7bd9"></span>WF</div>
<div class="pm-grid">
<div class="pm-tile">
<div class="pm-name">WFDash Web App</div>
<div class="pm-sub">6 open · 2 due this week</div>
<div class="pm-bar-track"><div class="pm-bar-fill" style="width:64%; background:#3d7bd9;"></div></div>
</div>
<div class="pm-tile">
<div class="pm-name">WFDASH Driver App</div>
<div class="pm-sub">No activity yet</div>
<div class="pm-bar-track"><div class="pm-bar-fill" style="width:4%; background:#4a4a55;"></div></div>
</div>
</div>
</div>
<div class="pm-group">
<div class="pm-group-label"><span class="pm-dot" style="background:#c96a3f"></span>RJBULK</div>
<div class="pm-grid">
<div class="pm-tile">
<div class="pm-name">RJ Bulk App <span class="pm-pill">Prototype</span></div>
<div class="pm-sub">No activity yet</div>
<div class="pm-bar-track"><div class="pm-bar-fill" style="width:0%;"></div></div>
</div>
</div>
</div>
</div>
<div class="card-body">
<h3>B — Richer Data Cards</h3>
<p>Each tile becomes a tiny dashboard preview: a progress bar and a status line ("2 due this week", "No activity yet") instead of a bare number. More useful at a glance, more visually busy.</p>
</div>
</div>
<div class="card" data-choice="banner" onclick="toggleSelect(this)">
<div class="card-image" style="padding:14px; background:#111116;">
<div class="pm-banner" style="background:#3d7bd9;">WF</div>
<div class="pm-banner-body" style="margin-bottom:14px;">
<div class="pm-tile" style="border:none; background:transparent; padding:4px;">
<div class="pm-name">WFDash Web App</div>
<div class="pm-sub">6 open cards</div>
</div>
<div class="pm-tile" style="border:none; background:transparent; padding:4px;">
<div class="pm-name">WFDASH Driver App</div>
<div class="pm-sub">0 open cards</div>
</div>
</div>
<div class="pm-banner" style="background:#c96a3f;">RJBULK</div>
<div class="pm-banner-body">
<div class="pm-tile" style="border:none; background:transparent; padding:4px;">
<div class="pm-name">RJ Bulk App</div>
<div class="pm-sub">0 open cards</div>
</div>
<div class="pm-tile" style="border:none; background:transparent; padding:4px;">
<div class="pm-name">Diesel Depot App <span class="pm-pill">Prototype</span></div>
<div class="pm-sub">0 open cards</div>
</div>
</div>
</div>
<div class="card-body">
<h3>C — Coloured Client Banners</h3>
<p>Each client gets a solid-colour header bar instead of a small dot + label. Strongest visual separation between clients at a glance across a long list; tiles underneath stay flat and simple since the banner already carries the identity.</p>
</div>
</div>
</div>
<p class="subtitle" style="margin-top:16px;">These are rough — spacing, exact colours and card size are easy to tune once we pick a direction. You can also mix ideas from more than one (e.g. banners from C with the progress bar from B).</p>

View file

@ -0,0 +1 @@
{"reason":"idle timeout","timestamp":1789653732910}

View file

@ -0,0 +1,4 @@
{"type":"server-started","port":50672,"host":"127.0.0.1","url_host":"localhost","url":"http://localhost:50672","screen_dir":"/Volumes/EXT/DEVELOPMENT-FORGEJO/KANBANBOARD-DEV/.superpowers/brainstorm/24862-1789651152/content","state_dir":"/Volumes/EXT/DEVELOPMENT-FORGEJO/KANBANBOARD-DEV/.superpowers/brainstorm/24862-1789651152/state"}
{"type":"screen-added","file":"/Volumes/EXT/DEVELOPMENT-FORGEJO/KANBANBOARD-DEV/.superpowers/brainstorm/24862-1789651152/content/layout-directions.html"}
{"type":"screen-added","file":"/Volumes/EXT/DEVELOPMENT-FORGEJO/KANBANBOARD-DEV/.superpowers/brainstorm/24862-1789651152/content/combined-b-c.html"}
{"type":"server-stopped","reason":"idle timeout"}

View file

@ -0,0 +1 @@
24871

56
Dockerfile Normal file
View file

@ -0,0 +1,56 @@
# Client Board — production image for Coolify.
#
# This container is the Next.js app ONLY. PocketBase is a separate, already-
# hosted service (see docs/superpowers memory: "Coolify-only PocketBase") —
# this Dockerfile does not run or bundle it.
#
# NEXT_PUBLIC_APP_URL and NEXT_PUBLIC_PB_URL are inlined into the client
# JavaScript bundle at BUILD time, not read at container start. Coolify must
# be told to pass them as build arguments (its "Build Variables" section),
# not just as runtime environment variables — a value only set at runtime
# will be missing from the browser bundle entirely.
# ---- deps: install once, reused unless package*.json changes ----
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# ---- builder: compile with the build-time public vars baked in ----
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ARG NEXT_PUBLIC_APP_URL
ARG NEXT_PUBLIC_PB_URL
ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL
ENV NEXT_PUBLIC_PB_URL=$NEXT_PUBLIC_PB_URL
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# ---- runner: the small image Coolify actually deploys ----
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Standalone's server only binds every interface when told to — left at the
# default it binds localhost-only, which is unreachable from outside the
# container.
ENV HOSTNAME=0.0.0.0
ENV PORT=3000
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,10 @@ import type { NextConfig } from "next";
const nextConfig: NextConfig = {
reactStrictMode: true,
// A self-contained server bundle — the whole point of the Dockerfile's
// small final image. Without it the runtime stage would need the full
// node_modules tree instead of the pruned one Next assembles itself.
output: "standalone",
};
export default nextConfig;

0
public/.gitkeep Normal file
View file