initial hugo site with terminal theme
This commit is contained in:
parent
2c46b2ad6d
commit
ddf013b6b3
64
.gitea/workflows/ci.yaml
Normal file
64
.gitea/workflows/ci.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
# Required secrets:
|
||||
# REGISTRY_USER — Gitea container registry username
|
||||
# REGISTRY_PASSWORD — Gitea container registry password
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build-check:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Verify Hugo build
|
||||
uses: docker://hugomods/hugo:exts
|
||||
with:
|
||||
args: hugo --minify
|
||||
|
||||
build-and-push:
|
||||
if: github.event_name == 'push'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: docker-container
|
||||
driver-opts: network=host
|
||||
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: gitea.nik4nao.com
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Resolve short SHA
|
||||
id: sha
|
||||
run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and push multiarch image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
gitea.nik4nao.com/nik/portfolio:latest
|
||||
gitea.nik4nao.com/nik/portfolio:${{ steps.sha.outputs.short }}
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -1 +1,4 @@
|
||||
.env
|
||||
.env
|
||||
.hugo_build.lock
|
||||
public/
|
||||
resources/_gen/
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "themes/terminal"]
|
||||
path = themes/terminal
|
||||
url = https://github.com/panr/hugo-theme-terminal.git
|
||||
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@ -0,0 +1,10 @@
|
||||
FROM hugomods/hugo:exts AS builder
|
||||
|
||||
WORKDIR /site
|
||||
COPY . .
|
||||
RUN hugo --minify
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY --from=builder /site/public /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
149
content/cv.md
Normal file
149
content/cv.md
Normal file
@ -0,0 +1,149 @@
|
||||
---
|
||||
title: "CV"
|
||||
type: "cv"
|
||||
date: 2026-03-17
|
||||
draft: false
|
||||
---
|
||||
|
||||
# NIK AFIQ
|
||||
|
||||
Tokyo, Japan
|
||||
nik@nik4nao.com | github.com/nikafiq | nik4nao.com
|
||||
|
||||
|
||||
---
|
||||
|
||||
## PROFESSIONAL SUMMARY
|
||||
|
||||
Backend engineer with 3 years of professional experience designing and
|
||||
operating distributed, high-throughput systems on GCP and AWS. Core
|
||||
expertise in Go and Python, with hands-on production experience in
|
||||
event-driven microservices, Kafka-based pipelines, Kubernetes, and
|
||||
cloud-native data infrastructure. Comfortable operating systems at
|
||||
hundreds of TPS with reliability and zero-downtime migration
|
||||
constraints. Trilingual (English, Japanese N1, Malay) — routinely
|
||||
bridges Japanese and overseas engineering teams. Actively integrates
|
||||
AI tooling (GitHub Copilot, Gemini, Claude) into daily coding,
|
||||
review, and documentation workflows.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## WORK EXPERIENCE
|
||||
|
||||
### 株式会社ホープス (Hopes Co., Ltd.) — Tokyo
|
||||
**Backend Engineer** | Aug 2025 – Present
|
||||
|
||||
Designing and operating a distributed RCS consent management pipeline
|
||||
(SO→FoRCE) on GCP/GKE connecting a high-traffic notice delivery
|
||||
system to a downstream fulfillment API.
|
||||
|
||||
- Architected an event-driven pipeline using GKE + Managed Kafka
|
||||
(8 partitions, keyed by account_id) + Cloud Spanner, handling a
|
||||
global cap of 200 TPS with a 10-second downstream timeout budget
|
||||
- Built the Go consumer service (so-notice-receiver) with
|
||||
singleflight coalescing to prevent duplicate in-flight requests,
|
||||
and circuit breaker logic to shed load under downstream failure
|
||||
- Designed reliable offset commit ordering: offsets committed only
|
||||
after durable Spanner write, ensuring at-least-once delivery with
|
||||
no data loss on crash
|
||||
- Implemented a retry cronjob requeuing up to 5 failed Spanner rows
|
||||
back to Kafka every 5 minutes, with configurable backoff
|
||||
- Designed a zero-downtime interleaved index migration on a Cloud
|
||||
Spanner accounts table under 400 TPS sustained read traffic
|
||||
- Right-sized GKE resource configs (CPU/memory requests and limits)
|
||||
from Locust load test data at 40 TPS steady / 120 TPS burst
|
||||
- Propagated distributed traces across service boundaries for
|
||||
end-to-end production observability
|
||||
|
||||
|
||||
### 株式会社ニッポンダイナミックシステムズ — Tokyo
|
||||
**Full Stack Engineer, IT Solutions — Pharma Market Team**
|
||||
| Apr 2023 – Jul 2025
|
||||
|
||||
- Built a scalable analytical DWH on Amazon Aurora (RDS) for a
|
||||
pharmaceutical client, integrating Salesforce and multiple
|
||||
external data sources via daily/weekly ETL batch pipelines using
|
||||
ECS/Fargate and Lambda; designed for HA with Multi-AZ failover
|
||||
- Constructed a SaaS data lake using AWS CDK + Glue +
|
||||
TypeScript/Python, fully automating ETL ingestion across
|
||||
heterogeneous data sources
|
||||
- Developed an internal AI application using AWS Bedrock (Claude
|
||||
Sonnet) + React, implementing RAG-based document retrieval and
|
||||
SES-based user matching in a small cross-functional team
|
||||
- Built a license authentication service (Node.js + Docker + Azure
|
||||
Web Apps + ADB2C), owning requirements definition, auth logic
|
||||
design, and client-facing communication
|
||||
- Designed and automated monthly maintenance operations: AMI image
|
||||
updates, security patching, automated regression testing, and
|
||||
blue/green deployments via AWS CodePipeline and Azure Pipelines
|
||||
- Conducted Docker image vulnerability scanning as part of CI/CD
|
||||
pipeline; managed VPC, WAF, and Security Group configurations
|
||||
- Mentored junior engineers on cloud architecture patterns;
|
||||
functioned as bilingual (EN/JA) liaison between domestic and
|
||||
overseas engineering teams
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SKILLS
|
||||
|
||||
**Languages:** Go, Python, TypeScript/JavaScript
|
||||
**Frameworks:** Gin, Flask, Next.js, Node.js
|
||||
**Cloud — AWS:** ECS/Fargate, Lambda, Aurora/RDS, DynamoDB, Glue,
|
||||
CDK, CodePipeline, Bedrock, Secrets Manager
|
||||
**Cloud — GCP:** GKE, Cloud Spanner, Managed Kafka (Pub/Sub),
|
||||
BigQuery, Cloud Trace
|
||||
**Cloud — Azure:** Web Apps, ADB2C, Azure Pipelines
|
||||
**Data:** MySQL, Aurora, PostgreSQL, DynamoDB, Cloud Spanner,
|
||||
Kafka, Redis
|
||||
**DevOps:** Docker, Kubernetes, ArgoCD, CI/CD, IaC (AWS CDK)
|
||||
**Observability:** Distributed tracing, ELK stack, Kibana
|
||||
**AI Tooling:** GitHub Copilot (daily coding + code review),
|
||||
Gemini (documentation + research), Claude (architecture
|
||||
reasoning + coding), AWS Bedrock RAG (production)
|
||||
**Security:** VPC, WAF, Security Groups, Secrets Manager,
|
||||
Docker vulnerability scanning
|
||||
**Other:** Homelab (k3s, self-hosted services, Ansible/IaC),
|
||||
personal dev blog at nik4nao.com
|
||||
|
||||
|
||||
---
|
||||
|
||||
## CERTIFICATIONS
|
||||
|
||||
| Certification | Issued |
|
||||
|---|---|
|
||||
| AWS Certified Solutions Architect – Associate (SAA) | Oct 2024 |
|
||||
| AWS Certified Developer – Associate (DVA) | Dec 2024 |
|
||||
| AWS Certified Cloud Practitioner (CLF) | Apr 2024 |
|
||||
| 基本情報技術者試験 (FE) — IPA Fundamental IT Engineer | Aug 2024 |
|
||||
| JLPT N1 — Japanese Language Proficiency | Dec 2022 |
|
||||
|
||||
*In progress: AWS Solutions Architect – Professional (SAP),
|
||||
Applied Information Technology Engineer (AP)*
|
||||
|
||||
|
||||
---
|
||||
|
||||
## EDUCATION
|
||||
|
||||
**Tokai University** — Bachelor of Engineering
|
||||
Major: Electrical and Electronic Engineering
|
||||
Minor: Information Technology
|
||||
Graduated: March 2023
|
||||
|
||||
*During a COVID-related leave of absence (2020–2021), independently
|
||||
studied programming and cloud architecture; resumed with an
|
||||
added IT minor upon return.*
|
||||
|
||||
|
||||
---
|
||||
|
||||
## ADDITIONAL
|
||||
|
||||
- **Languages:** English (business), Japanese (JLPT N1), Malay (native)
|
||||
- **Homelab:** Self-hosted k3s cluster, Gitea, Jellyfin, Cloudflare
|
||||
Tunnel, Ansible-based IaC on Minisforum UM790 Pro
|
||||
- **Dev blog / personal site:** nik4nao.com
|
||||
- **Self-hosted Git:** git.nik4nao.com (mirrored to github.com/nikafiq)
|
||||
14
content/posts/hello-world.md
Normal file
14
content/posts/hello-world.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: "Hello World"
|
||||
date: 2026-03-17
|
||||
draft: false
|
||||
tags: ["meta"]
|
||||
---
|
||||
|
||||
Welcome to my corner of the internet.
|
||||
|
||||
This site is where I write about things I'm building, breaking, and learning — mostly homelabs,
|
||||
Kubernetes, and the occasional software project. Expect posts about infrastructure, self-hosting,
|
||||
and whatever rabbit hole I've fallen down most recently.
|
||||
|
||||
If you want to see what I'm currently working on, check out the [projects](/projects) page.
|
||||
8
content/projects/_index.md
Normal file
8
content/projects/_index.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
title: "Projects"
|
||||
date: 2026-03-17
|
||||
draft: false
|
||||
---
|
||||
|
||||
A collection of things I've built or am currently working on — mostly self-hosted infrastructure,
|
||||
homelab experiments, and open-source tooling.
|
||||
54
content/projects/homelab.md
Normal file
54
content/projects/homelab.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "Homelab Kubernetes Cluster"
|
||||
date: 2026-03-17
|
||||
draft: false
|
||||
description: "Self-hosted k3s cluster on bare-metal with Gitea CI/CD, multi-arch builds, Authentik SSO, and ~15 running workloads."
|
||||
tags: ["kubernetes", "k3s", "homelab", "infrastructure", "traefik", "authentik"]
|
||||
github: ""
|
||||
url: ""
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
A self-hosted Kubernetes cluster running on bare-metal hardware at home. The cluster serves as a
|
||||
platform for running personal services, experimenting with cloud-native tooling, and learning
|
||||
operational patterns without a cloud bill.
|
||||
|
||||
## Hardware
|
||||
|
||||
| Host | Role | Specs |
|
||||
|---|---|---|
|
||||
| Minisforum UM780 XTX | K3s control-plane | AMD Ryzen 7 8745H |
|
||||
| HP ProDesk (nik-debian) | K3s storage agent | NFS server, mergerfs media pool |
|
||||
| Mac Mini M2 | Standalone Docker host | ARM, outside the cluster |
|
||||
|
||||
## Stack
|
||||
|
||||
- **Distribution:** k3s
|
||||
- **Ingress:** Traefik v3
|
||||
- **TLS:** cert-manager — Let's Encrypt (public) + internal CA (LAN)
|
||||
- **Auth:** Authentik SSO — OIDC + forwardAuth proxy, TOTP MFA enforced
|
||||
- **DNS:** Pihole (primary + secondary, externalIPs)
|
||||
- **Storage:** NFS (Debian) + local-path dynamic provisioner
|
||||
- **CI/CD:** Gitea Actions + act_runner, Docker buildx multiarch (amd64 + arm64)
|
||||
- **Registry:** Gitea built-in container registry
|
||||
- **Observability:** Prometheus + Grafana + Loki + Promtail
|
||||
- **IaC:** Ansible (host-level), Helm + raw manifests (cluster-level), all tracked in Gitea
|
||||
|
||||
## Highlights
|
||||
|
||||
- All cluster state is managed as code in a Gitea monorepo — single-file manifests per service, organised by concern
|
||||
- Authentik SSO protects all web-facing services via Traefik forwardAuth; OIDC integrated with Gitea and Grafana
|
||||
- Multi-arch image builds (amd64 + arm64) via buildx on every push to `main`, pushed to the self-hosted registry
|
||||
- Dual-cert TLS strategy: internal CA for `*.home.arpa` services, Let's Encrypt for `*.nik4nao.com` public services
|
||||
- Pihole running as primary + secondary with externalIPs for LAN-wide DNS and ad-blocking
|
||||
- DDNS CronJob keeps the public A record in sync via the Porkbun API
|
||||
|
||||
## Running Workloads
|
||||
|
||||
Traefik, cert-manager, Pihole, Authentik, Gitea, Prometheus, Grafana, Loki, Promtail,
|
||||
Jellyfin, qBittorrent, JDownloader, Photoview, Dashy, Glances, DDNS CronJob, this portfolio site.
|
||||
|
||||
## Status
|
||||
|
||||
Active and in daily use.
|
||||
54
hugo.toml
Normal file
54
hugo.toml
Normal file
@ -0,0 +1,54 @@
|
||||
baseURL = "https://nik4nao.com/"
|
||||
languageCode = "en-us"
|
||||
title = "nik4nao"
|
||||
theme = "terminal"
|
||||
|
||||
[params]
|
||||
# dir name of your main content (default is `content/posts`).
|
||||
# the list of set content will show up on your index page (baseurl).
|
||||
contentTypeName = "posts"
|
||||
|
||||
# ["orange", "blue", "red", "green", "pink"]
|
||||
themeColor = "orange"
|
||||
|
||||
# if you set this to 0, only metadata of posts will appear
|
||||
fullWidthTheme = false
|
||||
|
||||
# centered theme with any value (e.g. "true")
|
||||
centerTheme = false
|
||||
|
||||
# if your resource directory contains an image called `cover.png`,
|
||||
# it will be used as the cover of your blog
|
||||
showCoverImage = true
|
||||
|
||||
# set terminal prompt
|
||||
terminalPrompt = "nik@nik4nao ~ $"
|
||||
|
||||
# show/hide posts list on start page
|
||||
showMenuItems = 3
|
||||
|
||||
# show a footer instead of the HUGO signature
|
||||
# customFooter = ""
|
||||
|
||||
# set theme to full screen width
|
||||
# fullWidthTheme = false
|
||||
|
||||
[[params.menu]]
|
||||
identifier = "posts"
|
||||
name = "posts"
|
||||
url = "/posts"
|
||||
|
||||
[[params.menu]]
|
||||
identifier = "projects"
|
||||
name = "projects"
|
||||
url = "/projects"
|
||||
|
||||
[[params.menu]]
|
||||
identifier = "cv"
|
||||
name = "cv"
|
||||
url = "/cv"
|
||||
|
||||
[taxonomies]
|
||||
tag = "tags"
|
||||
|
||||
paginate = 5
|
||||
10
layouts/cv/single.html
Normal file
10
layouts/cv/single.html
Normal file
@ -0,0 +1,10 @@
|
||||
{{ define "main" }}
|
||||
<article class="post">
|
||||
<div class="cv-download">
|
||||
<a href="/cv/nik-afiq-cv.pdf" download class="cv-download-btn">↓ Download PDF</a>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</article>
|
||||
{{ end }}
|
||||
38
layouts/index.html
Normal file
38
layouts/index.html
Normal file
@ -0,0 +1,38 @@
|
||||
{{ define "main" }}
|
||||
<div class="index-content">
|
||||
|
||||
{{/* ── Hero / intro ───────────────────────────────────────────────────── */}}
|
||||
<div class="index-hero">
|
||||
<p class="index-intro">
|
||||
Backend engineer based in Tokyo. I build distributed systems,
|
||||
operate Kubernetes infrastructure, and occasionally write about it.
|
||||
</p>
|
||||
<ul class="index-nav">
|
||||
{{ range .Site.Params.menu }}
|
||||
<li>
|
||||
<span class="prompt">{{ $.Site.Params.terminalPrompt }}</span>
|
||||
<a href="{{ .url }}">cd {{ .name }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{{/* ── Recent posts ────────────────────────────────────────────────────── */}}
|
||||
{{ $posts := where .Site.RegularPages "Type" .Site.Params.contentTypeName }}
|
||||
{{ if $posts }}
|
||||
<section class="index-posts">
|
||||
<h2>Recent Posts</h2>
|
||||
{{ range first 5 $posts }}
|
||||
<article class="post-preview">
|
||||
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "2006-01-02" }}</time>
|
||||
<a href="{{ .Permalink }}">{{ .Title }}</a>
|
||||
</article>
|
||||
{{ end }}
|
||||
{{ if gt (len $posts) 5 }}
|
||||
<p class="index-all-posts"><a href="/posts">All posts →</a></p>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
</div>
|
||||
{{ end }}
|
||||
1
layouts/partials/extended_head.html
Normal file
1
layouts/partials/extended_head.html
Normal file
@ -0,0 +1 @@
|
||||
<link rel="stylesheet" href="/css/custom.css">
|
||||
36
layouts/projects/list.html
Normal file
36
layouts/projects/list.html
Normal file
@ -0,0 +1,36 @@
|
||||
{{ define "main" }}
|
||||
<div class="projects-page">
|
||||
<header>
|
||||
<h1 class="post-title">{{ .Title }}</h1>
|
||||
{{ with .Content }}
|
||||
<div class="page-intro">{{ . }}</div>
|
||||
{{ end }}
|
||||
</header>
|
||||
|
||||
<div class="project-grid">
|
||||
{{ range .Pages }}
|
||||
<div class="project-card">
|
||||
<h2 class="project-card__title">
|
||||
<a href="{{ .Permalink }}">{{ .Title }}</a>
|
||||
</h2>
|
||||
|
||||
{{ with .Params.description }}
|
||||
<p class="project-card__desc">{{ . }}</p>
|
||||
{{ end }}
|
||||
|
||||
{{ with .Params.tags }}
|
||||
<ul class="project-tags">
|
||||
{{ range . }}<li>{{ . }}</li>{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
<div class="project-card__links">
|
||||
{{ with .Params.github }}<a href="{{ . }}" target="_blank" rel="noopener">GitHub →</a>{{ end }}
|
||||
{{ with .Params.url }}<a href="{{ . }}" target="_blank" rel="noopener">Live →</a>{{ end }}
|
||||
<a href="{{ .Permalink }}">Details →</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
32
layouts/projects/single.html
Normal file
32
layouts/projects/single.html
Normal file
@ -0,0 +1,32 @@
|
||||
{{ define "main" }}
|
||||
<article class="post">
|
||||
<header class="project-header">
|
||||
<h1 class="post-title">{{ .Title }}</h1>
|
||||
|
||||
{{ with .Params.description }}
|
||||
<p class="project-description">{{ . }}</p>
|
||||
{{ end }}
|
||||
|
||||
{{ with .Params.tags }}
|
||||
<ul class="project-tags">
|
||||
{{ range . }}<li>{{ . }}</li>{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
{{ if or .Params.github .Params.url }}
|
||||
<div class="project-links">
|
||||
{{ with .Params.github }}<a href="{{ . }}" target="_blank" rel="noopener">GitHub →</a>{{ end }}
|
||||
{{ with .Params.url }}<a href="{{ . }}" target="_blank" rel="noopener">Live Site →</a>{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</header>
|
||||
|
||||
<div class="post-content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
|
||||
<footer class="post-footer">
|
||||
<a href="/projects">← Back to Projects</a>
|
||||
</footer>
|
||||
</article>
|
||||
{{ end }}
|
||||
216
static/css/custom.css
Normal file
216
static/css/custom.css
Normal file
@ -0,0 +1,216 @@
|
||||
/* ─── CV page ─────────────────────────────────────────────────────────────── */
|
||||
|
||||
.cv-download {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.cv-download-btn {
|
||||
display: inline-block;
|
||||
padding: 0.4rem 1rem;
|
||||
border: 1px solid var(--accent);
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.05em;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.cv-download-btn:hover {
|
||||
background: var(--accent);
|
||||
color: var(--background);
|
||||
}
|
||||
|
||||
/* ─── Projects list ────────────────────────────────────────────────────────── */
|
||||
|
||||
.projects-page .page-intro {
|
||||
margin-bottom: 2.5rem;
|
||||
color: var(--color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.project-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.project-card {
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 1.25rem 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.project-card__title {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.project-card__title a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.project-card__title a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.project-card__desc {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.85;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* ─── Tags (shared by list and detail) ────────────────────────────────────── */
|
||||
|
||||
.project-tags {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.project-tags li {
|
||||
font-size: 0.75rem;
|
||||
padding: 0.15rem 0.5rem;
|
||||
border: 1px solid var(--border-color);
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* ─── Project links (shared) ───────────────────────────────────────────────── */
|
||||
|
||||
.project-card__links,
|
||||
.project-links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.project-card__links a,
|
||||
.project-links a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.project-card__links a:hover,
|
||||
.project-links a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ─── Project detail page ──────────────────────────────────────────────────── */
|
||||
|
||||
.project-header {
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.project-description {
|
||||
font-size: 1rem;
|
||||
opacity: 0.85;
|
||||
margin: 0.5rem 0 1rem;
|
||||
}
|
||||
|
||||
.post-footer {
|
||||
margin-top: 3rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.post-footer a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.post-footer a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ─── Homepage ─────────────────────────────────────────────────────────────── */
|
||||
|
||||
.index-hero {
|
||||
margin-bottom: 2.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.index-intro {
|
||||
margin: 0 0 1.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.6;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.index-nav {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem 2rem;
|
||||
}
|
||||
|
||||
.index-nav li {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.index-nav .prompt {
|
||||
opacity: 0.5;
|
||||
margin-right: 0.4rem;
|
||||
}
|
||||
|
||||
.index-nav a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.index-nav a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.index-posts h2 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.post-preview {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 1rem;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.post-preview time {
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.post-preview a {
|
||||
color: var(--color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.post-preview a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.index-all-posts {
|
||||
margin-top: 1.25rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.index-all-posts a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.index-all-posts a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
1
themes/terminal
Submodule
1
themes/terminal
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 5a2b4c0f1fdb9180d525930b2c8f68a90221d245
|
||||
Loading…
x
Reference in New Issue
Block a user