Skip to content

Commit

Permalink
feat: api for r2 assets and fetch alt text from image captions (#59)
Browse files Browse the repository at this point in the history
- **feat: API R2 assets**
  

- **blog: update WordPress post with R2Image component for all four
images**
  

- **fix: remove signed URL logging**
  

- **fix: replace all images in all blog posts with R2Image component**
  

- **fix: set image caption as alt text in R2Image component**
  

- **fix: placeholder alt text**
  • Loading branch information
arunsathiya authored Aug 26, 2024
2 parents 7063471 + 736bc5e commit 5d01df5
Show file tree
Hide file tree
Showing 23 changed files with 219 additions and 41 deletions.
14 changes: 10 additions & 4 deletions .prettierrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ module.exports = {
{
files: '*.astro',
options: {
parser: 'astro'
}
}
]
parser: 'astro',
},
},
{
files: '*.mdx',
options: {
parser: 'mdx',
},
},
],
};
28 changes: 17 additions & 11 deletions astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
import tailwind from "@astrojs/tailwind";
import tailwind from '@astrojs/tailwind';
import { defineConfig } from 'astro/config';
import { autoNewTabExternalLinks } from './src/autoNewTabExternalLinks';

import partytown from "@astrojs/partytown";
import partytown from '@astrojs/partytown';

// https://astro.build/config
export default defineConfig({
site: 'https://www.arun.blog',
integrations: [mdx(), sitemap(), tailwind(), partytown()],
markdown: {
extendDefaultPlugins: true,
rehypePlugins: [[autoNewTabExternalLinks, {
domain: 'localhost:4321'
}]]
}
});
site: 'https://www.arun.blog',
output: 'server',
integrations: [mdx(), sitemap(), tailwind(), partytown()],
markdown: {
extendDefaultPlugins: true,
rehypePlugins: [
[
autoNewTabExternalLinks,
{
domain: 'localhost:4321',
},
],
],
},
});
58 changes: 58 additions & 0 deletions src/components/R2Image.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
interface Props {
imageKey: string;
alt: string;
}
const { imageKey, alt } = Astro.props;
console.log('R2Image component rendering with props:', { imageKey, alt });
---

<img data-r2-key={imageKey} src='/placeholder.png' alt={alt} />

