Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
38 changes: 38 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Release

on:
push:
tags:
- 'v*.*.*'

env:
IMAGE_NAME: frederikaulich

jobs:
retag:
name: Retag & push versioned image
runs-on: ubuntu-latest
steps:
- name: Set up doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DO_ACCESS_TOKEN }}

- name: Log in to DigitalOcean registry
run: doctl registry login --expiry-seconds 600

- name: Extract version from tag
id: meta
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"

- name: Pull latest image
run: docker pull ${{ secrets.DO_REGISTRY }}/${{ env.IMAGE_NAME }}:latest

- name: Retag with release version
run: |
docker tag \
${{ secrets.DO_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ secrets.DO_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}

- name: Push versioned image
run: docker push ${{ secrets.DO_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
.output/

node_modules/

README.md
17 changes: 17 additions & 0 deletions .release-it.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://unpkg.com/release-it/schema/release-it.json",
"git": {
"commitMessage": "Release v${version}",
"tagName": "v${version}",
"tagAnnotation": "Release v${version}",
"requireBranch": "main",
"push": true
},
"github": {
"release": true,
"releaseName": "v${version}"
},
"npm": {
"publish": false
}
}
104 changes: 56 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,75 +1,83 @@
# Nuxt Minimal Starter
# frederik.dev

Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
[![CI](https://github.com/Kiesen/website/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Kiesen/website/actions/workflows/ci.yml)

## Setup
Personal portfolio — blog, résumé, and playground. Built with Nuxt 4 and Vue 3, deployed on DigitalOcean via Docker.

Make sure to install dependencies:
## Features

```bash
# npm
npm install
- Animated particle-network hero with interactive 3D depth effect
- Sections: About, Experience, Skills, Projects, Contact
- **Spotify "Last Liked" widget** — live card showing the most recently liked track, linked directly to Spotify (see [setup](#spotify-widget) below)
- Dark / light theme toggle
- Fully static-export capable (`bun run generate`)

## Stack

# pnpm
pnpm install
| Layer | Choice |
| --------------- | ------------------------------- |
| Framework | Nuxt 4 (Vue 3, Vite, Nitro) |
| Language | TypeScript (strict) |
| Styling | Tailwind CSS |
| Package manager | Bun |
| Hosting | DigitalOcean (Docker) |
| Registry | DigitalOcean Container Registry |

# yarn
yarn install
## Getting started

# bun
```bash
bun install
bun run dev # http://localhost:3000
```

## Development Server

Start the development server on `http://localhost:3000`:
Other commands:

```bash
# npm
npm run dev

# pnpm
pnpm dev
bun run build # production build → .output/
bun run generate # static site → .output/public/
bun run preview # preview production build
bun run lint # ESLint + Prettier check
bun run lint:fix # auto-fix
```

# yarn
yarn dev
## Spotify widget

# bun
bun run dev
```
The "Last liked on Spotify" card calls `/api/spotify/last-liked` (a Nitro server route), which fetches your most recently saved track via the Spotify Web API. The response is cached server-side for one hour.

## Production
### One-time setup

Build the application for production:
1. Create an app at [developer.spotify.com](https://developer.spotify.com/dashboard) and note the **Client ID** and **Client Secret**.
2. Add `http://localhost:3000/api/spotify/callback` as a Redirect URI in the app settings.
3. Create a `.env` file (git-ignored) with:

```bash
# npm
npm run build
```env
NUXT_SPOTIFY_CLIENT_ID=
NUXT_SPOTIFY_CLIENT_SECRET=
NUXT_SPOTIFY_REDIRECT_URI=http://localhost:3000/api/spotify/callback
NUXT_SPOTIFY_AUTH_SECRET=any-random-string
NUXT_SPOTIFY_REFRESH_TOKEN= # filled in step 5
```

# pnpm
pnpm build
4. Start the dev server and open `http://localhost:3000/api/spotify/auth` — this redirects to Spotify's OAuth consent screen.
5. After granting access, the callback prints a refresh token to the terminal. Paste it into `NUXT_SPOTIFY_REFRESH_TOKEN`.

# yarn
yarn build
In production set the same env vars on your server (or as DigitalOcean App Platform env vars), using your live domain as the redirect URI.

# bun
bun run build
```
## Release flow

Locally preview production build:
Releases are managed with [release-it](https://github.com/release-it/release-it).

```bash
# npm
npm run preview
GITHUB_TOKEN=ghp_xxx bun run release
```

# pnpm
pnpm preview
This will interactively bump the version, commit, create an annotated git tag, push everything to `main`, and open a GitHub Release. Pushing the tag then triggers the [release pipeline](.github/workflows/release.yml) which retags the existing `:latest` Docker image with the semver version — no rebuild needed.

# yarn
yarn preview
## CI / CD

# bun
bun run preview
```
| Workflow | Trigger | What it does |
| -------------------------------------------- | -------------------- | ------------------------------------------- |
| [ci.yml](.github/workflows/ci.yml) | push / PR → `main` | lint, build, Docker build & push `:latest` |
| [release.yml](.github/workflows/release.yml) | push of `v*.*.*` tag | pulls `:latest`, retags as `vX.Y.Z`, pushes |

Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
Required repository secrets: `DO_ACCESS_TOKEN`, `DO_REGISTRY`.
Loading
Loading