Compare commits

..

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

21 changed files with 1812 additions and 1627 deletions

View file

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

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.3.5",
"private": true,
"scripts": {
"astro": "astro",
@ -23,35 +23,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

@ -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

@ -0,0 +1,7 @@
{
"title": "Reading stuff & something to look forward to",
"description": "fighting to find a direction above the storm",
"publishDate": "2025-06-10",
"publishedOn": "",
"publishState": ""
}

View file

@ -0,0 +1,12 @@
## Reading
Books I'm currently reading as I continue to have a messed up health & rhythm
- [Getting Real](https://books.37signals.com/8/getting-real)
- [How to Read a Book](https://en.wikipedia.org/wiki/How_to_Read_a_Book)
- [Code Complete 2](http://www.amazon.com/dp/0735619670/)
- [The Mythical Man-Month](http://www.amazon.com/dp/0201835959/)
## Something to look forward to
Reading has been a great companion lately. [37signals](https://37signals.com/) inspired me while reading their book "Getting Real", just in time as I'm up for updating my vision for 2030, after achieving most of my personal 2025 targets. [I want to start a cooperative that will empower people to take ownership of their digital lives.](https://social.ayco.io/@ayo/114655020696985932).

View file

@ -50,9 +50,14 @@ export const footerLinks: Link[] = [
url: 'https://sr.ht/~ayoayco',
icon: 'sourcehut',
},
{
text: 'GitHub',
url: 'https://ayco.io/gh',
icon: 'github',
},
{
text: 'Mastodon',
url: 'https://main.elk.zone/social.ayco.io/@ayo',
url: 'https://social.ayco.io/about',
icon: 'mastodon',
},
{
@ -65,21 +70,11 @@ export const footerLinks: Link[] = [
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',
icon: 'github',
},
]
export const socialLinks: Link[] = [

View file

@ -1,7 +1,7 @@
{
"title": "Reading stuff & something to look forward to",
"description": "fighting to find a direction above the storm",
"publishDate": "2025-06-10",
"title": "",
"description": "",
"publishDate": "2025-10-18",
"publishedOn": "",
"publishState": ""
}

View file

@ -1,12 +0,0 @@
## Reading
Books I'm currently reading as I continue to have a messed up health & rhythm
- [Getting Real](https://books.37signals.com/8/getting-real)
- [How to Read a Book](https://en.wikipedia.org/wiki/How_to_Read_a_Book)
- [Code Complete 2](http://www.amazon.com/dp/0735619670/)
- [The Mythical Man-Month](http://www.amazon.com/dp/0201835959/)
## Something to look forward to
Reading has been a great companion lately. [37signals](https://37signals.com/) inspired me while reading their book "Getting Real", just in time as I'm up for updating my vision for 2030, after achieving most of my personal 2025 targets. [I want to start a cooperative that will empower people to take ownership of their digital lives.](https://social.ayco.io/@ayo/114655020696985932).

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

@ -2,7 +2,7 @@
import Layout from '../layouts/Layout.astro'
import Card from '../components/Card.astro'
import Footer from '../components/Footer.astro'
import now from '../constants/now.json'
// import now from '../constants/now.json'
---
<Layout>
@ -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"
/>
@ -30,10 +30,10 @@ import now from '../constants/now.json'
Hi, I'm <span class="heavy-text">Ayo</span>!
</h1>
<!--a href="https://forms.ayo.run/form/tnz7FybY" class="now-wrapper"-->
<a href="/now" class="now-wrapper">
<!--a href="/now" class="now-wrapper">
<span class="now-label">now</span>
<span class="status">{now.title}</span>
</a>
</a-->
</div>
</div>
</section>

View file

@ -0,0 +1,75 @@
---
import Layout from '../../../../layouts/Layout.astro'
import Footer from '../../../../components/Footer.astro'
const title = `Reading stuff & something to look forward to`
const description = `fighting to find a direction above the storm`
let publishedOn = ``
const publishDate = `2025-06-10`
const publishState = ``
const content = `<h2>Reading</h2>
<p>Books I'm currently reading as I continue to have a messed up health &#x26; rhythm</p>
<ul>
<li><a href="https://books.37signals.com/8/getting-real">Getting Real</a></li>
<li><a href="https://en.wikipedia.org/wiki/How_to_Read_a_Book">How to Read a Book</a></li>
<li><a href="http://www.amazon.com/dp/0735619670/">Code Complete 2</a></li>
<li><a href="http://www.amazon.com/dp/0201835959/">The Mythical Man-Month</a></li>
</ul>
<h2>Something to look forward to</h2>
<p>Reading has been a great companion lately. <a href="https://37signals.com/">37signals</a> inspired me while reading their book "Getting Real", just in time as I'm up for updating my vision for 2030, after achieving most of my personal 2025 targets. <a href="https://social.ayco.io/@ayo/114655020696985932">I want to start a cooperative that will empower people to take ownership of their digital lives.</a>.</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>

View file

@ -20,7 +20,7 @@ import Card from '../components/Card.astro'
newTab
href="https://git.ayo.run/ayo/simple-tts#readme"
title="Simple TTS"
body="A machine learning text-to-speech program for the terminal"
body="A simple machine learning text-to-speech program for the terminal"
/>
<Card
newTab
@ -28,6 +28,11 @@ import Card from '../components/Card.astro'
title="McFly"
body="A meta-framework for building web experiences"
/>
<Card
href="/showcase/tech-bsky-fedi"
title="Tech Bsky ↔ Fedi"
body="Celebrating bsky folks who bridged their accounts to the fediverse!"
/>
<Card
newTab
href="https://ayco.io/sh/astro-sw#readme"
@ -75,6 +80,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

@ -0,0 +1,218 @@
---
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'
const csvToArray = (content: string) => {
return content
.split('\n')
.slice(1)
.map((str) => str.split(',')[0])
}
const accounts = csvToArray(importedCode)
let accountObjects = accounts
.map((account) => {
const bskyHandle = account?.replace('@bsky.brid.gy', '')
const url = `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile/?actor=${bskyHandle}`
return account
? {
bskyHandle,
fediHandle: account,
url,
}
: null
})
.filter((acct) => !!acct)
const urls = accountObjects.map((account) => account.url)
const promises = urls.map((url) => fetch(url))
const responses = await Promise.all(promises)
let data = await Promise.all(responses.map((response) => response.json()))
// filter accounts with error (e.g., AccountDisabled)
accountObjects = accountObjects.filter((acct, index) => {
const hasNoError = !data[index].error
if (!hasNoError)
console.log(`>>> ${acct.bskyHandle} has error: ${data[index].error}`)
return hasNoError
})
data = data.filter((datum) => !datum.error)
const title = 'Tech Bsky ↔ Fedi'
const description =
'Celebrating bsky folks who bridged their accounts to the fediverse!'
---
<Layout title={title} description={description} ogImage="bskyfedi.png">
<main>
<h1 class="text-gradient">{title}</h1>
<p><em>{description}</em></p>
<p>
A lot of tech accounts are now active in Bsky. Some of them opted to be
bridged to the Fediverse via <a href="https://fed.brid.gy">fed.brid.gy</a>
-- so we can also follow them from any ActivityPub powered social platforms.
</p>
<p>
On this page, I upload my handpicked tech Bsky accounts that are currently
bridged to the Fedi. Feel free to <a
href="mailto:ayo@ayco.io?subject=Re:%20Tech%20bsky%20<->%20fedi"
>send me a mail</a
> to request adding accounts I missed.
</p>
<p>
If you are on bsky and want to be bridged too, please follow <a
href="https://bsky.app/profile/ap.brid.gy"
target="_blank">@ap.brid.gy</a
>.
</p>
<p>
If you are on fedi and want to follow the accounts here, scroll to the <a
href="#how">bottom of the page</a
> for a handy `.csv` file you can upload to your chosen fedi platform.
</p>
<p>
Note that for the bsky accounts to see your replies and likes from fedi,
you have to bridge your account as well by following <a
href="https://elk.zone/@bsky.brid.gy@bsky.brid.gy"
>@bsky.brid.gy@bsky.brid.gy</a
>
</p>
<h2>Accounts ({accountObjects.length})</h2>
<p><em>Ordered in terms of my time of discovery.</em></p>
<div class="table-container">
<table>
<tr>
<th>&nbsp;</th>
<th>Fedi</th>
<th>Bsky</th>
</tr>
{
accountObjects.map((account, index) => (
<tr>
<td>
<Image
src={data[index].avatar ?? ''}
alt={`${account.bskyHandle}'s avatar`}
width="50"
height="50"
decoding="async"
loading="lazy"
/>
</td>
<td>
<span>
<a
href={`https://elk.zone/@${account.fediHandle}`}
target="_blank"
>
{account.fediHandle}
</a>
</span>
</td>
<td>
<span>
<a
href={`https://bsky.app/profile/${account.bskyHandle}`}
target="_blank"
>
{account.bskyHandle}
</a>
</span>
</td>
</tr>
))
}
</table>
</div>
<h2 id="how">How how how?</h2>
<p>
Download the <a href="following_accounts.csv">.csv file</a>
<strong>or</strong> copy the content below and save in a file. Then, upload
to your fedi account provider.
</p>
<p>If you're on Mastodon, this functionality is found in:</p>
<p>
<strong>Preferences</strong> &rarr; <strong>Import and export</strong> &rarr;
<strong>Import</strong>
</p>
<h2>Full <code class="inline-code">.csv</code> content</h2>
<br />
<Code code={importedCode} />
<Footer />
</main>
</Layout>
<style>
td img {
border-radius: 5px;
min-width: 50px;
width: 50px;
height: 50px;
}
.table-container {
overflow-x: auto;
}
th,
td {
padding: 1rem;
border-radius: 5px;
background: rgba(0, 0, 0, 0.01);
border: 1px solid rgba(0, 0, 0, 0.1);
}
th:first-child,
td:first-child {
display: block;
max-width: calc(50px + 2rem);
}
td a {
color: var(--text-color-dark);
text-decoration: none;
&:hover {
color: var(--color-brand-blue-3);
text-decoration: underline;
}
}
@media (prefers-color-scheme: dark) {
td,
th {
background: rgba(0, 0, 0, 0.1);
border: 1px solid rgba(0, 0, 0, 0.1);
& a {
color: var(--text-color-light);
text-decoration: none;
&:hover {
color: var(--color-brand-complement);
text-decoration: underline;
}
}
}
}
</style>