diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..e95158ac
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,33 @@
+name: Code Quality
+
+on:
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches:
+ - main
+
+env:
+ PUBLIC_SUPABASE_URL: ${{ vars.PUBLIC_SUPABASE_URL || 'https://your-supabase-url.supabase.co' }}
+ PUBLIC_SUPABASE_PUBLISHABLE_KEY: ${{ vars.PUBLIC_SUPABASE_PUBLISHABLE_KEY || 'your-supabase-publishable-key' }}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v4
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+ - name: Install Node.js
+ uses: actions/setup-node@v5
+ with:
+ cache: pnpm
+ cache-dependency-path: pnpm-lock.yaml
+ node-version: 24
+ - name: Install Dependencies
+ run: pnpm install
+ - name: Check Formatters
+ run: pnpm fmt
+ - name: Run All Lints in Parallel
+ run: pnpm lint
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index d28bbe35..a828771c 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -2,9 +2,9 @@ name: Deploy to GitHub Pages
on:
workflow_dispatch:
- pull_request:
push:
- branches: main
+ branches:
+ - main
permissions:
contents: read
@@ -15,6 +15,10 @@ concurrency:
group: pages
cancel-in-progress: false
+env:
+ PUBLIC_SUPABASE_URL: ${{ vars.PUBLIC_SUPABASE_URL || 'https://your-supabase-url.supabase.co' }}
+ PUBLIC_SUPABASE_PUBLISHABLE_KEY: ${{ vars.PUBLIC_SUPABASE_PUBLISHABLE_KEY || 'your-supabase-publishable-key' }}
+
jobs:
build:
runs-on: ubuntu-latest
@@ -31,10 +35,6 @@ jobs:
node-version: 24
- name: Install Dependencies
run: pnpm install
- - name: Check Formatters
- run: pnpm fmt
- - name: Run All Lints in Parallel
- run: pnpm lint
- name: Build Website
run: pnpm build
- name: Setup Pages
diff --git a/.gitignore b/.gitignore
index 307132b5..6e6fc58b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,6 @@
.eslintcache
node_modules
build
-*.sh
\ No newline at end of file
+*.sh
+.env
+.env.*
\ No newline at end of file
diff --git a/package.json b/package.json
index edc76eb2..6546b3d5 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"@iconify/icons-heroicons": "^1.2.9",
"@iconify/icons-simple-icons": "^1.2.74",
"@iconify/svelte": "^5.0.2",
+ "@supabase/supabase-js": "^2.100.1",
"@sveltejs/kit": "^2.47.3",
"html-minifier": "^4.0.0",
"svelte": "^5.41.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 33e8b53d..e7ff21ae 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,6 +17,9 @@ importers:
'@iconify/svelte':
specifier: ^5.0.2
version: 5.0.2(svelte@5.41.4)
+ '@supabase/supabase-js':
+ specifier: ^2.100.1
+ version: 2.100.1
'@sveltejs/kit':
specifier: ^2.47.3
version: 2.47.3(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.41.4)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.36.0)))(svelte@5.41.4)(vite@7.1.12(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.36.0))
@@ -649,6 +652,33 @@ packages:
'@standard-schema/spec@1.0.0':
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
+ '@supabase/auth-js@2.100.1':
+ resolution: {integrity: sha512-c5FB4nrG7cs1mLSzFGuIVl2iR2YO5XkSJ96uF4zubYm8YDn71XOi2emE9sBm/avfGCj61jaRBLOvxEAVnpys0Q==}
+ engines: {node: '>=20.0.0'}
+
+ '@supabase/functions-js@2.100.1':
+ resolution: {integrity: sha512-mo8QheoV4KR+wSubtyEWhZUxWnCM7YZ23TncccMAlbWAHb8YTDqRGRm9IalWCAswniKyud6buZCk9snRqI86KA==}
+ engines: {node: '>=20.0.0'}
+
+ '@supabase/phoenix@0.4.0':
+ resolution: {integrity: sha512-RHSx8bHS02xwfHdAbX5Lpbo6PXbgyf7lTaXTlwtFDPwOIw64NnVRwFAXGojHhjtVYI+PEPNSWwkL90f4agN3bw==}
+
+ '@supabase/postgrest-js@2.100.1':
+ resolution: {integrity: sha512-OIh4mOSo2LdqF2kox76OAPDtcSs+PwKABJOjc6plUV4/LXhFEsI2uwdEEIs7K7fd141qehWEVl/Y+Ts0fNvYsw==}
+ engines: {node: '>=20.0.0'}
+
+ '@supabase/realtime-js@2.100.1':
+ resolution: {integrity: sha512-FHuRWPX4qZQ4x+0Q+ZrKaBZnOiVGiwsgiAUJM98pYRib1yeaE/fOM1lZ1ozd+4gA8Udw23OyaD8SxKS5mT5NYw==}
+ engines: {node: '>=20.0.0'}
+
+ '@supabase/storage-js@2.100.1':
+ resolution: {integrity: sha512-x9xpEIoWM4xKiAlwfWTgHPSN6N4Y0aS4FVU4F6ZPbq7Gayw08SrtC6/YH/gOr8CjXQr0HxXYXDop2xGTSjubYA==}
+ engines: {node: '>=20.0.0'}
+
+ '@supabase/supabase-js@2.100.1':
+ resolution: {integrity: sha512-CAeFm5sfX8sbTzxoxRafhohreIzl9a7R6qHTck3MrgTqm5M5g/u0IHfEKYzI9w/17r8NINl8UZrw2i08wrO7Iw==}
+ engines: {node: '>=20.0.0'}
+
'@sveltejs/acorn-typescript@1.0.6':
resolution: {integrity: sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==}
peerDependencies:
@@ -818,6 +848,9 @@ packages:
'@types/uglify-js@3.17.5':
resolution: {integrity: sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==}
+ '@types/ws@8.18.1':
+ resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
+
'@typescript-eslint/eslint-plugin@8.46.2':
resolution: {integrity: sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1160,6 +1193,10 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ iceberg-js@0.8.1:
+ resolution: {integrity: sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==}
+ engines: {node: '>=20.0.0'}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -1746,6 +1783,18 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ ws@8.20.0:
+ resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
yaml@1.10.2:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
@@ -2186,6 +2235,46 @@ snapshots:
'@standard-schema/spec@1.0.0': {}
+ '@supabase/auth-js@2.100.1':
+ dependencies:
+ tslib: 2.8.1
+
+ '@supabase/functions-js@2.100.1':
+ dependencies:
+ tslib: 2.8.1
+
+ '@supabase/phoenix@0.4.0': {}
+
+ '@supabase/postgrest-js@2.100.1':
+ dependencies:
+ tslib: 2.8.1
+
+ '@supabase/realtime-js@2.100.1':
+ dependencies:
+ '@supabase/phoenix': 0.4.0
+ '@types/ws': 8.18.1
+ tslib: 2.8.1
+ ws: 8.20.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ '@supabase/storage-js@2.100.1':
+ dependencies:
+ iceberg-js: 0.8.1
+ tslib: 2.8.1
+
+ '@supabase/supabase-js@2.100.1':
+ dependencies:
+ '@supabase/auth-js': 2.100.1
+ '@supabase/functions-js': 2.100.1
+ '@supabase/postgrest-js': 2.100.1
+ '@supabase/realtime-js': 2.100.1
+ '@supabase/storage-js': 2.100.1
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
'@sveltejs/acorn-typescript@1.0.6(acorn@8.15.0)':
dependencies:
acorn: 8.15.0
@@ -2352,6 +2441,10 @@ snapshots:
dependencies:
source-map: 0.6.1
+ '@types/ws@8.18.1':
+ dependencies:
+ '@types/node': 24.9.1
+
'@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
@@ -2751,6 +2844,8 @@ snapshots:
relateurl: 0.2.7
uglify-js: 3.19.3
+ iceberg-js@0.8.1: {}
+
ignore@5.3.2: {}
ignore@7.0.5: {}
@@ -3162,8 +3257,7 @@ snapshots:
dependencies:
typescript: 5.9.3
- tslib@2.8.1:
- optional: true
+ tslib@2.8.1: {}
type-check@0.4.0:
dependencies:
@@ -3231,6 +3325,8 @@ snapshots:
word-wrap@1.2.5: {}
+ ws@8.20.0: {}
+
yaml@1.10.2: {}
yocto-queue@0.1.0: {}
diff --git a/src/lib/components/cards/MemberCard.svelte b/src/lib/components/cards/MemberCard.svelte
index 30e44a23..0241583d 100644
--- a/src/lib/components/cards/MemberCard.svelte
+++ b/src/lib/components/cards/MemberCard.svelte
@@ -1,20 +1,25 @@
@@ -26,7 +31,7 @@
onmouseleave={() => (isOverlayVisible = false)}
>
-
{name}
- {#if title} + {#if titles}- {title.join(', ')} + {titles.join(', ')}
{/if}