Compare commits
No commits in common. "main" and "v1.3.74" have entirely different histories.
15 changed files with 64 additions and 239 deletions
31
README.md
31
README.md
|
|
@ -22,30 +22,13 @@ $ pnpm i
|
|||
|
||||
## Commands
|
||||
|
||||
| Command | Action |
|
||||
| ----------------------------- | ---------------------------------------------- |
|
||||
| `pnpm run dev` | start dev server |
|
||||
| `pnpm run build` | generate static files to `dist` directory |
|
||||
| `pnpm run deploy` | upload to my server |
|
||||
| `pnpm run prep:now` | back up and clear current `now page` constants |
|
||||
| `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
|
||||
```
|
||||
| Command | Action |
|
||||
| ------------------- | ---------------------------------------------- |
|
||||
| `pnpm run dev` | start dev server |
|
||||
| `pnpm run build` | generate static files to `dist` directory |
|
||||
| `pnpm run deploy` | upload to my server |
|
||||
| `pnpm run prep:now` | back up and clear current `now page` constants |
|
||||
| `pnpm run patch:build:deploy` | increment version, build, then upload |
|
||||
|
||||
## Deployment
|
||||
|
||||
|
|
|
|||
16
package.json
16
package.json
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@ayco/personal-website",
|
||||
"type": "module",
|
||||
"version": "1.3.95",
|
||||
"version": "1.3.74",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"astro": "astro",
|
||||
|
|
@ -11,9 +11,8 @@
|
|||
"preview": "astro preview",
|
||||
"lint": "eslint . --config eslint.config.mjs --cache",
|
||||
"lint:fix": "eslint . --config eslint.config.mjs --fix",
|
||||
"fmt": "prettier . --config prettier.config.mjs --check",
|
||||
"fmt:fix": "prettier . --config prettier.config.mjs --write",
|
||||
"check": "npm run fmt && npm run lint",
|
||||
"format": "prettier . --write",
|
||||
"check": "npm run format && npm run lint",
|
||||
"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",
|
||||
"pbd": "npm run patch:build:deploy",
|
||||
|
|
@ -52,7 +51,6 @@
|
|||
"rehype-stringify": "^10.0.1",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.1.2",
|
||||
"sharp": "^0.34.5",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.3",
|
||||
|
|
@ -63,14 +61,14 @@
|
|||
},
|
||||
"lint-staged": {
|
||||
"*.{js,mjs,astro,ts}": [
|
||||
"prettier . --config prettier.config.mjs --write",
|
||||
"eslint . --config eslint.config.mjs --fix"
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
],
|
||||
"*.json": [
|
||||
"prettier . --config prettier.config.mjs --write"
|
||||
"prettier --write"
|
||||
]
|
||||
},
|
||||
"packageManager": "pnpm@11.5.2+sha512.71c631e382066efc25625d5cf029075de07b61b37f6e27350fbd84b1bda5864c8c1967adc280776b45c30a715c0359a3be08fef42d5bb09e2b99029979692916",
|
||||
"packageManager": "pnpm@11.2.2",
|
||||
"dependencies": {
|
||||
"@ayo-run/status-indicator": "^2.1.2",
|
||||
"web-component-base": "^4.1.2"
|
||||
|
|
|
|||
|
|
@ -96,9 +96,6 @@ importers:
|
|||
remark-rehype:
|
||||
specifier: ^11.1.2
|
||||
version: 11.1.2
|
||||
sharp:
|
||||
specifier: ^0.34.5
|
||||
version: 0.34.5
|
||||
tslib:
|
||||
specifier: ^2.8.1
|
||||
version: 2.8.1
|
||||
|
|
@ -3258,7 +3255,8 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@img/colour@1.1.0': {}
|
||||
'@img/colour@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-darwin-arm64@0.34.5':
|
||||
optionalDependencies:
|
||||
|
|
@ -4124,7 +4122,8 @@ snapshots:
|
|||
|
||||
destr@2.0.5: {}
|
||||
|
||||
detect-libc@2.1.2: {}
|
||||
detect-libc@2.1.2:
|
||||
optional: true
|
||||
|
||||
devalue@5.8.1: {}
|
||||
|
||||
|
|
@ -5776,6 +5775,7 @@ snapshots:
|
|||
'@img/sharp-win32-arm64': 0.34.5
|
||||
'@img/sharp-win32-ia32': 0.34.5
|
||||
'@img/sharp-win32-x64': 0.34.5
|
||||
optional: true
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"title": "Social Web & Web Components",
|
||||
"description": "Getting into discussions about improving the social web & building components",
|
||||
"publishDate": "2026-05-12",
|
||||
"publishedOn": "",
|
||||
"publishState": ""
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
I bought a pull-up bar, and in addition to a few barbells at home, I am starting to have a mini gym.
|
||||
|
||||
Super happy that I am getting healthier as I build my workout routines.
|
||||
|
||||
To keep my mind sharp, I find it helpful to have several hobby things I can get back to from time to time.
|
||||
|
||||
I am in a few discussions for exploring some things in the open social web. Details can come later as they become more concrete.
|
||||
|
||||
Soft launch of my own newsletter is up on the canary version of my blog: https://main.ayos.blog/subscribe -- because email is the first decentralized social platform. Let's explore that idea more in the coming months.
|
||||
|
||||
I'm also back on my webcomponents main arc, after some side quests in self-hosting & machine learning.
|
||||
|
||||
Links to come later. Cheers!
|
||||
|
|
@ -57,7 +57,7 @@ export const footerLinks: Link[] = [
|
|||
},
|
||||
{
|
||||
text: 'Mastodon',
|
||||
url: 'https://elk.zone/m.webtoo.ls/@ayo',
|
||||
url: 'https://main.elk.zone/social.ayco.io/@ayo',
|
||||
icon: 'mastodon',
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"title": "Fam++, Crypto, ~AI, OSS",
|
||||
"description": "Navigating changes in the family and the tech industry",
|
||||
"publishDate": "2026-06-18",
|
||||
"publishedOn": "the 18th of June 2026",
|
||||
"publishState": "in Amsterdam"
|
||||
"title": "Social Web & Web Components",
|
||||
"description": "Getting into discussions about improving the social web & building components",
|
||||
"publishDate": "2026-05-12",
|
||||
"publishedOn": "",
|
||||
"publishState": ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,13 @@
|
|||
## 2 vs 2 in the house
|
||||
I bought a pull-up bar, and in addition to a few barbells at home, I am starting to have a mini gym.
|
||||
|
||||
A new challenger is entering the game. It is safe to share now that we're expecting a new addition to the family: a baby girl is joining us later this year. I have been enjoying having a mini-me in the form of my lil kiddo, Kahel, and now it's time for Jen to have hers.
|
||||
Super happy that I am getting healthier as I build my workout routines.
|
||||
|
||||
## Cryptography
|
||||
To keep my mind sharp, I find it helpful to have several hobby things I can get back to from time to time.
|
||||
|
||||
The latest rabbit hole for my tech adventures is on [cryptography](https://elk.zone/m.webtoo.ls/@ayo@ayco.io/116667802537651710); particularly OpenPGP stuff and the implementation on signing & verifying emails. Check [my public key](/pgp) if you want to exchange encrypted messages :)
|
||||
I am in a few discussions for exploring some things in the open social web. Details can come later as they become more concrete.
|
||||
|
||||
Technically this key-pair cryptography can be applied to any data exchange, so I naturally have been ruminating on how we can bring this to the decentralized social web.
|
||||
Soft launch of my own newsletter is up on the canary version of my blog: https://main.ayos.blog/subscribe -- because email is the first decentralized social platform. Let's explore that idea more in the coming months.
|
||||
|
||||
## "AI"
|
||||
I'm also back on my webcomponents main arc, after some side quests in self-hosting & machine learning.
|
||||
|
||||
I disassembled the eGPU setup I have for experimenting with local LLM inference and built a new PC. It is now a dedicated 24/7 "AI" computer at home that powers my [Open WebUI](https://ai.ayo.run) service. Additionally it runs [hermes](https://hermes-agent.nousresearch.com/) which is a "totally safe private local agentic AI" architecture -- and I got to say, it is the most successful one I've tried yet with local AI stuff.
|
||||
|
||||
Where am I using this? I don't know yet. It's purely for understanding the "agentic" stuff
|
||||
|
||||
## Open source
|
||||
|
||||
- [Elk](https://elk.zone) - I try to help out reviewing PRs and will pick up coding work again
|
||||
- [Webtoo.ls](https://webtoo.ls) - I picked up administration work for this and have BIG dreams on bringing more Web ecosystem open source presence to the Fediverse
|
||||
- [others](https://git.ayo.run/ayo) - A lot of my other explorations are out in the open
|
||||
Links to come later. Cheers!
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { getImage } from 'astro:assets'
|
|||
|
||||
// fetch mastodon account
|
||||
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 { avatar } = data
|
||||
|
|
@ -51,28 +51,13 @@ const ogFileType = 'image/png'
|
|||
font-size: var(--font-size-base);
|
||||
color: var(--text-color-dark);
|
||||
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) {
|
||||
html,
|
||||
body,
|
||||
* {
|
||||
background-color: var(--bg-darker);
|
||||
background: var(--bg-darker);
|
||||
color: var(--text-color-light);
|
||||
|
||||
background-image: radial-gradient(
|
||||
circle,
|
||||
hsl(var(--dot-grid-dark)) 1px,
|
||||
transparent 1px
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,4 @@
|
|||
--bg-dark: #343a40;
|
||||
--bg-darker: #212529;
|
||||
--bg-darkest: #000;
|
||||
|
||||
--dot-grid-light: 214 32% 82%;
|
||||
--dot-grid-dark: 215 25% 25%;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Picture } from 'astro:assets'
|
|||
|
||||
// fetch mastodon account
|
||||
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 { avatar, note } = data
|
||||
|
|
@ -38,15 +38,13 @@ const avatarSize = 150
|
|||
</h1>
|
||||
|
||||
<a href="/now" class="now-wrapper action primary">
|
||||
<span class="now-label">
|
||||
<status-indicator status="active" pulse> now </status-indicator>
|
||||
</span>
|
||||
<span class="now-label">now</span>
|
||||
<span class="status">{now.title}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<main class=".dot-grid">
|
||||
<main>
|
||||
<section class="introduction-section">
|
||||
<p>
|
||||
I care about the <em>Web</em>, and I love to <em>create</em> stuff to <em
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
---
|
||||
import Layout from '../../../../layouts/Layout.astro'
|
||||
import Footer from '../../../../components/Footer.astro'
|
||||
|
||||
const title = `Social Web & Web Components`
|
||||
const description = `Getting into discussions about improving the social web & building components`
|
||||
let publishedOn = ``
|
||||
const publishDate = `2026-05-12`
|
||||
const publishState = ``
|
||||
const content = `<p>I bought a pull-up bar, and in addition to a few barbells at home, I am starting to have a mini gym.</p>
|
||||
<p>Super happy that I am getting healthier as I build my workout routines.</p>
|
||||
<p>To keep my mind sharp, I find it helpful to have several hobby things I can get back to from time to time.</p>
|
||||
<p>I am in a few discussions for exploring some things in the open social web. Details can come later as they become more concrete.</p>
|
||||
<p>Soft launch of my own newsletter is up on the canary version of my blog: https://main.ayos.blog/subscribe -- because email is the first decentralized social platform. Let's explore that idea more in the coming months.</p>
|
||||
<p>I'm also back on my webcomponents main arc, after some side quests in self-hosting & machine learning.</p>
|
||||
<p>Links to come later. Cheers!</p>`
|
||||
|
||||
publishedOn = publishedOn === '' ? publishDate : publishedOn
|
||||
---
|
||||
|
||||
<Layout title={title} description={description}>
|
||||
<main>
|
||||
<h1><span class="text-gradient">{title}</span></h1>
|
||||
<p>
|
||||
<small>
|
||||
Published on
|
||||
<time datetime={publishDate}>
|
||||
{publishedOn}
|
||||
</time>
|
||||
{publishState}
|
||||
</small>
|
||||
</p>
|
||||
|
||||
<Fragment set:html={content} />
|
||||
</main>
|
||||
<Footer />
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.text-gradient {
|
||||
font-weight: 900;
|
||||
background-image: var(--ayo-gradient);
|
||||
animation: pulse 4s ease-in-out infinite;
|
||||
background-size: 500% 500%;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-size: 100% 200%;
|
||||
background-position-y: 100%;
|
||||
border-radius: 0.4rem;
|
||||
}
|
||||
|
||||
.highlighted-content {
|
||||
margin: 1rem 0;
|
||||
background: #4f39fa;
|
||||
padding: 1rem;
|
||||
border-radius: 0.4rem;
|
||||
color: var(--color-bg);
|
||||
}
|
||||
|
||||
.highlighted-content code {
|
||||
font-size: var(--font-size-base);
|
||||
border: 0.1em solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
padding: 0.15em 0.25em;
|
||||
}
|
||||
|
||||
.link-card-grid {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,7 +4,7 @@ import Footer from '../components/Footer.astro'
|
|||
|
||||
const title = 'PGP public key'
|
||||
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'
|
||||
---
|
||||
|
||||
<Layout title={"Ayo's " + title} description={description}>
|
||||
|
|
@ -13,12 +13,7 @@ const description =
|
|||
<p>{description}</p>
|
||||
|
||||
<div class="key-block" role="region" aria-labelledby="public-key">
|
||||
<div class="btn-wrapper">
|
||||
<button class="copy-btn btn" aria-label="Copy key to clipboard"
|
||||
>Copy</button
|
||||
>
|
||||
<a href="/publickey.asc" class="btn">Download</a>
|
||||
</div>
|
||||
<button class="copy-btn" aria-label="Copy key to clipboard">Copy</button>
|
||||
<pre
|
||||
id="public-key"><code>
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
|
@ -36,42 +31,32 @@ AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
|
|||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
</code></pre>
|
||||
</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>
|
||||
<Footer />
|
||||
</Layout>
|
||||
|
||||
<script>
|
||||
/* Clipboard copy logic */
|
||||
const copyBtn = document.querySelector('.copy-btn')
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', async () => {
|
||||
const keyText = (
|
||||
document.querySelector('#public-key code') as HTMLElement
|
||||
)?.innerText.trim()
|
||||
if (!keyText) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(keyText)
|
||||
const btn = document.querySelector('.copy-btn')
|
||||
if (btn) {
|
||||
const original = btn.textContent
|
||||
btn.textContent = 'Copied!'
|
||||
setTimeout(() => {
|
||||
btn.textContent = original
|
||||
}, 2000)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Copy failed', err)
|
||||
alert('Unable to copy the key. Please copy it manually.')
|
||||
}
|
||||
})
|
||||
}
|
||||
document.querySelector('.copy-btn').addEventListener('click', async () => {
|
||||
const keyText = document.querySelector('#public-key code').innerText.trim()
|
||||
try {
|
||||
await navigator.clipboard.writeText(keyText)
|
||||
const btn = document.querySelector('.copy-btn')
|
||||
const original = btn.textContent
|
||||
btn.textContent = 'Copied!'
|
||||
setTimeout(() => {
|
||||
btn.textContent = original
|
||||
}, 2000)
|
||||
} catch (err) {
|
||||
console.error('Copy failed', err)
|
||||
alert('Unable to copy the key. Please copy it manually.')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
@ -98,16 +83,11 @@ AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
.btn-wrapper {
|
||||
/* Copy button */
|
||||
.copy-btn {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
background: var(--color-brand-blue-1);
|
||||
color: #fff;
|
||||
border: none;
|
||||
|
|
@ -117,15 +97,14 @@ AP0YLC768PFTBm9CM5T1BE0xjJ7s4dZSrVoI4n8RSe1nCA==
|
|||
cursor: pointer;
|
||||
opacity: 0.9;
|
||||
transition: opacity 0.2s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:hover,
|
||||
.btn:focus {
|
||||
.copy-btn:hover,
|
||||
.copy-btn:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
.copy-btn:focus {
|
||||
outline: 2px solid #0056b3;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ import Card from '../components/Card.astro'
|
|||
<main>
|
||||
<h1><span class="text-gradient">Hobby Projects</span></h1>
|
||||
<p>
|
||||
See more of my previous projects at <a href="https://ayos.blog/projects"
|
||||
>my blog</a
|
||||
See more of my previous projects at <a href="https://ayos.blog">my blog</a
|
||||
>.
|
||||
</p>
|
||||
<ul>
|
||||
|
|
|
|||
|
|
@ -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/**'],
|
||||
},
|
||||
})
|
||||
Loading…
Reference in a new issue