Compare commits

..

No commits in common. "main" and "v1.3.75" have entirely different histories.

10 changed files with 52 additions and 128 deletions

View file

@ -22,30 +22,13 @@ $ pnpm i
## Commands ## Commands
| Command | Action | | Command | Action |
| ----------------------------- | ---------------------------------------------- | | ------------------- | ---------------------------------------------- |
| `pnpm run dev` | start dev server | | `pnpm run dev` | start dev server |
| `pnpm run build` | generate static files to `dist` directory | | `pnpm run build` | generate static files to `dist` directory |
| `pnpm run deploy` | upload to my server | | `pnpm run deploy` | upload to my server |
| `pnpm run prep:now` | back up and clear current `now page` constants | | `pnpm run prep:now` | back up and clear current `now page` constants |
| `pnpm run patch:build:deploy` | increment version, build, then upload | | `pnpm run patch:build:deploy` | increment version, build, then upload |
## Testing
This project uses Vitest for unit tests. The test script is defined in `package.json` as `vitest run .`.
Run tests locally with pnpm (recommended):
```bash
# install dependencies (if you haven't already)
pnpm i
# run tests once
pnpm test
# run Vitest in interactive/watch mode
pnpm exec vitest
```
## Deployment ## Deployment

View file

@ -1,7 +1,7 @@
{ {
"name": "@ayco/personal-website", "name": "@ayco/personal-website",
"type": "module", "type": "module",
"version": "1.3.88", "version": "1.3.75",
"private": true, "private": true,
"scripts": { "scripts": {
"astro": "astro", "astro": "astro",
@ -11,9 +11,8 @@
"preview": "astro preview", "preview": "astro preview",
"lint": "eslint . --config eslint.config.mjs --cache", "lint": "eslint . --config eslint.config.mjs --cache",
"lint:fix": "eslint . --config eslint.config.mjs --fix", "lint:fix": "eslint . --config eslint.config.mjs --fix",
"fmt": "prettier . --config prettier.config.mjs --check", "format": "prettier . --write",
"fmt:fix": "prettier . --config prettier.config.mjs --write", "check": "npm run format && npm run lint",
"check": "npm run fmt && npm run lint",
"deploy": "eval $(grep '^HOST' .env) && scp -r dist ayo@$HOST:~/ayco.io-flask", "deploy": "eval $(grep '^HOST' .env) && scp -r dist ayo@$HOST:~/ayco.io-flask",
"patch:build:deploy": "npm version patch && npm run build && npm run deploy", "patch:build:deploy": "npm version patch && npm run build && npm run deploy",
"pbd": "npm run patch:build:deploy", "pbd": "npm run patch:build:deploy",
@ -52,7 +51,6 @@
"rehype-stringify": "^10.0.1", "rehype-stringify": "^10.0.1",
"remark-parse": "^11.0.0", "remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2", "remark-rehype": "^11.1.2",
"sharp": "^0.34.5",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"typescript-eslint": "^8.59.3", "typescript-eslint": "^8.59.3",
@ -63,14 +61,14 @@
}, },
"lint-staged": { "lint-staged": {
"*.{js,mjs,astro,ts}": [ "*.{js,mjs,astro,ts}": [
"prettier . --config prettier.config.mjs --write", "prettier --write",
"eslint . --config eslint.config.mjs --fix" "eslint --fix"
], ],
"*.json": [ "*.json": [
"prettier . --config prettier.config.mjs --write" "prettier --write"
] ]
}, },
"packageManager": "pnpm@11.5.2+sha512.71c631e382066efc25625d5cf029075de07b61b37f6e27350fbd84b1bda5864c8c1967adc280776b45c30a715c0359a3be08fef42d5bb09e2b99029979692916", "packageManager": "pnpm@11.2.2",
"dependencies": { "dependencies": {
"@ayo-run/status-indicator": "^2.1.2", "@ayo-run/status-indicator": "^2.1.2",
"web-component-base": "^4.1.2" "web-component-base": "^4.1.2"

View file

@ -96,9 +96,6 @@ importers:
remark-rehype: remark-rehype:
specifier: ^11.1.2 specifier: ^11.1.2
version: 11.1.2 version: 11.1.2
sharp:
specifier: ^0.34.5
version: 0.34.5
tslib: tslib:
specifier: ^2.8.1 specifier: ^2.8.1
version: 2.8.1 version: 2.8.1
@ -3258,7 +3255,8 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@img/colour@1.1.0': {} '@img/colour@1.1.0':
optional: true
'@img/sharp-darwin-arm64@0.34.5': '@img/sharp-darwin-arm64@0.34.5':
optionalDependencies: optionalDependencies:
@ -4124,7 +4122,8 @@ snapshots:
destr@2.0.5: {} destr@2.0.5: {}
detect-libc@2.1.2: {} detect-libc@2.1.2:
optional: true
devalue@5.8.1: {} devalue@5.8.1: {}
@ -5776,6 +5775,7 @@ snapshots:
'@img/sharp-win32-arm64': 0.34.5 '@img/sharp-win32-arm64': 0.34.5
'@img/sharp-win32-ia32': 0.34.5 '@img/sharp-win32-ia32': 0.34.5
'@img/sharp-win32-x64': 0.34.5 '@img/sharp-win32-x64': 0.34.5
optional: true
shebang-command@2.0.0: shebang-command@2.0.0:
dependencies: dependencies:

View file

@ -57,7 +57,7 @@ export const footerLinks: Link[] = [
}, },
{ {
text: 'Mastodon', text: 'Mastodon',
url: 'https://elk.zone/m.webtoo.ls/@ayo', url: 'https://main.elk.zone/social.ayco.io/@ayo',
icon: 'mastodon', icon: 'mastodon',
}, },
{ {

View file

@ -15,7 +15,7 @@ import { getImage } from 'astro:assets'
// fetch mastodon account // fetch mastodon account
const response = await fetch( const response = await fetch(
'https://m.webtoo.ls/api/v1/accounts/lookup?acct=ayo' 'https://social.ayco.io/api/v1/accounts/lookup?acct=ayo'
) )
const data = await response.json() const data = await response.json()
const { avatar } = data const { avatar } = data
@ -51,28 +51,13 @@ const ogFileType = 'image/png'
font-size: var(--font-size-base); font-size: var(--font-size-base);
color: var(--text-color-dark); color: var(--text-color-dark);
background-color: var(--text-color-light); background-color: var(--text-color-light);
background-image: radial-gradient(
circle,
hsl(var(--dot-grid-light)) 1px,
transparent 1px
);
background-size: 24px 24px;
background-position: -24px -24px;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
html, html,
body, body,
* { * {
background-color: var(--bg-darker); background: var(--bg-darker);
color: var(--text-color-light); color: var(--text-color-light);
background-image: radial-gradient(
circle,
hsl(var(--dot-grid-dark)) 1px,
transparent 1px
);
} }
} }

View file

@ -26,7 +26,4 @@
--bg-dark: #343a40; --bg-dark: #343a40;
--bg-darker: #212529; --bg-darker: #212529;
--bg-darkest: #000; --bg-darkest: #000;
--dot-grid-light: 214 32% 82%;
--dot-grid-dark: 215 25% 25%;
} }

View file

@ -8,7 +8,7 @@ import { Picture } from 'astro:assets'
// fetch mastodon account // fetch mastodon account
const response = await fetch( const response = await fetch(
'https://m.webtoo.ls/api/v1/accounts/lookup?acct=ayo' 'https://social.ayco.io/api/v1/accounts/lookup?acct=ayo'
) )
const data = await response.json() const data = await response.json()
const { avatar, note } = data const { avatar, note } = data
@ -38,15 +38,13 @@ const avatarSize = 150
</h1> </h1>
<a href="/now" class="now-wrapper action primary"> <a href="/now" class="now-wrapper action primary">
<span class="now-label"> <span class="now-label">now</span>
<status-indicator status="active" pulse> now </status-indicator>
</span>
<span class="status">{now.title}</span> <span class="status">{now.title}</span>
</a> </a>
</div> </div>
</div> </div>
</section> </section>
<main class=".dot-grid"> <main>
<section class="introduction-section"> <section class="introduction-section">
<p> <p>
I care about the <em>Web</em>, and I love to <em>create</em> stuff to <em I care about the <em>Web</em>, and I love to <em>create</em> stuff to <em
@ -95,7 +93,6 @@ const avatarSize = 150
&.primary { &.primary {
border: 1px solid rgba(255, 255, 255, 0.2); border: 1px solid rgba(255, 255, 255, 0.2);
border-style: dotted;
border-radius: 40px; border-radius: 40px;
} }
} }

