Compare commits

..

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

18 changed files with 1500 additions and 1670 deletions

View file

@ -1,2 +0,0 @@
# replace with correct IP, and rename the file to .env
HOST=123.456.789.00

1
.gitignore vendored
View file

@ -2,7 +2,6 @@
dist/
.output/
.astro/
.continue/
# dependencies
node_modules/

View file

@ -10,7 +10,7 @@ You need [node](https://nodejs.org) and [pnpm](https://pnpm.io).
```bash
# clone project
$ git clone https://git.ayo.run/ayo/ayco.io-astro
$ git clone git@git.sr.ht:~ayoayco/ayco.io-astro
# go into project dir
$ cd ./ayco.io-astro
@ -26,25 +26,16 @@ $ pnpm i
| ------------------- | ---------------------------------------------- |
| `pnpm run dev` | start dev server |
| `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 |
## Deployment
For the script `npm run deploy`, you need to add an environmental variable named HOST containing the IP address of the host server. This will scp the build files into the server.
For the script `npm run deploy`, you need to add an environmental variable named HOST containing the IP address of the host server. This will scp the build files into the server.
You can do this by adding a `.env` file with the following content (replace the IP):
If you want to run build before deploying, do `npm run build:deploy`
```bash
# .env
HOST=123.456.789.00
```
-----
There is a service worker (`src/sw.mjs`) that caches assets on client browsers. For cache invalidation, the version property in package.json is used. Increment the version via `npm version patch` (or `minor`, `major`) if there is a significant change in the website's assets.
If you want to run build before deploying, do `npm run build:deploy`
---
_Just keep building._<br />
_~Ayo_
*Just keep building.*<br />
*~Ayo*

View file

@ -1,9 +1,9 @@
---
import { Code } from 'astro:components'
import { Image } from 'astro:assets'
import Footer from '../../components/Footer.astro'
import Layout from '../../layouts/Layout.astro'
import importedCode from '../../../public/following_accounts.csv?raw'
import Footer from '../components/Footer.astro'
import Layout from '../layouts/Layout.astro'
import importedCode from '../../public/following_accounts.csv?raw'
const csvToArray = (content: string) => {
return content

View file

@ -1,7 +1,7 @@
{
"name": "@ayco/personal-website",
"type": "module",
"version": "1.3.31",
"version": "1.2.0",
"private": true,
"scripts": {
"astro": "astro",
@ -12,8 +12,7 @@
"lint": "eslint . --config eslint.config.mjs --cache",
"format": "prettier . --write",
"check": "npm run format && npm run lint",
"predeploy": "npm version patch && npm run build",
"deploy": "npm run predeploy && 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",
"build:preview": "npm run build && astro preview",
"build:deploy": "npm run build && npm run deploy",
"copy:dist": "npm run build && cp -R dist ../ayco.io-flask/",
@ -23,35 +22,35 @@
"devDependencies": {
"@astro-reactive/form": "^0.10.1",
"@astro-reactive/validator": "^0.5.1",
"@astrojs/sitemap": "^3.7.0",
"@astrojs/sitemap": "^3.4.2",
"@ayco/astro-sw": "^0.8.14",
"@eslint/compat": "^2.0.1",
"@eslint/js": "^9.39.2",
"@eslint/compat": "^1.3.1",
"@eslint/js": "^9.32.0",
"@iconify-json/mdi": "^1.2.3",
"@iconify-json/simple-icons": "^1.2.67",
"@iconify-json/tabler": "^1.2.26",
"@typescript-eslint/parser": "^8.53.1",
"astro": "^5.16.15",
"@iconify-json/simple-icons": "^1.2.45",
"@iconify-json/tabler": "^1.2.20",
"@typescript-eslint/parser": "^8.38.0",
"astro": "^5.12.8",
"astro-eslint-parser": "^1.2.2",
"astro-github-stats": "^0.8.0",
"astro-icon": "^1.1.5",
"consola": "^3.4.2",
"eslint": "^9.39.2",
"eslint-plugin-astro": "^1.5.0",
"eslint": "^9.32.0",
"eslint-plugin-astro": "^1.3.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"globals": "^17.1.0",
"globals": "^16.3.0",
"husky": "^9.1.7",
"jiti": "^2.6.1",
"lint-staged": "^16.2.7",
"jiti": "^2.5.1",
"lint-staged": "^16.1.2",
"pathe": "^2.0.3",
"prettier": "^3.8.1",
"prettier": "^3.6.2",
"prettier-plugin-astro": "^0.14.1",
"rehype-stringify": "^10.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2",
"tslib": "^2.8.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.53.1",
"typescript": "^5.9.2",
"typescript-eslint": "^8.38.0",
"unified": "^11.0.5"
},
"lint-staged": {

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 KiB

BIN
public/ayo-cartoon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

View file

@ -8,7 +8,8 @@ jay.bsky.team@bsky.brid.gy, true, false,
b0rk.jvns.ca@bsky.brid.gy, true, false,
seldo.com@bsky.brid.gy, true, false,
nerdy.dev@bsky.brid.gy, true, false,
samuel.fm@bsky.brid.gy, true, false,
wongmjane.com@bsky.brid.gy, true, false,
samuel.bsky.team@bsky.brid.gy, true, false,
laurenshof.online@bsky.brid.gy, true, false,
bell.bz@bsky.brid.gy, true, false,
matrix.org@bsky.brid.gy, true, false,
@ -28,9 +29,10 @@ jacobhands.com@bsky.brid.gy, true, false,
malstrom.me@bsky.brid.gy, true, false,
shuuji3.xyz@bsky.brid.gy, true, false,
intenttoship.dev@bsky.brid.gy, true, false,
haoqun.dev@bsky.brid.gy, true, false,
element.io@bsky.brid.gy, true, false,
e18e.dev@bsky.brid.gy, true, false,
danabra.mov@bsky.brid.gy, true, false,
heydonworks.com@bsky.brid.gy, true, false,
heydonworks.bsky.social@bsky.brid.gy, true, false,
danielroe.dev@bsky.brid.gy, true, false,
patak.dev@bsky.brid.gy, true, false,

1 Account address Show boosts Notify on new posts Languages
8 b0rk.jvns.ca@bsky.brid.gy true false
9 seldo.com@bsky.brid.gy true false
10 nerdy.dev@bsky.brid.gy true false
11 samuel.fm@bsky.brid.gy wongmjane.com@bsky.brid.gy true false
12 samuel.bsky.team@bsky.brid.gy true false
13 laurenshof.online@bsky.brid.gy true false
14 bell.bz@bsky.brid.gy true false
15 matrix.org@bsky.brid.gy true false
29 malstrom.me@bsky.brid.gy true false
30 shuuji3.xyz@bsky.brid.gy true false
31 intenttoship.dev@bsky.brid.gy true false
32 haoqun.dev@bsky.brid.gy true false
33 element.io@bsky.brid.gy true false
34 e18e.dev@bsky.brid.gy true false
35 danabra.mov@bsky.brid.gy true false
36 heydonworks.com@bsky.brid.gy heydonworks.bsky.social@bsky.brid.gy true false
37 danielroe.dev@bsky.brid.gy true false
38 patak.dev@bsky.brid.gy true false

View file

@ -32,8 +32,8 @@ const year = new Date().getFullYear()
aria-label={linkObj.text}
>
<Icon
width="1em"
height="1em"
width="1.5em"
height="1.5em"
name={`${linkObj.set ?? 'simple-icons'}:${linkObj.icon}`}
/>
</a>
@ -47,7 +47,9 @@ const year = new Date().getFullYear()
<a href="/">Ayo Ayco</a>. This website <a
href="https://ayos.blog/stopped-tracking-on-my-sites"
>does not track users</a
>. See the <a href="https://git.ayo.run/ayo/ayco.io-astro">source code.</a>
>. See the <a href="https://git.sr.ht/~ayoayco/ayco.io-astro"
>source code.</a
>
</p>
<WebRings />

View file

@ -7,7 +7,7 @@ export interface Props {
const defaultDescription =
'Professional software engineer specializing in web development with a decade of experience building web applications for both private businesses and government-funded high-impact projects utilizing web technologies, IoT, data viz/insights, remote sensing, and GIS'
const defaultTitle = 'Ayo Ayco - Tech Leader, Software Engineer, Web Developer'
const defaultTitle = 'Ayo Ayco - Web Dev, Engineer, Leader, Thinker'
const defaultOgImage = 'ayo.png'
let {

View file

@ -40,19 +40,14 @@ export const links: Link[] = [
export default links
export const footerLinks: Link[] = [
{
text: "Ayo's Forge",
url: 'https://git.ayo.run/ayo/',
icon: 'git',
},
{
text: 'SourceHut',
url: 'https://sr.ht/~ayoayco',
url: 'https://ayco.io/sh/',
icon: 'sourcehut',
},
{
text: 'Mastodon',
url: 'https://main.elk.zone/social.ayco.io/@ayo',
url: 'https://yolk.ayo.run/https://social.ayco.io/public/local',
icon: 'mastodon',
},
{
@ -60,21 +55,6 @@ export const footerLinks: Link[] = [
url: 'https://metapixl.com/@ayo',
icon: 'pixelfed',
},
{
text: 'Bluesky',
url: 'http://bsky.app/profile/ayo.ayco.io',
icon: 'bluesky',
},
{
text: 'Instagram',
url: 'https://www.instagram.com/ayoayco/',
icon: 'instagram',
},
{
text: 'LinkedIn',
url: 'https://www.linkedin.com/in/ayoayco/',
icon: 'linkedin',
},
{
text: 'GitHub',
url: 'https://ayco.io/gh',

View file

@ -8,33 +8,51 @@ import Footer from '../components/Footer.astro'
<h1>Ayo Ayco</h1>
<p>ᜈᜄ᜔ᜋᜓᜎ ᜐ ᜉᜒᜇ̢̟ᜎᜐ᜔ ᜅ᜔ ᜐᜒᜎᜅᜈᜈ᜔</p>
<p>
Technical engineering leader experienced in web development, software
architecture, and community building. Passionate about the indieweb,
digital sovereignty, and kindness.
Frontend guy who likes server adventures, coding, and linux. Passionate
about the indieweb, digital sovereignty, and kindness.
</p>
<details>
<summary>
Hey there! I interrupt this page for a message from this website's
sponsor...
</summary>
<p>
<strong>Myself!</strong> Thank you for wanting to read a bit more about me.
<!--Some people shy away from writing things about themselves, and thus looks negatively at others who do. But that shouldn't be the case!-->
I find it helpful to have a single canonical <code class="inline-code"
>/about</code
> page with these significant information. It is always a work in progress
(like me), and to be honest, I do this mostly as a reminder as the world
continue to impose identity onto us. Cheers to celebrating differences!
</p>
<small> Now back to the rest of the web page... </small>
</details>
<p>
I am an engineering manager at <a href="https://ing.com">ING</a> and a certified
software architecture professional (CPSAF®) by <a
href="https://isaqb.org"
target="_blank">iSAQB</a
>.
I am a newbie engineering manager at a large global bank headquartered in
Amsterdam. I'm also a certified software architecture professional
(CPSAF®) by <a href="https://isaqb.org" target="_blank">isaqb.org</a>.
</p>
<p>
In my spare time, I find it fun building <a href="/showcase">projects</a>,
running self-hosted services at <a href="https://ayo.run">ayo.run</a>, and
volunteering to <a href="https://ayos.blog/why-fediverse/" target="_blank"
>Fediverse</a
In my spare time, when I have energy, I find it fun building <a
href="/showcase">hobby projects</a
>, running self-hosted services at <a href="https://ayo.run">ayo.run</a>,
and volunteering to <a
href="https://ayos.blog/why-fediverse/"
target="_blank">Fediverse</a
> projects like <a href="https://elk.zone">elk.zone</a>,
<a href="https://m.webtoo.ls/public/local">webtoo.ls</a>, and <a
href="https://m.webtoo.ls/@vitest">vitest's fedi presence</a
>.
</p>
<p>
I've volunteered much of my early years into leadership trainings,
teaching & leading groups of students, planting a church, and facilitating
focus group discussions with entrepreneurial founders, where I learned the
power of multi-generational & multi-cultural communities.
In a previous life, I've volunteered much of my weekends into teaching
kids, leading groups of students, planting a church, and facilitating
focus group discussions with entrepreneurial founders, where I learned a
lot about the power of multi-generational & multi-cultural communities.
</p>
<h2 id="contact">Contact info</h2>
<ul>
<li>✉️ Email: <a href="mailto:ayo@ayco.io">ayo@ayco.io</a></li>

View file

@ -21,7 +21,7 @@ import now from '../constants/now.json'
<img
class="u-photo highlighted-section__content__profile-picture"
alt="Ayo Ayco's avatar"
src="/ayo-2025-sm.png"
src="/ayo-sm.png"
width="140"
height="140"
/>
@ -29,7 +29,7 @@ import now from '../constants/now.json'
<h1 title="Ayo Ayco | Software Engineer + Web Developer">
Hi, I'm <span class="heavy-text">Ayo</span>!
</h1>
<!--a href="https://forms.ayo.run/form/tnz7FybY" class="now-wrapper"-->
<!-- <a href="https://forms.ayo.run/form/tnz7FybY" class="now-wrapper"> -->
<a href="/now" class="now-wrapper">
<span class="now-label">now</span>
<span class="status">{now.title}</span>

View file

@ -16,12 +16,6 @@ import Card from '../components/Card.astro'
>.
</p>
<ul>
<Card
newTab
href="https://git.ayo.run/ayo/simple-tts#readme"
title="Simple TTS"
body="A machine learning text-to-speech program for the terminal"
/>
<Card
newTab
href="https://mcfly.js.org"
@ -75,6 +69,11 @@ import Card from '../components/Card.astro'
title="Reactive Form"
body="The reactive form component for Astro 🔥"
/>
<Card
href="/showcase/astro-github-stats"
title="GitHub Stats"
body="Embed GitHub stats on your Astro page ✨"
/>
</ul>
</main>
<Footer />

View file

@ -6,39 +6,17 @@
const cacheName = `${__prefix ?? 'app'}-v${__version ?? '000'}`
const forceLogging = true
/**
* Cleans up old service worker caches by deleting any cache that doesn't match the current cache name.
* This ensures only the current version of the application's cache is retained.
* @async
* @function cleanOldCaches
* @returns {Promise<void>} A promise that resolves when old caches have been deleted
*/
const cleanOldCaches = async () => {
const allowCacheNames = [cacheName]
const allCaches = await caches.keys()
allCaches.forEach((key) => {
if (!allowCacheNames.includes(key)) {
console.info('Deleting old cache', key)
caches
.delete(key)
.then(() => {
console.info('Successfully deleted cache:', key)
})
.catch((error) => {
console.warn('Failed to delete old cache:', key, error)
})
caches.delete(key)
}
})
}
/**
* Adds specified resources to the service worker cache.
* This function is used to cache static assets for offline access.
* @async
* @function addResourcesToCache
* @param {Array<string>} resources - An array of URLs representing the resources to be cached.
* @returns {Promise<void>} A promise that resolves when all resources have been successfully added to the cache.
*/
const addResourcesToCache = async (resources) => {
const cache = await caches.open(cacheName)
console.info('adding resources to cache...', {
@ -56,14 +34,6 @@ const addResourcesToCache = async (resources) => {
}
}
/**
* Puts a response in the cache.
* @async
* @function putInCache
* @param {Request} request - The request to be cached.
* @param {Response} response - The response to be cached.
* @returns {Promise<void>} A promise that resolves when the response has been added to the cache.
*/
const putInCache = async (request, response) => {
const cache = await caches.open(cacheName)
@ -79,6 +49,9 @@ const networkFirst = async ({ request, fallbackUrl }) => {
try {
// Try to get the resource from the network for 5 seconds
const responseFromNetwork = await fetch(request.clone())
// response may be used only once
// we need to save clone to put one copy in cache
// and serve second one
putInCache(request, responseFromNetwork.clone())
console.info('using network response', responseFromNetwork.url)
return responseFromNetwork
@ -91,13 +64,11 @@ const networkFirst = async ({ request, fallbackUrl }) => {
return responseFromCache
}
// If fallback is provided, try to use it, otherwise return error
if (fallbackUrl) {
const fallbackResponse = await cache.match(fallbackUrl)
if (fallbackResponse) {
console.info('using fallback cached response...', fallbackResponse.url)
return fallbackResponse
}
// Try the fallback
const fallbackResponse = await cache.match(fallbackUrl)
if (fallbackResponse) {
console.info('using fallback cached response...', fallbackResponse.url)
return fallbackResponse
}
// when even the fallback response is not available,