diff --git a/app/page.tsx b/app/page.tsx
index 172c0ec..1eebfb3 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -63,6 +63,7 @@ export default async function Home() {
src={profileAvatar}
alt={`${profileName} avatar`}
fill
+ sizes="96px"
priority
className="object-cover"
/>
diff --git a/components/LinkCard.tsx b/components/LinkCard.tsx
index 5c9e3c6..5c7eca4 100644
--- a/components/LinkCard.tsx
+++ b/components/LinkCard.tsx
@@ -68,6 +68,7 @@ export function LinkCard({ counts, links1, links2 }: { counts: FollowerCounts, l
onClick={() => setIsPage2(false)}
disabled={!isPage2}
className="text-zinc-400 hover:text-white disabled:opacity-50"
+ aria-label="หน้าก่อนหน้า"
>
@@ -76,6 +77,7 @@ export function LinkCard({ counts, links1, links2 }: { counts: FollowerCounts, l
onClick={() => setIsPage2(true)}
disabled={isPage2}
className="text-zinc-400 hover:text-white disabled:opacity-50"
+ aria-label="หน้าถัดไป"
>
diff --git a/instrumentation.ts b/instrumentation.ts
new file mode 100644
index 0000000..0097ee2
--- /dev/null
+++ b/instrumentation.ts
@@ -0,0 +1,10 @@
+export async function register() {
+ if (process.env.NEXT_RUNTIME === "nodejs") {
+ try {
+ const { getFollowerCounts } = await import("./lib/followers");
+ await getFollowerCounts();
+ } catch (error) {
+ console.error("[Instrumentation] Failed to warm up cache:", error);
+ }
+ }
+}
diff --git a/nginx.conf b/nginx.conf
index 2ff810e..71226b1 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -33,6 +33,12 @@ http {
listen 80;
server_name localhost;
+ # Security headers for Lighthouse Best Practices
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
+
# Use Docker's internal DNS resolver with a short TTL
# This prevents caching stale IPs when containers are rebuilt
resolver 127.0.0.11 valid=10s;