View file

@ -4,7 +4,7 @@ import Footer from '../components/Footer.astro'
const title = 'PGP public key' const title = 'PGP public key'
const description = const description =
'Use to verify my digital signature or to encrypt messages intended only for me.' 'Use to verify my digitally signed content like emails and files or to encrypt messages intended only for me.'
--- ---
<Layout title={"Ayo's " + title} description={description}> <Layout title={"Ayo's " + title} description={description}>
@ -13,12 +13,7 @@ const description =
<p>{description}</p> <p>{description}</p>
<div class="key-block" role="region" aria-labelledby="public-key"> <div class="key-block" role="region" aria-labelledby="public-key">
<div class="btn-wrapper"> <button class="copy-btn" aria-label="Copy key to clipboard">Copy</button>
<button class="copy-btn btn" aria-label="Copy key to clipboard"
>Copy</button
>
<a href="/publickey.asc" class="btn">Download</a>
</div>
<pre <pre
id="public-key"><code> id="public-key"><code>
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
@ -36,42 +31,32 @@ AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
</code></pre> </code></pre>
</div> </div>
<p>Expiry Date: 2027-05-30</p>
<p>
Fingerprint: <code>17F1 3D5E 8FF7 372B 1354 5C38 65E6 BF64 1529 3C65</code
>
</p>
<p></p> <p>
<a href="/publickey.asc" class="download-link"> Download key (asc) </a>
</p>
<p>This key will expire on: 2027-05-30</p>
</main> </main>
<Footer /> <Footer />
</Layout> </Layout>
<script> <script>
/* Clipboard copy logic */ /* Clipboard copy logic */
const copyBtn = document.querySelector('.copy-btn') document.querySelector('.copy-btn').addEventListener('click', async () => {
if (copyBtn) { const keyText = document.querySelector('#public-key code').innerText.trim()
copyBtn.addEventListener('click', async () => { try {
const keyText = ( await navigator.clipboard.writeText(keyText)
document.querySelector('#public-key code') as HTMLElement const btn = document.querySelector('.copy-btn')
)?.innerText.trim() const original = btn.textContent
if (!keyText) return btn.textContent = 'Copied!'
try { setTimeout(() => {
await navigator.clipboard.writeText(keyText) btn.textContent = original
const btn = document.querySelector('.copy-btn') }, 2000)
if (btn) { } catch (err) {
const original = btn.textContent console.error('Copy failed', err)
btn.textContent = 'Copied!' alert('Unable to copy the key. Please copy it manually.')
setTimeout(() => { }
btn.textContent = original })
}, 2000)
}
} catch (err) {
console.error('Copy failed', err)
alert('Unable to copy the key. Please copy it manually.')
}
})
}
</script> </script>
<style> <style>
@ -98,16 +83,11 @@ AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
display: block; display: block;
} }
/* buttons */ /* Copy button */
.btn-wrapper { .copy-btn {
position: absolute; position: absolute;
top: 0.5rem; top: 0.5rem;
right: 0.5rem; right: 0.5rem;
}
.btn {
display: inline-block;
position: relative;
background: var(--color-brand-blue-1); background: var(--color-brand-blue-1);
color: #fff; color: #fff;
border: none; border: none;
@ -117,15 +97,14 @@ AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
cursor: pointer; cursor: pointer;
opacity: 0.9; opacity: 0.9;
transition: opacity 0.2s; transition: opacity 0.2s;
text-decoration: none;
} }
.btn:hover, .copy-btn:hover,
.btn:focus { .copy-btn:focus {
opacity: 1; opacity: 1;
} }
.btn:focus { .copy-btn:focus {
outline: 2px solid #0056b3; outline: 2px solid #0056b3;
outline-offset: 2px; outline-offset: 2px;
} }

View file

@ -11,8 +11,7 @@ import Card from '../components/Card.astro'
<main> <main>
<h1><span class="text-gradient">Hobby Projects</span></h1> <h1><span class="text-gradient">Hobby Projects</span></h1>
<p> <p>
See more of my previous projects at <a href="https://ayos.blog/projects" See more of my previous projects at <a href="https://ayos.blog">my blog</a
>my blog</a
>. >.
</p> </p>
<ul> <ul>

View file

@ -1,14 +0,0 @@
import { defineConfig } from 'vitest/config'
// Exclude generated files and heavy folders from the watcher to avoid
// continuous re-runs when build output or other tools touch files.
export default defineConfig({
test: {
globals: true,
environment: 'node',
exclude: ['dist/**', 'public/**', 'node_modules/**'],
},
watch: {
exclude: ['dist/**', 'public/**', 'node_modules/**', '.git/**'],
},
})