Compare commits

..

4 Commits

Author SHA1 Message Date
616f93ccf4 set theme 2025-12-26 00:31:54 +01:00
9e73f5b781 Updated favicon 2025-12-23 23:32:24 +01:00
d92ce1c259 Add deployment automation and update documentation 2025-12-23 22:53:15 +01:00
1afd8637eb Configure static site generation with adapter-static 2025-12-23 22:50:10 +01:00
10 changed files with 190 additions and 57 deletions

View File

@@ -1,38 +1,76 @@
# sv
# jnss-web
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
Static website for jnss.me - built with SvelteKit and deployed via Caddy.
## Creating a project
## Project Structure
If you're seeing this, you've probably already done this step. Congrats!
This project uses a **two-branch deployment strategy**:
- **`main` branch**: Source code and development
- Contains all source files, configuration, and build tooling
- `build/` directory is gitignored
- **`deploy` branch**: Orphan branch with build outputs only
- Contains only the static build artifacts (index.html, _app/, etc.)
- No source code or build dependencies
- Used by Ansible/Caddy for serving the site
## Development
Install dependencies:
```sh
# create a new project in the current directory
npx sv create
# create a new project in my-app
npx sv create my-app
bun install
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
Start development server:
```sh
npm run dev
bun run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
# or open in browser automatically
bun run dev -- --open
```
## Building
To create a production version of your app:
Build the static site:
```sh
npm run build
bun run build
```
You can preview the production build with `npm run preview`.
Preview the production build locally:
```sh
bun run preview
```
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
## Deployment
This project uses an automated deployment script that builds and pushes to the `deploy` branch:
```sh
# Deploy with auto-generated timestamp commit message
./deploy.sh
# Deploy with custom commit message
./deploy.sh "Add new feature X"
```
**What the script does:**
1. Builds the site on the `main` branch (`bun run build`)
2. Switches to the `deploy` branch
3. Clears old build files
4. Moves new build output to the root of `deploy` branch
5. Commits and pushes to `origin/deploy`
6. Switches back to `main` branch
**For rick-infra:**
The Ansible role clones the `deploy` branch to get production-ready static files:
```sh
git clone -b deploy git@jnss.me:joakim/jnss-web.git
```
## Tech Stack
- **Framework**: SvelteKit 2.x with static adapter
- **Build Tool**: Vite 7.x
- **Package Manager**: Bun
- **Deployment**: Two-branch strategy (main → source, deploy → build artifacts)
- **Hosting**: Caddy (configured via rick-infra)

View File

@@ -7,6 +7,7 @@
"devDependencies": {
"@poppanator/sveltekit-svg": "^6.0.1",
"@sveltejs/adapter-auto": "^7.0.0",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.49.1",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
"svelte": "^5.45.6",
@@ -135,6 +136,8 @@
"@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@7.0.0", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-ImDWaErTOCkRS4Gt+5gZuymKFBobnhChXUZ9lhUZLahUgvA4OOvRzi3sahzYgbxGj5nkA6OV0GAW378+dl/gyw=="],
"@sveltejs/adapter-static": ["@sveltejs/adapter-static@3.0.10", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew=="],
"@sveltejs/kit": ["@sveltejs/kit@2.49.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ=="],
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.1", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ=="],

59
deploy.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# deploy.sh - Build and deploy to orphan deploy branch
# Usage: ./deploy.sh [commit-message]
set -e
COMMIT_MSG="${1:-Deploy: $(date +'%Y-%m-%d %H:%M:%S')}"
echo "📦 Building site on main branch..."
bun run build
if [ ! -d "build" ]; then
echo "❌ Build failed - build directory not found"
exit 1
fi
echo "✅ Build successful"
echo ""
echo "🔄 Switching to deploy branch..."
git checkout deploy
echo "🧹 Cleaning deploy branch (keeping .git and .gitignore)..."
# Remove all tracked files except .gitignore
git ls-files | grep -v "^\.gitignore$" | xargs -r git rm -f
# Remove any untracked files/directories except build/, node_modules/, and .svelte-kit/
find . -mindepth 1 -maxdepth 1 ! -name 'build' ! -name 'node_modules' ! -name '.svelte-kit' ! -name '.git' ! -name '.gitignore' -exec rm -rf {} +
echo "📋 Copying build output to root..."
if [ -d "build" ]; then
mv build/* .
rm -rf build/
echo "✅ Build files copied to deploy branch root"
else
echo "⚠️ No build directory found (this is expected on deploy branch)"
fi
echo "📝 Staging changes..."
git add -A
# Check if there are any changes to commit
if git diff --staged --quiet; then
echo " No changes to deploy"
git checkout main
exit 0
fi
echo "💾 Committing build artifacts..."
git commit -m "$COMMIT_MSG"
echo "🚀 Pushing to origin/deploy..."
git push origin deploy
echo "✅ Switching back to main..."
git checkout main
echo ""
echo "✨ Deployment complete!"
echo " Deploy branch commit: $(git rev-parse --short deploy)"
echo " Main branch commit: $(git rev-parse --short main)"

View File

@@ -14,6 +14,7 @@
"devDependencies": {
"@poppanator/sveltekit-svg": "^6.0.1",
"@sveltejs/adapter-auto": "^7.0.0",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.49.1",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
"svelte": "^5.45.6",

View File

@@ -1,7 +1,6 @@
:root {
--text-color-primary: black;
--border-radius: 8px;
--border-color: black;
--border-color: var(--color-secondary);
--border-size: 2px;
--spacing30: 0.5rem;
@@ -10,6 +9,26 @@
--spacing60: 1.25rem;
--spacing70: 1.5rem;
--color-base-100: oklch(24.353% 0 0);
--color-base-200: oklch(22.648% 0 0);
--color-base-300: oklch(20.944% 0 0);
--color-base-content: oklch(84.87% 0 0);
--color-primary: oklch(41.703% 0.099 251.473);
--color-primary-content: oklch(88.34% 0.019 251.473);
--color-secondary: oklch(64.092% 0.027 229.389);
--color-secondary-content: oklch(12.818% 0.005 229.389);
--color-accent: oklch(67.271% 0.167 35.791);
--color-accent-content: oklch(13.454% 0.033 35.791);
--color-neutral: oklch(27.441% 0.013 253.041);
--color-neutral-content: oklch(85.488% 0.002 253.041);
--color-info: oklch(62.616% 0.143 240.033);
--color-info-content: oklch(12.523% 0.028 240.033);
--color-success: oklch(70.226% 0.094 156.596);
--color-success-content: oklch(14.045% 0.018 156.596);
--color-warning: oklch(77.482% 0.115 81.519);
--color-warning-content: oklch(15.496% 0.023 81.519);
--color-error: oklch(51.61% 0.146 29.674);
--color-error-content: oklch(90.322% 0.029 29.674);
}
*,

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill="#d16b6b" d="M576 304.2L576 320L64 320C64 300 74 281.3 90.6 270.2L338.9 104.7C347.5 99 357.5 96 367.8 96C482.8 96 576 189.2 576 304.2zM576 368L576 480C576 515.3 547.3 544 512 544L128 544C92.7 544 64 515.3 64 480L64 368L576 368z"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 462 B

View File

@@ -5,7 +5,7 @@
import Metrics from "$lib/assets/chart.svg?component";
</script>
<div >
<div>
<a href="https://cloud.jnss.me"><Cloud /><span>Cloud</span></a>
<a href="https://git.jnss.me"><GitBranch /><span>Git</span></a>
<a href="https://vault.jnss.me"><Vault /><span>Vault</span></a>
@@ -16,9 +16,10 @@
div {
--card-size: 150px;
container-type: inline-size;
display: flex;
flex-wrap: wrap;
justify-content: center;
justify-content: space-between;
gap: var(--spacing50);
a {
@@ -32,14 +33,19 @@
width: var(--card-size);
height: var(--card-size);
color: var(--text-color-primary);
background-color: var(--color-base-300);
color: var(--color-secondary);
border: var(--border-size) solid var(--border-color);
border-radius: var(--border-radius);
span {
font-size: 1.25rem;
color: var(--color-base-content);
}
}
@media (width < 515px) {
justify-content: center;
}
}
</style>

1
src/routes/+layout.js Normal file
View File

@@ -0,0 +1 @@
export const prerender = true;

View File

@@ -1,12 +1,12 @@
<script>
import favicon from "$lib/assets/favicon.svg";
import css from "../app.css";
import faviconUrl from "$lib/assets/favicon.svg?url";
import "../app.css";
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
<link rel="icon" href={faviconUrl} />
</svelte:head>
<div class="left"></div>
@@ -22,6 +22,8 @@
grid-template-columns:
minmax(var(--spacing50), auto) minmax(auto, 800px)
minmax(var(--spacing50), auto);
color: var(--color-base-content);
background-color: var(--color-base-100);
}
}
</style>

View File

@@ -1,12 +1,16 @@
import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-static';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
adapter: adapter({
// Default options for static adapter
pages: 'build',
assets: 'build',
fallback: undefined,
precompress: false,
strict: true
})
}
};