From f71b054ae5dd8b6bc490670793c039a489611ae1 Mon Sep 17 00:00:00 2001 From: Luke Else Date: Thu, 25 Sep 2025 22:03:37 +0100 Subject: [PATCH 1/4] feat: Added dev-container --- .devcontainer/devcontainer.json | 18 +++ .dockerignore | 36 ++--- .gitea/workflows/dev.yaml | 60 ++++---- .gitea/workflows/main.yaml | 60 ++++---- .gitignore | 23 +-- .npmrc | 8 +- .prettierignore | 26 ++-- .prettierrc | 20 +-- README.md | 112 +++++++------- dockerfile | 42 ++--- src/app.d.ts | 24 +-- src/app.html | 62 ++++---- src/lib/api/git.ts | 132 ++++++++-------- src/lib/data.ts | 8 +- src/lib/stores.ts | 22 +-- src/lib/types.ts | 44 +++--- src/main.svelte | 170 ++++++++++----------- src/routes/+layout.svelte | 56 +++---- src/routes/+page.svelte | 12 +- src/routes/contact/+page.svelte | 206 ++++++++++++------------- src/routes/repos/+page.svelte | 146 +++++++++--------- static/json/me.json | 262 ++++++++++++++++---------------- svelte.config.js | 20 +-- tsconfig.json | 36 ++--- vite.config.ts | 20 +-- 25 files changed, 822 insertions(+), 803 deletions(-) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..4cb50d4 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,18 @@ +{ + "name": "luke-else.co.uk", + "image": "git.luke-else.co.uk/luke-else/lab:latest", + "remoteUser": "dev", + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "zsh" + }, + "extensions": [ + "ms-azuretools.vscode-docker", + "ms-vscode-remote.remote-containers", + "svelte.svelte-vscode" + ] + } + }, + "postCreateCommand": "pnpm install && pnpm run dev" +} \ No newline at end of file diff --git a/.dockerignore b/.dockerignore index e4ee886..11ec1e7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,19 +1,19 @@ -# .dockerignore - -.vscode - -node_modules - -.git -.gitattributes -.gitea - -.eslintignore -.eslintrc.cjs - -.prettierrc -.pretieriignore - -README.md - +# .dockerignore + +.vscode + +node_modules + +.git +.gitattributes +.gitea + +.eslintignore +.eslintrc.cjs + +.prettierrc +.pretieriignore + +README.md + Dockerfile \ No newline at end of file diff --git a/.gitea/workflows/dev.yaml b/.gitea/workflows/dev.yaml index 4b9b6ff..17a7e2b 100644 --- a/.gitea/workflows/dev.yaml +++ b/.gitea/workflows/dev.yaml @@ -1,30 +1,30 @@ -name: Build and Push Development Docker Image - -on: - push: - branches: [ development ] - -jobs: - build-and-push: - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - registry: ${{ secrets.CONTAINER_REGISTRY }} - username: ${{ secrets.CONTAINER_REGISTRY_USERNAME }} - password: ${{ secrets.CONTAINER_REGISTRY_PASSKEY }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and Tag Docker Image - run: | - docker build -t ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:dev . - - - name: Push Docker Image - run: | - docker push ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:dev +name: Build and Push Development Docker Image + +on: + push: + branches: [ development ] + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + registry: ${{ secrets.CONTAINER_REGISTRY }} + username: ${{ secrets.CONTAINER_REGISTRY_USERNAME }} + password: ${{ secrets.CONTAINER_REGISTRY_PASSKEY }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and Tag Docker Image + run: | + docker build -t ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:dev . + + - name: Push Docker Image + run: | + docker push ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:dev diff --git a/.gitea/workflows/main.yaml b/.gitea/workflows/main.yaml index dd41a9c..fa910d7 100644 --- a/.gitea/workflows/main.yaml +++ b/.gitea/workflows/main.yaml @@ -1,30 +1,30 @@ -name: Build and Push Latest Docker Image - -on: - push: - branches: [ main ] - -jobs: - build-and-push: - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - registry: ${{ secrets.CONTAINER_REGISTRY }} - username: ${{ secrets.CONTAINER_REGISTRY_USERNAME }} - password: ${{ secrets.CONTAINER_REGISTRY_PASSKEY }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and Tag Docker Image - run: | - docker build -t ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:latest . - - - name: Push Docker Image - run: | - docker push ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:latest +name: Build and Push Latest Docker Image + +on: + push: + branches: [ main ] + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + registry: ${{ secrets.CONTAINER_REGISTRY }} + username: ${{ secrets.CONTAINER_REGISTRY_USERNAME }} + password: ${{ secrets.CONTAINER_REGISTRY_PASSKEY }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and Tag Docker Image + run: | + docker build -t ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:latest . + + - name: Push Docker Image + run: | + docker push ${{ secrets.CONTAINER_REGISTRY }}/${{ secrets.CONTAINER_REGISTRY_USERNAME }}/luke-else.co.uk:latest diff --git a/.gitignore b/.gitignore index ee1f68a..c577545 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,12 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example -vite.config.js.timestamp-* -vite.config.ts.timestamp-* -.vscode +.DS_Store +node_modules +.pnpm-store +/build +/.svelte-kit +/package +.env +.env.* +!.env.example +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +.vscode diff --git a/.npmrc b/.npmrc index 9edd2b9..037a8cf 100644 --- a/.npmrc +++ b/.npmrc @@ -1,4 +1,4 @@ -engine-strict=true -resolution-mode=highest - -@luke-else:registry=https://git.luke-else.co.uk/api/packages/luke-else/npm/ +engine-strict=true +resolution-mode=highest + +@luke-else:registry=https://git.luke-else.co.uk/api/packages/luke-else/npm/ diff --git a/.prettierignore b/.prettierignore index 3897265..dbc521a 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,13 +1,13 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/.prettierrc b/.prettierrc index d8bcc7b..417fe58 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,10 +1,10 @@ -{ - "useTabs": false, - "tabWidth": 4, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100, - "plugins": ["prettier-plugin-svelte"], - "pluginSearchDirs": ["."], - "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] -} +{ + "useTabs": false, + "tabWidth": 4, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte"], + "pluginSearchDirs": ["."], + "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] +} diff --git a/README.md b/README.md index 3b5ddc9..691a27c 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,56 @@ -## Welcome - -This site contains information relating to my personal situation, however, you are able to clone this project and change the `me.json` file to update this as required. - -## Screenshots - -