<script>
async function refreshSignedUrls() {
const images = document.querySelectorAll<HTMLImageElement>('img[data-r2-key]');

if (images.length === 0) {
console.warn('No images found with data-r2-key attribute. DOM content:', document.body.innerHTML);
}

for (const img of images) {
const imageKey = img.getAttribute('data-r2-key');

if (imageKey) {
try {
const response = await fetch(`/api/signedUrl?key=${encodeURIComponent(imageKey)}`, {
headers: {
Accept: 'application/json',
},
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();

if (data.url) {
img.src = data.url;
} else {
console.error('No URL received in the response');
}
} catch (error) {
console.error('Failed to refresh signed URL:', error);
}
} else {
console.warn('Image found without data-r2-key attribute');
}
}
}

// Refresh URLs on page load
refreshSignedUrls();

// Optionally, refresh URLs periodically
setInterval(refreshSignedUrls, 50 * 60 * 1000); // Refresh every 50 minutes
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tags: ['Automation']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

> Note: As of Feb 2024, I have moved to a Astro-based website deployed to the edge with Fastly Compute, with Notion as a backend and GitHub Actions as my build tool.
For a while, I have been thinking about excluding draft posts from search engines' indexes. When I say draft posts, I am talking about the blog posts that aren't worthy of being indexed; those that aren't subjected to the level of quality that I expect the public to read. Think of draft blog posts similar to tweets. [I have been trying to use my blog as a source of my thoughts](https://www.notion.so/2021/01/19/blog-as-a-replacement-for-twitter/), while being cross-posted to other social networks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ seoTitle: 'Growing my home lab - Tailscale TLS certificates for each Docker with
slug: 'tailscale-tls-certificates-for-my-home-lab'
description: 'I am starting to grow my home lab with Raspberry Pi, Docker, Caddy and Tailscale. Right now, I have Whoogle, libreddit, pihole and Caddy running on my nodes.'
pubDate: 'Sep 26 2021'
updatedDate: 'Aug 24 2024'
updatedDate: 'Aug 25 2024'
tags: ['Tools', 'DevOps']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

I have grown up reading Raspberry Pi users build amazing projects on this wonderful reddit: [r/homelab](https://old.reddit.com/r/homelab/). Until an year ago, I didn't have a clue where to start, mostly because the idea of setting up Wireguard to access these self-hosted services was a bit intimidating. Tailscale changed everything.

Tailscale is a mesh VPN software that makes it incredibly easy to connect your devices together. This includes your laptops, mobile devices, servers, and even printers. The idea is that, Tailscale acts as an interface for all devices to talk to each other, without having to create, manage and install Wireguard certificates manually.
Expand All @@ -27,7 +29,11 @@ But my use-case was to run Caddy as a reverse proxy, to serve each Docker contai

- Libreddit on the root domain `mew.tailnet-b593.ts.net`.
- Whoogle on `mew.tailnet-b593.ts.net/google`
![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/tailscale-tls-certificates-for-my-home-lab-5e11ac3a-ce18-4dbb-8ff9-05c0afe3f875.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=1d2256cf8abe4bca460f6f7183a041d5d8e231f0908e2101df3df84e8c7ec4f7&X-Amz-SignedHeaders=host&x-id=GetObject)

<R2Image
imageKey='blog/assets/tailscale-tls-certificates-for-my-home-lab-5e11ac3a-ce18-4dbb-8ff9-05c0afe3f875.png'
alt='Tailscale TLS certificates on a Whoogle instance'
/>

I wanted to access my pihole admin on HTTPS too, but I couldn't get it working on a subfolder, like `mew.tailnet-b593.ts.net/pihole`. When I assigned the root domain to pihole, libreddit had to go to a subfolder like `mew.tailnet-b593.ts.net/reddit` and when I tried that, CSS on my libreddit instance broke.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tags: ['Content Management', 'Tools', 'Open Source']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

For years, design on WordPress had been in the form of PHP templates bundled together as a WordPress theme. The templates apply to specific content as desginated by the [WordPress Template Hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/). The largest issue with this approach would be that anyone wanting a custom design on their site must have PHP skills to write theme code.

Full Site Editing (FSE) is changing that process. Those with programming knowledge can design custom designs for their pages, posts or even for search archives or 404 pages. This is largely possible, thanks to the extensible nature of Gutenberg blocks. They are now available for use on sidebars in the form of widgets, on the header and footer areas, in the form of Full Site Editing.
Expand All @@ -21,17 +23,17 @@ Personally, I wanted a theme that shows all of my blog posts on the homepage, bu

Right now, my homepage looks as shown below, this is a two column layout:

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/thoughts-on-wordpress-full-site-editing-53ae846c-1d75-424e-804c-2ea4301ed73a.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062629Z&X-Amz-Expires=3600&X-Amz-Signature=d8fb6e924ee620e4661ec858b21d3bfb9ba649e223bfe0f24b23df8646647d24&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/thoughts-on-wordpress-full-site-editing-53ae846c-1d75-424e-804c-2ea4301ed73a.png' alt='' />

The content on the right isn't my sidebar. Rather is the right column of my homepage's FSE editor. For comparison, my editor view is as shown below:

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/thoughts-on-wordpress-full-site-editing-4a79b9de-cff0-41be-ba1d-7dd6fccdf17f.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062629Z&X-Amz-Expires=3600&X-Amz-Signature=2beac7d7f103ab1070af3719febc6a952ba6e9e4316a10095418e916d4debccc&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/thoughts-on-wordpress-full-site-editing-4a79b9de-cff0-41be-ba1d-7dd6fccdf17f.png' alt='' />

Likewise, here's a comparison of the single blog post view:

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/thoughts-on-wordpress-full-site-editing-f180d5e9-7857-4305-af28-294e025d7254.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062629Z&X-Amz-Expires=3600&X-Amz-Signature=ed313851e14e778decd1e8ba4fb1da52c2c1fbbb089ab6e437c3ccf675de30f9&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/thoughts-on-wordpress-full-site-editing-f180d5e9-7857-4305-af28-294e025d7254.png' alt='' />

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/thoughts-on-wordpress-full-site-editing-d2d99e7a-628f-46d9-a7bc-21c61db2a145.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062629Z&X-Amz-Expires=3600&X-Amz-Signature=faee3d6d3f7561ab401594c9d9192fcc94bb89784b0bbfabe2e3ea628ba72e5c&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/thoughts-on-wordpress-full-site-editing-d2d99e7a-628f-46d9-a7bc-21c61db2a145.png' alt='' />

See how the editor looks very similar to a blog post or page editor?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tags: ['Tools', 'Security', 'Privacy']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

A week ago, the wonderful folks at 1Password announced a new feature: automatic generation of email aliases when creating a new vault entry. As an user of SimpleLogin, [I am already familiar with the concept of using unique aliases for each website](https://blogarunsathiya.wordpress.com/2020/06/25/of-emails-and-aliases/). It's the same functionality that [1Password and Fastmail announced](https://blog.1password.com/fastmail-masked-email/), except that generating the alias doesn't require a visit to the email provider's website.

## Fastmail vs SimpleLogin
Expand All @@ -17,7 +19,7 @@ I see how this is helpful for the common user, but I am also slightly sad that s

In my 2 years of being a SimpleLogin customer, I have generated over 1200 aliases and I guess, about 50% reply addresses. All of that is available at a fantastic cost of 30 USD per year.

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/thoughts-on-the-1password-fastmail-partnership-e3f54144-5013-458d-a4c8-a89475ba1d78.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=dd0edbefdefb7009a22d66618bf3c577c123146da944d597f2f0b0a43b8de623&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/thoughts-on-the-1password-fastmail-partnership-e3f54144-5013-458d-a4c8-a89475ba1d78.png' alt='' />

Except one outage, the service has been spectacular so far and support is great. The founder, Son, often responds to my emails, welcomes feedback and sometimes includes users in future product discussions. If you are looking for a privacy-respecting email alias generator, look no beyond SimpleLogin. *This is not a sponsored post. I am just a happy user.*

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tags: ['Tools', 'Privacy', 'Security']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

I definitely agree with [what James writes here](https://blog.james.cridland.net/should-you-store-your-2fa-totp-tokens-in-your-password-manager-9798199b728):

> Storing them in your password manager is probably as safe, or even safer, than using your phone
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tags: ['Automation']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

One thing that I found lacking in the [SimpleLogin API](https://github.com/simple-login/app/blob/master/docs/api.md) is that, it doesn't expose an API endpoint to create a contact based on the alias' email address. Rather, the `POST /api/aliases/:alias_id/contacts` endpoint requires the alias ID. So, I ended up downloading all aliases as multiple batches (each query returns upto 20 results) and saved them as json files in a folder.

With them in a folder, I could use jq to parse all of these json files for an alias email address, get its ID and further use it to create a new contact. All of this works like a charm now. My entire process works independent of the dashboard now: create a new alias, get its ID, create a contact, copy the reverse contact address, paste it on my email client.
Expand All @@ -31,6 +33,6 @@ If you are wondering what the `tr -d "\\""` part is, it's to remove the unwant

The contact's reverse address is finally in my clipboard, which I can paste on Apple Mail:

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/jq-magic-to-create-contacts-for-simplelogin-aliases-3976fae0-0b0f-42c5-8361-c78f3f890db0.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=a13e3dee56444bcefdeacdcb917beaca2e59ac60a5a8c01c64154cfe7ebf743f&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/jq-magic-to-create-contacts-for-simplelogin-aliases-3976fae0-0b0f-42c5-8361-c78f3f890db0.png' alt='' />

SimpleLogin recently announced an update to their Firefox extension too, to create reverse aliases (contact reverse address) on the go, but I like this API-based process better. The extension takes a while to populate all aliases.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tags: ['Automation']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

Learned a neat thing today — [it's possible to set custom DNS resolvers for certain domains](https://news.ycombinator.com/item?id=29026068). I can create a custom config file for dnsmasq and specify the DNS resolvers to use for those domains. I don't have a need for it today, but may be handy in cases like archive.is not loading on Cloudflare DNS.

These requests still go through pihole, so ad-blocking capabilities are available. It's just the upstream that changes. My test below confirms so: I have set `dnsleaktest.com` to be queried using Google DNS but requests still pass through pihole.
Expand All @@ -19,6 +21,6 @@ server=/dnsleaktest.com/8.8.8.8
server=/dnsleaktest.com/8.8.4.4
```

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/dnsmasq-custom-dns-resolvers-for-specific-domains-42362915-5cb1-4239-b9c9-2284826ef946.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=d26e83e47d6ba0bafbf28dee5dce9e918b2c33f254934f359ac125272e395d96&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/dnsmasq-custom-dns-resolvers-for-specific-domains-42362915-5cb1-4239-b9c9-2284826ef946.png' alt='' />

I use two Raspberry Pi devices at home, both running pihole with Unbound as a recursive DNS resolver. These devices are connected to my [Tailscale network, so all of my devices (and my friends) can enjoy Unbound and pihole's ad-blocking capabilities](https://blogarunsathiya.wordpress.com/2021/03/30/pi-hole-on-tailscale/).
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tags: ['Tools', 'Automation']
coverImage: './image.webp'
---

import R2Image from 'src/components/R2Image.astro';

Among Us can be hosted on the public servers. Games can be private or public, but the problem with public server-hosted games is that, games disconnect sometimes. That's because these public servers are popular that it doesn't handle surge in active sessions. A solution is to host the games locally on a private network.

That's where Impostor and Tailscale come in.
Expand All @@ -29,13 +31,13 @@ Install Impostor on the Raspberry Pi. The process involves installing Dotnet run

Finally, anyone can start the game, mark it as `Public` and then other devices can join this public room. Make sure that the "World" in your "Online" mode is set to "Impostor", not "Asia", "Europe" or "Americas".

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/private-among-us-games-on-the-tailscale-network-039db48d-d183-45f4-b9e7-a52ca42cdbd0.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=3178a84724944431b1bdccc4007f599acb160904f0d26f7ecd1d217ffede44fb&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/private-among-us-games-on-the-tailscale-network-039db48d-d183-45f4-b9e7-a52ca42cdbd0.png' alt='' />

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/private-among-us-games-on-the-tailscale-network-954b6a83-28b1-4707-9dda-d263dd8a5dd8.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=c7939d102b901d414317a3742416671dd573762c49ed240a2cf43c495b452bd3&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/private-among-us-games-on-the-tailscale-network-954b6a83-28b1-4707-9dda-d263dd8a5dd8.png' alt='' />

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/private-among-us-games-on-the-tailscale-network-43079733-26cb-4f4a-b37f-b2ce47640f60.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=ecb73c6a6e2f238ac8da84253435a06878c3df1f5f5684767b467d10df5f2cf0&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/private-among-us-games-on-the-tailscale-network-43079733-26cb-4f4a-b37f-b2ce47640f60.png' alt='' />

![image.png](https://portfolio.75d17a47b6c80ac40b0e7e44a4a8517d.r2.cloudflarestorage.com/blog/assets/private-among-us-games-on-the-tailscale-network-ad192dfe-ca42-414e-958c-c99ceaf84bdf.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=8367778c331a87824282df96c3af94ca%2F20240825%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20240825T062628Z&X-Amz-Expires=3600&X-Amz-Signature=0ec23bb339d2b832148c876aef6803e3ec409dbec41846aebe746d046378c88b&X-Amz-SignedHeaders=host&x-id=GetObject)
<R2Image imageKey='blog/assets/private-among-us-games-on-the-tailscale-network-ad192dfe-ca42-414e-958c-c99ceaf84bdf.png' alt='' />

## Other notes

Expand Down
Loading

0 comments on commit 5d01df5

Please sign in to comment.