Extract Vue frontend into separate container and add stp_wasm crate
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m58s

Move Vue app from nginx/vue/ to top-level vue/ with its own Dockerfile,
update docker-compose configs and nginx proxy to serve from the new
container, and add initial Rust WASM crate (stp_wasm). Also fix .gitignore
to exclude Rust target/ directories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-25 16:40:45 +00:00
parent 2b84730126
commit d3d3269d49
182 changed files with 215 additions and 34 deletions

5
vue/.dockerignore Normal file
View File

@@ -0,0 +1,5 @@
node_modules
.vite
dist
**/.git
**/.DS_Store

7
vue/Dockerfile Normal file
View File

@@ -0,0 +1,7 @@
FROM node:22-slim
RUN apt-get update && apt-get install -y make git && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["sh", "-c", "npm run build -- --outDir /output --emptyOutDir"]

41
vue/README.md Normal file
View File

@@ -0,0 +1,41 @@
# My Web - Frontend
Vue 3 SPA for [adam-french.co.uk](https://adam-french.co.uk). Built with Vite, Tailwind CSS v4, Pinia, and Vue Router.
## Setup
```sh
npm install
```
## Development
```sh
npm run dev
```
The Vite dev server proxies API requests:
- `/api` -> `http://localhost:8080` (Go backend)
- `/gitea` -> `http://localhost:3000` (Gitea)
- `/radio` -> `http://localhost:8000` (Icecast2)
## Production Build
```sh
npm run build
```
In production, the built `dist/` is served by Nginx inside a Docker container (see `../Dockerfile`).
## Recommended IDE Setup
[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Recommended Browser Setup
- Chromium-based browsers (Chrome, Edge, Brave, etc.):
- [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
- [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
- Firefox:
- [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
- [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)

136
vue/crates/stp_wasm/Cargo.lock generated Normal file
View File

@@ -0,0 +1,136 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "bumpalo"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "js-sys"
version = "0.3.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "stp_wasm"
version = "0.1.0"
dependencies = [
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "syn"
version = "2.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "wasm-bindgen"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-sys"
version = "0.3.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
dependencies = [
"js-sys",
"wasm-bindgen",
]

View File

@@ -0,0 +1,15 @@
[package]
name = "stp_wasm"
version = "0.1.0"
edition = "2024"
[dependencies]
js-sys = "0.3.85"
wasm-bindgen = "0.2.108"
web-sys = { version = "0.3.85", features = [
"console",
"Document",
"Element",
"Window",
"Animation",
] }

View File

@@ -0,0 +1,6 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct BadApplePlayer {
is_playing: bool,
}

12
vue/index.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AF</title>
<link rel="icon" type="/img/x-icon" href="/img/favicon.ico" />
</head>
<body id="app">
<script type="module" src="/src/main.js"></script>
</body>
</html>

8
vue/jsconfig.json Normal file
View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

3788
vue/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

33
vue/package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"name": "nginx-html",
"version": "0.0.0",
"private": true,
"type": "module",
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@mdit/plugin-katex": "^0.24.1",
"@tailwindcss/vite": "^4.1.18",
"@vueuse/core": "^14.2.1",
"axios": "^1.13.2",
"katex": "^0.16.27",
"markdown-it": "^14.1.0",
"markdown-it-wikilinks": "^1.4.0",
"pinia": "^3.0.4",
"tailwindcss": "^4.1.18",
"typescript": "^5.9.3",
"vue": "^3.5.22",
"vue-router": "^4.6.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"vite": "^7.1.11",
"vite-plugin-vue-devtools": "^8.0.3"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vue/public/fonts/m12.ttf Normal file

Binary file not shown.

BIN
vue/public/img/Untitled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vue/public/img/epic.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vue/public/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
vue/public/img/img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
vue/public/img/rune.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
vue/public/img/uh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

2
vue/public/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-agent: *
Allow: /

Binary file not shown.

12
vue/src/App.vue Normal file
View File

@@ -0,0 +1,12 @@
<script setup>
import { RouterView } from "vue-router";
import Navbar from "@/components/Navbar.vue";
import Footer from "@/components/Footer.vue";
</script>
<template>
<Navbar class="no-print sticky" />
<RouterView />
<!-- <Footer style="height: 10vh" /> -->
</template>

299
vue/src/assets/styles.css Normal file
View File

@@ -0,0 +1,299 @@
@import "tailwindcss";
/* PRINTING */
@media print {
.no-print,
.no-print * {
display: none !important;
margin: 0px;
padding: 0px;
width: 0x;
height: 0px;
}
}
/* END OF PRINTING */
/* FONTS */
@font-face {
font-family: "big_noodle_titling";
src: url("/fonts/big_noodle_titling.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "CreatoDisplay";
src: url("/fonts/CreatoDisplay-Bold.otf") format("opentype");
font-weight: normal;
font-style: normal;
}
/* END OF FONTS */
/* VARIABLES */
:root {
/* RED, WHITE, BLACK are standard*/
--portal_grey: #dddddd;
--portal_orange: #ff9a00;
--portal_light_orange: #ff5d00;
--portal_blue: #0065ff;
--portal_light_blue: #00a2ff;
/* MAIN COLORS */
--primary: #55ffbb;
--secondary: #62ff57;
--tertiary: #ff579a;
--quaternary: #024942;
/* BACKGROUND COLORS */
--bg_primary: #1b110e;
--bg_secondary: #000;
--link: #222;
--bdr: 2px;
--spacing: 3px;
/* FONTS USED */
--font_heading: big_noodle_titling;
--font_default: CreatoDisplay;
}
@theme {
--color-primary: var(--primary);
--color-secondary: var(--secondary);
--color-tertiary: var(--tertiary);
--color-quaternary: var(--quaternary);
--color-bg_primary: var(--bg_primary);
--color-bg_secondary: var(--bg_secondary);
--color-link: var(--link);
--borderWidth-primary: var(--primary);
--borderWidth-secondary: var(--secondary);
--borderWidth-tertiary: var(--tertiary);
--font-heading: var(--font_heading);
--default-font-family: var(--font_default);
}
/* END OF VARIABLES */
/* ELEMENTS */
body {
margin: 0 auto;
width: 100vw;
height: 100vh;
}
main {
@apply overflow-y-scroll w-full h-full p-10;
}
input {
@apply text-secondary border-primary border;
}
small {
@apply text-tertiary;
}
code {
@apply text-tertiary;
}
ul {
@apply text-tertiary;
}
li {
@apply text-tertiary;
}
h1,
h2,
h3,
h4 {
@apply m-1 font-heading text-primary;
}
h3,
h4 {
@apply text-lg;
}
h1 {
@apply text-2xl;
}
h2 {
@apply text-xl;
}
p {
@apply text-secondary;
}
a {
@apply text-primary bg-link text-center font-heading tracking-wide;
}
input,
textarea {
@apply text-primary border p-2 w-full;
}
input::placeholder,
textarea::placeholder {
@apply text-secondary opacity-50;
}
table {
@apply border-primary border text-primary;
}
td {
@apply gap-1;
}
tr {
@apply border-primary border-b text-primary;
}
th {
@apply pr-3 pl-3 border-r border-dotted border-tertiary;
}
td {
@apply pr-3 pl-3;
}
/* END OF ELEMENTS */
/* CLASSES */
.img-stamp {
width: 99px;
height: 55px;
}
/* BORDERS */
.bdr-1 {
@apply border-30;
border-image: url("/img/borders/border1.gif") 30 round;
}
.bdr-1-inv {
@apply border-30;
border-image: url("/img/borders/border1inv.gif") 30 round;
}
.bdr-2 {
@apply border-5;
border-image: url("/img/borders/border4.gif") 7 round;
}
.bdr-cv {
@apply border-30;
border-image: url("/img/borders/bordercv.png") 30 round;
}
/* A5 Page */
.a5page-landscape {
@apply m-0 box-content;
height: 148mm;
width: 210mm;
}
.a5page-portrait {
@apply m-0 box-content;
width: 148mm;
height: 210mm;
}
/* A4 Page */
.a4page-portrait {
@apply m-0 box-content;
width: 210mm;
height: 297mm;
}
.a4page-landscape {
@apply m-0 box-content;
height: 210mm;
width: 297mm;
}
/* END OF CLASSES */
/* PHONE */
@media (max-width: 850px) {
.a4page-portrait {
width: 100%;
/* fill mobile width */
height: fit-content;
margin: 0 auto;
/* center horizontally */
box-sizing: border-box;
}
.a4page-landscape {
width: 100%;
/* fill mobile width */
height: fit-content;
margin: 0 auto;
/* center horizontally */
box-sizing: border-box;
}
}
@media (max-width: 600px) {
.a5page-portrait {
width: 100%;
height: fit-content;
margin: 0 auto;
box-sizing: border-box;
}
.a5page-landscape {
width: 100%;
height: fit-content;
margin: 0 auto;
box-sizing: border-box;
}
}
.tl {
@apply absolute top-0 left-0;
}
.tr {
@apply absolute top-0 right-0;
}
.bl {
@apply absolute bottom-0 left-0;
}
.br {
@apply absolute bottom-0 right-0;
}
.background {
@apply fixed;
}
.halftone {
--dot_size: 1px;
--bg_size: 3px;
--bg_pos: calc(var(--bg_size) / 2);
--blur: 0%;
background-color: var(--bg_secondary);
background-image: radial-gradient(circle at center,
var(--bg_primary) var(--dot_size),
transparent var(--blur));
background-size: var(--bg_size) var(--bg_size);
background-position: 0 0;
}

View File

@@ -0,0 +1,3 @@
<template>
<footer></footer>
</template>

Some files were not shown because too many files have changed in this diff Show More