- - -

- -

- - - -

- -

- -

- -## Getting Started - -Get starting but installing all of the dependencies of the project. - -```bash -npm install - -``` - -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: - -```bash -npm run dev - -``` - -```bash -# or start the server and open the app in a new browser tab -npm run dev -- --open - -``` - -## Building - -To create a production version of the app: - -```bash -npm run build - - -``` - -You can preview the production build with `npm run preview`. - -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. In this case, vite is used. +## Welcome + +This site contains information relating to my personal situation, however, you are able to clone this project and change the `me.json` file to update this as required. + +## Screenshots + +

+ + +

+ +

+ + + +

+ +

+ +

+ +## Getting Started + +Get starting but installing all of the dependencies of the project. + +```bash +npm install + +``` + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: + +```bash +npm run dev + +``` + +```bash +# or start the server and open the app in a new browser tab +npm run dev -- --open + +``` + +## Building + +To create a production version of the app: + +```bash +npm run build + + +``` + +You can preview the production build with `npm run preview`. + +> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. In this case, vite is used. diff --git a/dockerfile b/dockerfile index abc2178..dc4cec7 100644 --- a/dockerfile +++ b/dockerfile @@ -1,21 +1,21 @@ -FROM git.luke-else.co.uk/luke-else/nodejs:latest AS build - -WORKDIR /app - -COPY package*.json ./ -RUN rm -rf node_modules -RUN rm -rf build -COPY . . -RUN pnpm install -RUN pnpm run build - -FROM git.luke-else.co.uk/luke-else/nodejs:latest AS run - -WORKDIR /app -COPY --from=build /app/package.json ./package.json -COPY --from=build /app/.npmrc ./.npmrc -COPY --from=build /app/build ./build -RUN pnpm install --prod - -EXPOSE 3000 -ENTRYPOINT [ "pnpm", "run", "start" ] +FROM git.luke-else.co.uk/luke-else/nodejs:latest AS build + +WORKDIR /app + +COPY package*.json ./ +RUN rm -rf node_modules +RUN rm -rf build +COPY . . +RUN pnpm install +RUN pnpm run build + +FROM git.luke-else.co.uk/luke-else/nodejs:latest AS run + +WORKDIR /app +COPY --from=build /app/package.json ./package.json +COPY --from=build /app/.npmrc ./.npmrc +COPY --from=build /app/build ./build +RUN pnpm install --prod + +EXPOSE 3000 +ENTRYPOINT [ "pnpm", "run", "start" ] diff --git a/src/app.d.ts b/src/app.d.ts index f59b884..381a357 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,12 +1,12 @@ -// See https://kit.svelte.dev/docs/types#app -// for information about these interfaces -declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface Platform {} - } -} - -export {}; +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface Platform {} + } +} + +export {}; diff --git a/src/app.html b/src/app.html index 8a81f56..935ffbd 100644 --- a/src/app.html +++ b/src/app.html @@ -1,31 +1,31 @@ - - - - - - - - - - - %sveltekit.head% - - - - - -
%sveltekit.body%
- - + + + + + + + + + + + %sveltekit.head% + + + + + +
%sveltekit.body%
+ + diff --git a/src/lib/api/git.ts b/src/lib/api/git.ts index 57627a1..fe8869f 100644 --- a/src/lib/api/git.ts +++ b/src/lib/api/git.ts @@ -1,67 +1,67 @@ -import type { GitRepo } from "../types"; - -const API_BASE_URL = "https://git.luke-else.co.uk/api/v1"; -export const IMAGE_URL_SUFFIX = "/raw/branch/main/assets/images/main.png"; - - -export async function fetchRepos(): Promise { - try { - console.log("Fetching repos..."); - const response = await fetch(`${API_BASE_URL}/repos/search?sort=updated&order=desc&limit=12`, { - headers: { - // "Authorization": `token ${ACCESS_TOKEN}`, - "Content-Type": "application/json" - } - }); - - if (!response.ok) { - throw new Error(`Error: ${response.statusText}`); - } - - const data: { data: GitRepo[] } = await response.json(); - return data.data; // Extract the list of repositories - } catch (error) { - console.error("Failed to fetch repos:", error); - return []; - } -} - -export function timeSince(inputDate: Date | string): string { - const date = new Date(inputDate); // Ensure it's a Date object - if (isNaN(date.getTime())) { - throw new Error("Invalid date provided"); - } - - const now: Date = new Date(); - const diffInMs: number = now.getTime() - date.getTime(); - const diffInSeconds: number = Math.floor(diffInMs / 1000); - const diffInMinutes: number = Math.floor(diffInSeconds / 60); - const diffInHours: number = Math.floor(diffInMinutes / 60); - const diffInDays: number = Math.floor(diffInHours / 24); - const diffInMonths: number = Math.floor(diffInDays / 30); // Approximate - const diffInYears: number = Math.floor(diffInDays / 365); // Approximate - - if (diffInDays === 0) return "Today"; - if (diffInDays === 1) return "Yesterday"; - if (diffInDays < 7) return `${diffInDays} days ago`; - if (diffInDays < 30) return `${Math.floor(diffInDays / 7)} week${diffInDays >= 14 ? 's' : ''} ago`; - if (diffInMonths < 12) return `${diffInMonths} month${diffInMonths > 1 ? 's' : ''} ago`; - return `${diffInYears} year${diffInYears > 1 ? 's' : ''} ago`; -} - -export async function checkImage(repo: GitRepo): Promise { - try { - const URL = repo.html_url + IMAGE_URL_SUFFIX; - console.log("Checking image:", URL); - const response = await fetch(URL); - if (response.ok) { - console.log("Image found!"); - return true; - } else { - console.log("Image not found!"); - return false; - } - } catch (error) { - return false; - } +import type { GitRepo } from "../types"; + +const API_BASE_URL = "https://git.luke-else.co.uk/api/v1"; +export const IMAGE_URL_SUFFIX = "/raw/branch/main/assets/images/main.png"; + + +export async function fetchRepos(): Promise { + try { + console.log("Fetching repos..."); + const response = await fetch(`${API_BASE_URL}/repos/search?sort=updated&order=desc&limit=12`, { + headers: { + // "Authorization": `token ${ACCESS_TOKEN}`, + "Content-Type": "application/json" + } + }); + + if (!response.ok) { + throw new Error(`Error: ${response.statusText}`); + } + + const data: { data: GitRepo[] } = await response.json(); + return data.data; // Extract the list of repositories + } catch (error) { + console.error("Failed to fetch repos:", error); + return []; + } +} + +export function timeSince(inputDate: Date | string): string { + const date = new Date(inputDate); // Ensure it's a Date object + if (isNaN(date.getTime())) { + throw new Error("Invalid date provided"); + } + + const now: Date = new Date(); + const diffInMs: number = now.getTime() - date.getTime(); + const diffInSeconds: number = Math.floor(diffInMs / 1000); + const diffInMinutes: number = Math.floor(diffInSeconds / 60); + const diffInHours: number = Math.floor(diffInMinutes / 60); + const diffInDays: number = Math.floor(diffInHours / 24); + const diffInMonths: number = Math.floor(diffInDays / 30); // Approximate + const diffInYears: number = Math.floor(diffInDays / 365); // Approximate + + if (diffInDays === 0) return "Today"; + if (diffInDays === 1) return "Yesterday"; + if (diffInDays < 7) return `${diffInDays} days ago`; + if (diffInDays < 30) return `${Math.floor(diffInDays / 7)} week${diffInDays >= 14 ? 's' : ''} ago`; + if (diffInMonths < 12) return `${diffInMonths} month${diffInMonths > 1 ? 's' : ''} ago`; + return `${diffInYears} year${diffInYears > 1 ? 's' : ''} ago`; +} + +export async function checkImage(repo: GitRepo): Promise { + try { + const URL = repo.html_url + IMAGE_URL_SUFFIX; + console.log("Checking image:", URL); + const response = await fetch(URL); + if (response.ok) { + console.log("Image found!"); + return true; + } else { + console.log("Image not found!"); + return false; + } + } catch (error) { + return false; + } } \ No newline at end of file diff --git a/src/lib/data.ts b/src/lib/data.ts index 38ef0c9..16f763e 100644 --- a/src/lib/data.ts +++ b/src/lib/data.ts @@ -1,5 +1,5 @@ -export async function getJson(path: string) { - let response = await fetch(path); - let users = await response.json(); - return users; +export async function getJson(path: string) { + let response = await fetch(path); + let users = await response.json(); + return users; } \ No newline at end of file diff --git a/src/lib/stores.ts b/src/lib/stores.ts index c0888fb..f6400dc 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -1,12 +1,12 @@ -import { writable } from "svelte/store"; -import type { GitRepo } from "./types"; -import { fetchRepos } from "./api/git"; - -//////////////////////////////////////// -// Git Repo Stores -//////////////////////////////////////// -export const repos = writable([]); - -export async function loadRepos() { - repos.set(await fetchRepos()); +import { writable } from "svelte/store"; +import type { GitRepo } from "./types"; +import { fetchRepos } from "./api/git"; + +//////////////////////////////////////// +// Git Repo Stores +//////////////////////////////////////// +export const repos = writable([]); + +export async function loadRepos() { + repos.set(await fetchRepos()); } \ No newline at end of file diff --git a/src/lib/types.ts b/src/lib/types.ts index 92a7c3c..4a9e4f0 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,22 +1,22 @@ -export type TimelinePosition = 'right' | 'left' | 'alternate'; - -export type ParentPosition = 'right' | 'left'; - -export type TimelineConfig = { - rootPosition: TimelinePosition; -}; - -export interface GitRepo { - name: string; - description: string; - language: string; - size: number; - updated_at: Date; - html_url: string; - private: boolean; - fork: boolean; - owner: { - login: string; - avatar_url: string; - }; -} +export type TimelinePosition = 'right' | 'left' | 'alternate'; + +export type ParentPosition = 'right' | 'left'; + +export type TimelineConfig = { + rootPosition: TimelinePosition; +}; + +export interface GitRepo { + name: string; + description: string; + language: string; + size: number; + updated_at: Date; + html_url: string; + private: boolean; + fork: boolean; + owner: { + login: string; + avatar_url: string; + }; +} diff --git a/src/main.svelte b/src/main.svelte index 1051bca..226f833 100644 --- a/src/main.svelte +++ b/src/main.svelte @@ -1,85 +1,85 @@ - - -{#await getJson('/json/me.json')} - -{:then info} -
- {toasts.add({ - title: 'Welcome', - duration: 5000, - type: 'success', - placement: 'bottom-center', - showProgress: true - })} -
- - -
- -

{info.name}

-

{info.job_title}

-
- Avatar -

- {@html info.about} -

-
-

{@html info.location}

-
-
- - -
- - {#each info.skills as skill} - -

{skill.name}

- -
- - About {skill.name} - {skill.about} - - -
-

{skill.link}

-
- {/each} -
-
- -
- -
-{:catch} -
- {toasts.add({ - title: 'Error', - description: 'There was an error loading static site data', - duration: 0, - placement: 'bottom-center', - showProgress: true - })} -
-{/await} + + +{#await getJson('/json/me.json')} + +{:then info} +
+ {toasts.add({ + title: 'Welcome', + duration: 5000, + type: 'success', + placement: 'bottom-center', + showProgress: true + })} +
+ + +
+ +

{info.name}

+

{info.job_title}

+
+ Avatar +

+ {@html info.about} +

+
+

{@html info.location}

+
+
+ + +
+ + {#each info.skills as skill} + +

{skill.name}

+ +
+ + About {skill.name} + {skill.about} + + +
+

{skill.link}

+
+ {/each} +
+
+ +
+ +
+{:catch} +
+ {toasts.add({ + title: 'Error', + description: 'There was an error loading static site data', + duration: 0, + placement: 'bottom-center', + showProgress: true + })} +
+{/await} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 4c42fe0..fa617c4 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,28 +1,28 @@ - - -
- - - - - - -
- - - - -
-
+ + +
+ + + + + + +
+ + + + +
+
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3194ecf..5c33e27 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,7 +1,7 @@ - - -
-
+ + +
+
\ No newline at end of file diff --git a/src/routes/contact/+page.svelte b/src/routes/contact/+page.svelte index 2327030..ef41935 100644 --- a/src/routes/contact/+page.svelte +++ b/src/routes/contact/+page.svelte @@ -1,103 +1,103 @@ - - -
-
- -
- -
- Contact Me -
- -
- -
-
- - -
-
- - -
-
- - -
-
-
- - -
- -
-
- -
- -
-
-
+ + +
+
+ +
+ +
+ Contact Me +
+ +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+ +
+
+ +
+ +
+
+
diff --git a/src/routes/repos/+page.svelte b/src/routes/repos/+page.svelte index 6fba91a..5582d24 100644 --- a/src/routes/repos/+page.svelte +++ b/src/routes/repos/+page.svelte @@ -1,73 +1,73 @@ - -
- {#await loadRepos()} - - {:then _} - {#if $repos.length == 0} - {console.log('No Repos')} -
- {toasts.add({ - title: 'Error', - description: 'Failed to load repositories', - duration: 5000, - type: 'error', - placement: 'bottom-center', - showProgress: true - })} -
-

Sorry... we can't show you anything here

- {/if} - - - {#each $repos as repo} - - -

{repo.name}

-

- {repo.language} -

-
- {repo.description} - {#if repoImages[repo.name]} - - See More - - repo image - - {/if} -
-

- Last Updated: {timeSince(repo.updated_at)} -

-
- {/each} -
- {/await} -
+ +
+ {#await loadRepos()} + + {:then _} + {#if $repos.length == 0} + {console.log('No Repos')} +
+ {toasts.add({ + title: 'Error', + description: 'Failed to load repositories', + duration: 5000, + type: 'error', + placement: 'bottom-center', + showProgress: true + })} +
+

Sorry... we can't show you anything here

+ {/if} + + + {#each $repos as repo} + + +

{repo.name}

+

+ {repo.language} +

+
+ {repo.description} + {#if repoImages[repo.name]} + + See More + + repo image + + {/if} +
+

+ Last Updated: {timeSince(repo.updated_at)} +

+
+ {/each} +
+ {/await} +
diff --git a/static/json/me.json b/static/json/me.json index d7bee24..4732a54 100644 --- a/static/json/me.json +++ b/static/json/me.json @@ -1,132 +1,132 @@ -{ - "name": "Luke Else", - "job_title": "Software Engineer", - "location": "Crawley, Sussex
UK", - "profile_photo": "/profile.jpg", - "about": "Hello! I'm an enthusiastic, dedicated software engineer passionate about backend development, networking, and embedded systems. I am currently employed at Thales UK and thrive on architecting robust backend solutions, optimizing data transmission, and crafting efficient embedded software. I love tackling complex challenges, collaborating with fellow professionals, and staying up-to-date with tech trends such as my current venture in learning Rust-Lang.", - "skills": [ - { - "name": "Rust", - "logo": "devicon-rust-plain", - "colour": "bg-orange-400", - "link": "https://rust-lang.org", - "about": "Rust combines safety, efficiency, and clean code, making it a powerful choice for reliable software development.", - "competency": 70 - }, - { - "name": "C++", - "logo": "devicon-cplusplus-plain", - "colour": "bg-blue-400", - "link": "https://cplusplus.com/", - "about": "C++ offers high-level abstractions with low-level control, making it essential for performance-critical applications.", - "competency": 80 - }, - { - "name" : "Python", - "logo": "devicon-python-plain", - "colour": "bg-yellow-400", - "link": "https://python.org", - "about": "Python is a versatile language known for its simplicity and readability, making it ideal for rapid development and data analysis.", - "competency": 70 - }, - { - "name": "Git", - "logo": "devicon-git-plain", - "colour": "bg-red-400", - "link": "https://git-scm.com", - "about": "Git is an essential tool for version control, enabling efficient collaboration and streamlined code management.", - "competency": 80 - }, - { - "name": "Docker", - "logo": "devicon-docker-plain", - "colour": "bg-blue-500", - "link": "https://docker.com", - "about": "Docker simplifies deployment by packaging applications in lightweight containers, ensuring consistency across environments.", - "competency": 100 - }, - { - "name": "Kubernetes", - "logo": "devicon-kubernetes-plain", - "colour": "bg-blue-600", - "link": "https://kubernetes.io", - "about": "Kubernetes automates the deployment, scaling, and management of containerized applications, enhancing operational efficiency.", - "competency": 40 - }, - { - "name": "PostgreSQL", - "logo": "devicon-postgresql-plain", - "colour": "bg-blue-700", - "link": "https://postgresql.org", - "about": "PostgreSQL is a powerful, open-source relational database known for its robustness and advanced features.", - "competency": 70 - }, - { - "name": "MongoDB", - "logo": "devicon-mongodb-plain", - "colour": "bg-green-500", - "link": "https://mongodb.com", - "about": "MongoDB is a NoSQL database that provides flexibility and scalability for modern applications with unstructured data.", - "competency": 70 - }, - { - "name": "Redis", - "logo": "devicon-redis-plain", - "colour": "bg-red-600", - "link": "https://redis.io", - "about": "Redis is an in-memory data structure store, used as a database, cache, and message broker for high-performance applications.", - "competency": 30 - }, - { - "name": "JavaScript", - "logo": "devicon-javascript-plain", - "colour": "bg-yellow-500", - "link": "https://javascript.com", - "about": "JavaScript is a versatile language that powers dynamic web applications and enhances user interactivity.", - "competency": 60 - }, - { - "name": "Tailwind CSS", - "logo": "devicon-tailwindcss-plain", - "colour": "bg-blue-800", - "link": "https://tailwindcss.com/", - "about": "Tailwind CSS is a utility-first CSS framework that enables rapid UI development with a focus on customization and responsiveness.", - "competency": 60 - }, - { - "name": "Svelte", - "logo": "devicon-svelte-plain", - "colour": "bg-orange-400", - "link": "https://svelte.dev", - "about": "Svelte compiles to optimized JavaScript, offering a fast, efficient, and maintainable front-end development experience.", - "competency": 55 - } - ], - "timeline" : [ - { - "duration" : "April 2025 - Present", - "title" : "Thales UK (DDCC) - Software Engineer", - "description" : "As a 3rd year apprentice at Thales UK’s Digital Data Competency Centre, I have taken on responsibility for developing microservices that encapsulate Machine Learning models provided by R&D teams, helping to advance product readiness. These services are primarily written in Python and deployed to Kubernetes clusters for use across the business. Our team also designs and maintains CI/CD pipelines to automate the deployment of both these services and their supporting infrastructure." - }, - { - "duration" : "September 2022 - April 2025", - "title" : "Thales UK (ISR) - Software Engineer", - "description" : "As a software engineering apprentice at Thales UK, Intelligence Surveillance and Reconnaissance, I worked within an agile team of six engineers, contributing to the ongoing development of a C++ system for the MOD. My role involved collaborating closely with colleagues, following Scrum methodologies, and leveraging internal frameworks to enhance and maintain the existing platform." - }, - { - "duration" : "September 2022 - Present", - "title" : "University of Warwick - Digital and Technology Solutions", - "description" : "The apprenticeship includes allocated time for studying a Digital and Thechnology Solutions degree with the University of Warwick, including modules relevant to business management, devlopment processes and data integrity etc..." - }, - { - "duration" : "September 2020 - July 2022", - "title" : "The Norton Knatchbull School (A-Levels)", - "description" : "Computer Science (A*)
Mathematics (A)
Physics (A)" - }, - { - "duration" : "September 2015 - July 2020", - "title" : "The Norton Knatchbull School (GCSEs)", - "description" : "Computer Science (9)
Physics (9)
Chemistry (9)
Biology (9)
Geography (9)
FSMQ (C)
Maths (8)
Spanish (7)
English (Literature & Language) (7, 7)
" - } - ] +{ + "name": "Luke Else", + "job_title": "Software Engineer", + "location": "Crawley, Sussex
UK", + "profile_photo": "/profile.jpg", + "about": "Hello! I'm an enthusiastic, dedicated software engineer passionate about backend development, networking, and embedded systems. I am currently employed at Thales UK and thrive on architecting robust backend solutions, optimizing data transmission, and crafting efficient embedded software. I love tackling complex challenges, collaborating with fellow professionals, and staying up-to-date with tech trends such as my current venture in learning Rust-Lang.", + "skills": [ + { + "name": "Rust", + "logo": "devicon-rust-plain", + "colour": "bg-orange-400", + "link": "https://rust-lang.org", + "about": "Rust combines safety, efficiency, and clean code, making it a powerful choice for reliable software development.", + "competency": 70 + }, + { + "name": "C++", + "logo": "devicon-cplusplus-plain", + "colour": "bg-blue-400", + "link": "https://cplusplus.com/", + "about": "C++ offers high-level abstractions with low-level control, making it essential for performance-critical applications.", + "competency": 80 + }, + { + "name" : "Python", + "logo": "devicon-python-plain", + "colour": "bg-yellow-400", + "link": "https://python.org", + "about": "Python is a versatile language known for its simplicity and readability, making it ideal for rapid development and data analysis.", + "competency": 70 + }, + { + "name": "Git", + "logo": "devicon-git-plain", + "colour": "bg-red-400", + "link": "https://git-scm.com", + "about": "Git is an essential tool for version control, enabling efficient collaboration and streamlined code management.", + "competency": 80 + }, + { + "name": "Docker", + "logo": "devicon-docker-plain", + "colour": "bg-blue-500", + "link": "https://docker.com", + "about": "Docker simplifies deployment by packaging applications in lightweight containers, ensuring consistency across environments.", + "competency": 100 + }, + { + "name": "Kubernetes", + "logo": "devicon-kubernetes-plain", + "colour": "bg-blue-600", + "link": "https://kubernetes.io", + "about": "Kubernetes automates the deployment, scaling, and management of containerized applications, enhancing operational efficiency.", + "competency": 40 + }, + { + "name": "PostgreSQL", + "logo": "devicon-postgresql-plain", + "colour": "bg-blue-700", + "link": "https://postgresql.org", + "about": "PostgreSQL is a powerful, open-source relational database known for its robustness and advanced features.", + "competency": 70 + }, + { + "name": "MongoDB", + "logo": "devicon-mongodb-plain", + "colour": "bg-green-500", + "link": "https://mongodb.com", + "about": "MongoDB is a NoSQL database that provides flexibility and scalability for modern applications with unstructured data.", + "competency": 70 + }, + { + "name": "Redis", + "logo": "devicon-redis-plain", + "colour": "bg-red-600", + "link": "https://redis.io", + "about": "Redis is an in-memory data structure store, used as a database, cache, and message broker for high-performance applications.", + "competency": 30 + }, + { + "name": "JavaScript", + "logo": "devicon-javascript-plain", + "colour": "bg-yellow-500", + "link": "https://javascript.com", + "about": "JavaScript is a versatile language that powers dynamic web applications and enhances user interactivity.", + "competency": 60 + }, + { + "name": "Tailwind CSS", + "logo": "devicon-tailwindcss-plain", + "colour": "bg-blue-800", + "link": "https://tailwindcss.com/", + "about": "Tailwind CSS is a utility-first CSS framework that enables rapid UI development with a focus on customization and responsiveness.", + "competency": 60 + }, + { + "name": "Svelte", + "logo": "devicon-svelte-plain", + "colour": "bg-orange-400", + "link": "https://svelte.dev", + "about": "Svelte compiles to optimized JavaScript, offering a fast, efficient, and maintainable front-end development experience.", + "competency": 55 + } + ], + "timeline" : [ + { + "duration" : "April 2025 - Present", + "title" : "Thales UK (DDCC) - Software Engineer", + "description" : "As a 3rd year apprentice at Thales UK’s Digital Data Competency Centre, I have taken on responsibility for developing microservices that encapsulate Machine Learning models provided by R&D teams, helping to advance product readiness. These services are primarily written in Python and deployed to Kubernetes clusters for use across the business. Our team also designs and maintains CI/CD pipelines to automate the deployment of both these services and their supporting infrastructure." + }, + { + "duration" : "September 2022 - April 2025", + "title" : "Thales UK (ISR) - Software Engineer", + "description" : "As a software engineering apprentice at Thales UK, Intelligence Surveillance and Reconnaissance, I worked within an agile team of six engineers, contributing to the ongoing development of a C++ system for the MOD. My role involved collaborating closely with colleagues, following Scrum methodologies, and leveraging internal frameworks to enhance and maintain the existing platform." + }, + { + "duration" : "September 2022 - Present", + "title" : "University of Warwick - Digital and Technology Solutions", + "description" : "The apprenticeship includes allocated time for studying a Digital and Thechnology Solutions degree with the University of Warwick, including modules relevant to business management, devlopment processes and data integrity etc..." + }, + { + "duration" : "September 2020 - July 2022", + "title" : "The Norton Knatchbull School (A-Levels)", + "description" : "Computer Science (A*)
Mathematics (A)
Physics (A)" + }, + { + "duration" : "September 2015 - July 2020", + "title" : "The Norton Knatchbull School (GCSEs)", + "description" : "Computer Science (9)
Physics (9)
Chemistry (9)
Biology (9)
Geography (9)
FSMQ (C)
Maths (8)
Spanish (7)
English (Literature & Language) (7, 7)
" + } + ] } \ No newline at end of file diff --git a/svelte.config.js b/svelte.config.js index 8f0f7a7..7e35e08 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,10 +1,10 @@ -// import adapter from '@sveltejs/adapter-auto'; -import adapter from '@sveltejs/adapter-node'; -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; - -const config = { - preprocess: vitePreprocess(), - kit: { adapter: adapter() } -}; - -export default config; +// import adapter from '@sveltejs/adapter-auto'; +import adapter from '@sveltejs/adapter-node'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +const config = { + preprocess: vitePreprocess(), + kit: { adapter: adapter() } +}; + +export default config; diff --git a/tsconfig.json b/tsconfig.json index 82081ab..a2319c4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,18 @@ -{ - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "moduleResolution": "bundler" - } - // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias - // - // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes - // from the referenced tsconfig.json - TypeScript does not merge them in -} +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in +} diff --git a/vite.config.ts b/vite.config.ts index 26a5bad..8c7ce3e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,10 +1,10 @@ -import { sveltekit } from '@sveltejs/kit/vite'; -import { defineConfig } from 'vite'; -import tailwindcss from '@tailwindcss/vite'; - -export default defineConfig({ - plugins: [ - tailwindcss(), - sveltekit(), - ] -}); +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vite'; +import tailwindcss from '@tailwindcss/vite'; + +export default defineConfig({ + plugins: [ + tailwindcss(), + sveltekit(), + ] +}); From bc7099d62784ce5ce457fbd3cdc1bd3d7876fc2e Mon Sep 17 00:00:00 2001 From: Luke Else Date: Thu, 25 Sep 2025 23:13:39 +0100 Subject: [PATCH 2/4] chore: Updated comments --- src/main.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.svelte b/src/main.svelte index 226f833..553e58e 100644 --- a/src/main.svelte +++ b/src/main.svelte @@ -47,7 +47,7 @@ - +
{#each info.skills as skill} @@ -69,6 +69,7 @@
+
From 558bca7f5658eb9dfe65283a8c59b3bddfacb19c Mon Sep 17 00:00:00 2001 From: Luke Else Date: Thu, 25 Sep 2025 23:29:30 +0100 Subject: [PATCH 3/4] fix: Linting --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4cb50d4..480d7cf 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,5 +14,5 @@ ] } }, - "postCreateCommand": "pnpm install && pnpm run dev" + "postCreateCommand": "pnpm install && pnpm run dev" } \ No newline at end of file From 9a36a46ad1e9891acc3bf8ac97a9dbd901062354 Mon Sep 17 00:00:00 2001 From: Luke Else Date: Thu, 25 Sep 2025 23:34:11 +0100 Subject: [PATCH 4/4] chore: Removed run command from devcontainer --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 480d7cf..a9b3682 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,5 +14,5 @@ ] } }, - "postCreateCommand": "pnpm install && pnpm run dev" + "postCreateCommand": "pnpm install" } \ No newline at end of file