Skip to content
RayderCPublic

About

Self-hosted personal portfolio with admin dashboard, project gallery, and hub for self-hosted services.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Amethyst

A self-hosted personal portfolio built for makers, welders, and fabricators. Post your projects with photos, YouTube embeds, and full markdown writeups. Everything is managed through a private admin dashboard — no external CMS, no cloud accounts, no subscriptions.


Features

Public Site

  • Home page — Editable hero, bio, and skills section. All content is changed from the dashboard with no code edits required.
  • Projects — Full project list with tag-based filtering. Each project supports a thumbnail, photo gallery, YouTube embed, and a complete markdown writeup.
  • Hub — A private bookmarks page for self-hosted services (Jellyfin, Nextcloud, Plex, Portainer, etc.) with auto-fetched favicons. Visible to any logged-in user. Each link has a green or red dot for whether it answers right now.
  • Your apps — SkyBit, ComicOrbit, AstroFit and NitroLog sit at the top of the Hub with their own icons, at localhost on their usual ports (7070, 7080, 7090, 7100). localhost only opens on the server itself, so for phones change each address under Dashboard → Hub to the server's IP or domain, or hide the ones you don't run.
  • Sign in with Amethyst — turn on shared login under Dashboard → System and paste its secret into the other apps' admin pages. Their login pages then get a Sign in with Amethyst button that signs in the account with the same username. Apps on your Hub go straight through; any other address asks first.
  • Animated cyberpunk UI — Circuit board background, neon glows, scan effects, and a glitch animation on the hero title.
  • Fully responsive — Works on desktop and mobile. The admin dashboard has a slide-out drawer on small screens.

Admin Dashboard

  • System — update notice (checks Docker Hub once a day, sends nothing about you), shared login, backups, and your recent sign-ins with Sign out everywhere else.
  • Backups — a copy of the database every night (the last 7, in /data/backups), plus Download backup (database and uploaded pictures in one .tar) and restore from a file or a saved copy. A copy is saved before every restore, so it can be undone.
  • Projects — Create, edit, and delete projects. Upload thumbnail and gallery photos directly (no external hosting needed). YouTube URL auto-parses into an embed.
  • Home Page Editor — Change your name, badge text, hero lines, bio, skills list, email, and GitHub link. Updates the live site instantly.
  • Hub Manager — Add, edit, and reorder links to self-hosted services. Favicon is auto-fetched from the service URL.
  • Users — Create additional accounts (admin or regular user). Only admins can access the dashboard; regular users can only access the Hub.

Access Levels

Page Public Logged-in User Admin
Home, Projects ✓ ✓ ✓
Hub — ✓ ✓
Dashboard — — ✓

Quick Start with Docker

The recommended way to run Amethyst. No environment variables required.

docker run -d \
  --name amethyst \
  --restart always \
  -p 3000:3000 \
  -v amethyst-data:/data \
  -v amethyst-uploads:/app/public/uploads \
  rayderc/amethyst:latest

Then open http://your-server:3000/setup to create your admin account.


Docker Compose

services:
  amethyst:
    image: rayderc/amethyst:latest
    container_name: amethyst
    restart: always
    ports:
      - 3000:3000
    volumes:
      - ./data:/data
      - ./uploads:/app/public/uploads
docker compose up -d

Environment Variables

All variables are optional. The app runs out of the box with no configuration.

Variable Default Description
SESSION_SECRET auto-generated Cookie encryption key (min 32 chars). Recommended in production — keeps sessions alive across container restarts.
DATABASE_PATH /data/amethyst.db Path to the SQLite database inside the container.
SESSION_COOKIE_SECURE false Set to true when running behind a TLS-terminating reverse proxy (HTTPS).

Example with fixed session secret

services:
  amethyst:
    image: rayderc/amethyst:latest
    container_name: amethyst
    restart: always
    ports:
      - 3000:3000
    environment:
      - SESSION_SECRET=your_random_secret_string_at_least_32_chars
      - SESSION_COOKIE_SECURE=true
    volumes:
      - ./data:/data
      - ./uploads:/app/public/uploads

Volumes

Path Contains
/data SQLite database (amethyst.db)
/app/public/uploads Uploaded images, served at /uploads/*

Mount both as volumes so data survives container updates.


Reverse Proxy (NGINX)

server {
    listen 443 ssl;
    server_name portfolio.example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Set SESSION_COOKIE_SECURE=true when running behind HTTPS.


Updating

docker pull rayderc/amethyst:latest
docker compose down && docker compose up -d

Database and uploads are preserved in volumes — nothing is lost on update.


Running Locally

Prerequisites: Node.js 20+, npm

git clone https://github.com/RayderC/Amethyst.git
cd Amethyst
npm install
npm run dev

Open http://localhost:3000, then navigate to /setup to create your admin account.


First-Time Setup

  1. Start the app (Docker or npm run dev)
  2. Go to /setup — create your admin account (only works before any user exists)
  3. Log in at /login
  4. Dashboard → Home Page — set your name, bio, hero text, and skills
  5. Dashboard → Projects → New Project — add your first project
  6. Toggle "Feature on home page" to show it on the front page
  7. Dashboard → Hub — add links to your self-hosted services

Tech Stack

Layer Technology
Framework Next.js 16 (App Router + Pages API Routes)
Language TypeScript 5
Database SQLite via better-sqlite3
Auth iron-session (encrypted cookie sessions)
Markdown react-markdown + remark-gfm
Styling Custom CSS with CSS custom properties
Container Docker (multi-platform: linux/amd64, linux/arm64)

Project Structure

app/
  components/        Shared UI — Navigation, ProjectCard, MarkdownEditor,
                     CircuitBackground, FooterAuth
  dashboard/         Protected admin pages — projects, home editor, hub, users
  hub/               Private service links page (any logged-in user)
  projects/          Public project list and detail pages
  page.tsx           Home page (server-rendered, reads config from DB)
  layout.tsx         Root layout — circuit canvas, dynamic metadata

pages/api/           API routes (Next.js Pages Router)
  login / logout / user / register / setup
  projects/          CRUD for portfolio projects
  sessions/          CRUD for hub service links
  site-config        Home page content
  users/             User management
  favicon            Favicon proxy (direct fetch → Google fallback)

lib/
  db.ts              SQLite connection, schema migrations, helpers
  session.ts         iron-session config
  siteConfig.ts      Default site content (overridden by DB values)
  url.ts             URL normalization helpers

public/uploads/      Uploaded images (gitignored, mounted as Docker volume)

License

MIT

About

Self-hosted personal portfolio with admin dashboard, project gallery, and hub for self-hosted services.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages