Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ ARG COMMIT_SHA
ARG NEXT_PUBLIC_SENTRY_DSN

# sentry.server/edge configs skipped — no server runtime in a static export
COPY public ./public
# no `public/` dir: static assets (favicon, robots.txt) live under src/app.
# Re-add `COPY public ./public` here if one is ever introduced.
COPY src ./src
COPY tsconfig.json next.config.ts postcss.config.mjs ./

Expand Down
75 changes: 73 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,74 @@
# StegNet frontend website
# StegNet frontend

Welcome to the StegNet frontend website repo!
The public StegNet website. A statically-exported [Next.js](https://nextjs.org)
site, served by Caddy from a small Docker image and self-hosted behind Traefik.

## Stack

- **Next.js 16** (App Router) — exported to static HTML (`output: "export"`)
- **Bun** — package manager and build runtime
- **Tailwind CSS v4** + **shadcn** (Base UI) components
- **Sentry** — client error tracking, releases, source maps
- **LogTape** — structured logging
- **Caddy** — static file server in the runtime image
Comment thread
NullishUsername marked this conversation as resolved.

## Local development

```bash
bun install
bun dev
```

Then open http://localhost:3000.

### Environment

Local env lives in `.env.local` (gitignored). The site reads:

| Variable | Purpose |
| --- | --- |
| `NEXT_PUBLIC_SENTRY_DSN` | Sentry DSN (public) |
| `NEXT_PUBLIC_APP_VERSION` | Version shown in the footer (set at build) |
| `NEXT_PUBLIC_COMMIT_SHA` | Commit shown in the footer (set at build) |

Sentry `environment` is derived at runtime from the hostname (`staging.*` →
staging, `localhost` → development, otherwise production), so one build serves
every environment.

## Build

```bash
bun run build
```

Produces a static site in `out/`.

## Docker

The image builds the static export and serves it with Caddy on port **8080**
(non-root). TLS is terminated upstream by Traefik.

```bash
docker build \
--build-arg VERSION=1.2.3 \
--build-arg COMMIT_SHA="$(git rev-parse HEAD)" \
--secret id=SENTRY_AUTH_TOKEN,env=SENTRY_AUTH_TOKEN \
-t stegnet-frontpage .
```

## Release & deploy

Deploys are driven by **git tags**. Pushing a `vX.Y.Z` tag triggers
`.github/workflows/publish-image.yml`, which:

1. builds the image (version + commit baked in) and creates the Sentry release
with source maps,
2. pushes `ghcr.io/stegnet/frontpage:<version>` and `:latest` to GHCR,
3. records a Sentry deploy and calls the Portainer webhook to roll out.

```bash
git tag v1.2.3
git push origin v1.2.3
```

Portainer pulls the new tag from GHCR and Caddy serves it behind Traefik.
1 change: 0 additions & 1 deletion public/file.svg

This file was deleted.

1 change: 0 additions & 1 deletion public/globe.svg

This file was deleted.

1 change: 0 additions & 1 deletion public/next.svg

This file was deleted.

1 change: 0 additions & 1 deletion public/vercel.svg

This file was deleted.

1 change: 0 additions & 1 deletion public/window.svg

This file was deleted.

4 changes: 0 additions & 4 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@
--radius-4xl: calc(var(--radius) * 2.6);
}

h1 {
font-size: xx-large;
}

:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
Expand Down
31 changes: 31 additions & 0 deletions src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Link from "next/link";

export default function NotFound() {
return (
<main className="relative flex flex-1 flex-col items-center justify-center overflow-hidden px-6 text-center">
<div
aria-hidden
className="pointer-events-none absolute left-1/2 top-1/3 -z-10 h-[40rem] w-[40rem] -translate-x-1/2 -translate-y-1/2 rounded-full bg-gradient-to-tr from-amber-500/20 via-fuchsia-500/10 to-transparent blur-3xl"
/>

<p className="mb-4 text-sm font-medium tracking-widest text-muted-foreground">
404
</p>

<h1 className="max-w-2xl text-balance text-3xl font-semibold tracking-tight sm:text-5xl">
This page wandered off.
</h1>

<p className="mt-6 max-w-md text-balance text-base text-muted-foreground">
The page you&apos;re after doesn&apos;t exist — or isn&apos;t ready yet.
</p>

<Link
href="/"
className="mt-8 inline-flex items-center rounded-full border border-border px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground"
>
Back home
</Link>
</main>
);
}
Comment thread
NullishUsername marked this conversation as resolved.
31 changes: 25 additions & 6 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,31 @@ export default function Home() {
useEffect(() => {
logger.info('Rendering home page...', { platform: navigator.userAgent });
}, [logger]);

return (
<div className="flex flex-col flex-1 items-center justify-center font-sans bg-zinc-50 dark:bg-gray-900">
<h1> We are cooking up something awesome... </h1>
<hr className="w-96 h-1 mx-auto my-4 border-0 rounded-sm md:my-10 bg-gray-900 dark:bg-amber-50" />
<p> Pardon the lack of detail, we will reach out when we have more info for you. Check back soon-ish!</p>
</div>
<main className="relative flex flex-1 flex-col items-center justify-center overflow-hidden px-6 text-center">
{/* Soft background accent — decorative only. */}
<div
aria-hidden
className="pointer-events-none absolute left-1/2 top-1/3 -z-10 h-[40rem] w-[40rem] -translate-x-1/2 -translate-y-1/2 rounded-full bg-gradient-to-tr from-amber-500/20 via-fuchsia-500/10 to-transparent blur-3xl"
/>

<span className="mb-6 inline-flex items-center gap-2 rounded-full border border-border px-3 py-1 text-xs font-medium text-muted-foreground">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-amber-500 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-amber-500" />
Comment thread
NullishUsername marked this conversation as resolved.
</span>
StegNet
</span>

<h1 className="max-w-3xl text-balance text-4xl font-semibold tracking-tight sm:text-6xl">
We&apos;re cooking up something awesome.
</h1>

<p className="mt-6 max-w-md text-balance text-base text-muted-foreground sm:text-lg">
Pardon the lack of detail — we&apos;ll reach out when we have more for
you. Check back soon-ish.
</p>
</main>
);
}