mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-11 03:12:56 +00:00
feat: standardize author profiles & add devcontainer
This commit is contained in:
1 parent
75234c306b
commit
f0eb4a7e9c
80 files changed
+1327
-1019
No files matched your search
@@ -3,6 +3,7 @@
|
||||
"files": {
|
||||
"includes": [
|
||||
"**",
|
||||
"!modules/**/*.html",
|
||||
"!**/node_modules",
|
||||
"!**/public",
|
||||
"!**/resources",
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
border: 1px solid #a8e9e9;
|
||||
border: 1px solid var(--color-primary-200, #cbd5f5);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@@ -54,5 +54,5 @@
|
||||
position: absolute;
|
||||
width: 60%;
|
||||
height: 10px;
|
||||
background-color: #3cb5b5;
|
||||
background-color: var(--color-primary-600, #2563eb);
|
||||
}
|
||||
@@ -7,7 +7,7 @@ Showcase your professional accomplishments, certifications, and awards with the
|
||||
## ✨ Key Features
|
||||
|
||||
- **Professional Cards**: Clean, shadowed card design for each award or certification
|
||||
- **Icon Integration**: Brand icons for certifying organizations and institutions
|
||||
- **Icon Integration**: Add per-award icons (e.g., trophy, badge) for instant visual cues
|
||||
- **Certificate Links**: Direct links to verify credentials with proper external link handling
|
||||
- **Date Formatting**: Customizable date display (month/year format by default)
|
||||
- **Markdown Support**: Rich text formatting for award titles and descriptions
|
||||
@@ -55,4 +55,3 @@ Showcase your professional accomplishments, certifications, and awards with the
|
||||
- **Brand Integration**: Certifying organization icons add visual interest and authenticity
|
||||
|
||||
Perfect for professionals, academics, consultants, and anyone who wants to showcase their achievements in a format that builds confidence and demonstrates expertise. Your accomplishments deserve professional presentation.
|
||||
|
||||
@@ -5,14 +5,9 @@
|
||||
{{/* Initialise */}}
|
||||
{{ $page := .wcPage }}
|
||||
{{ $block := .wcBlock }}
|
||||
{{ $author := $block.content.username | default "admin" }}
|
||||
|
||||
{{ $person_page_path := (printf "/authors/%s" $author) }}
|
||||
{{ $person_page := site.GetPage $person_page_path }}
|
||||
{{ if not $person_page }}
|
||||
{{ errorf "Could not find an author page at `%s`. Please check the value of `author` in your Skill block and create an associated author page if one does not already exist. See https://docs.hugoblox.com/page-builder/#about " $person_page_path }}
|
||||
{{end}}
|
||||
{{ $awards := $person_page.Params.awards }}
|
||||
{{ $author := $block.content.username | default "me" }}
|
||||
{{ $profile := partial "functions/get_author_profile" $author }}
|
||||
{{ $awards := $profile.awards }}
|
||||
|
||||
<div class="flex flex-col items-center max-w-prose mx-auto gap-3 justify-center">
|
||||
|
||||
@@ -24,25 +19,29 @@
|
||||
|
||||
<div class="w-full flex flex-col gap-6">
|
||||
{{ if $awards }}
|
||||
{{ range $idx, $key := sort $awards ".date_start" "desc" }}
|
||||
{{ range $idx, $key := sort $awards ".date" "desc" }}
|
||||
<div class="w-full p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
|
||||
{{- $icon := .icon }}
|
||||
{{ with $icon }}
|
||||
<div class="w-7 h-7 text-gray-500 dark:text-gray-400 mb-3">
|
||||
{{ partial "functions/get_icon" (dict "name" $icon "attributes" "style=\"height: 100%;\"") }}
|
||||
</div>
|
||||
{{ end}}
|
||||
{{with .url}}<a href={{.}} target="_blank" rel="noopener">{{end}}
|
||||
<h5 class="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">{{.title | markdownify | emojify}}</h5>
|
||||
<h5 class="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white flex items-center gap-2">
|
||||
{{ with $icon }}
|
||||
<span class="inline-flex items-center justify-center w-7 h-7 text-primary-600 dark:text-primary-300">
|
||||
{{ partial "functions/get_icon" (dict "name" . "attributes" "class='w-6 h-6'") }}
|
||||
</span>
|
||||
{{ end }}
|
||||
<span>{{.title | markdownify | emojify}}</span>
|
||||
</h5>
|
||||
{{with .url}}</a>{{end}}
|
||||
|
||||
<div class="block mb-3 text-sm font-normal leading-none text-gray-500 dark:text-gray-300">
|
||||
{{.awarder}} ∙
|
||||
{{ if .date}}
|
||||
{{ .awarder }} ∙
|
||||
{{ if .date }}
|
||||
{{ (time .date) | time.Format ($block.design.date_format | default "January 2006") }}
|
||||
{{else}}
|
||||
{{ else if .date_start }}
|
||||
{{ (time .date_start) | time.Format ($block.design.date_format | default "January 2006") }}
|
||||
{{ else }}
|
||||
{{ i18n "present" | default "Present" }}
|
||||
{{end}}
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{with .summary}}
|
||||
|
||||
@@ -6,6 +6,11 @@ Present a complete professional picture with the Resume Biography 3 block - an e
|
||||
|
||||
## 🛠️ Customization
|
||||
|
||||
- **Name sizing**: Adjust the profile heading size to accommodate long names using `design.name.size`:
|
||||
- `compact`: space-friendly for long names
|
||||
- `balanced` (default): matches the demo style
|
||||
- `display`: extra-large for short names
|
||||
|
||||
- **Section heading overrides**: Customize any of the three main section headings using `content.headings`:
|
||||
- `about`: Biography section heading (default: "Professional Summary" from i18n `about_me`)
|
||||
- `education`: Education section heading (default: from i18n `education`)
|
||||
@@ -20,6 +25,9 @@ content:
|
||||
about: Research Profile
|
||||
education: Academic Background
|
||||
interests: Research Areas
|
||||
design:
|
||||
name:
|
||||
size: compact
|
||||
```
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
@@ -6,20 +6,23 @@
|
||||
{{ $page := .wcPage }}
|
||||
{{ $block := .wcBlock }}
|
||||
|
||||
{{ $author := $block.content.username | default "admin" }}
|
||||
|
||||
{{ $person_page_path := (printf "/authors/%s" $author) }}
|
||||
{{ $person_page := site.GetPage $person_page_path }}
|
||||
{{ if not $person_page }}
|
||||
{{ errorf "Could not find an author page at `%s`. Please check the value of `author` in your About widget and create an associated author page if one does not already exist. See https://docs.hugoblox.com/page-builder/#about " $person_page_path }}
|
||||
{{end}}
|
||||
{{ $person := $person_page.Params }}
|
||||
{{ $avatar := ($person_page.Resources.ByType "image").GetMatch "*avatar*" }}
|
||||
{{ $author := $block.content.username | default "me" }}
|
||||
{{ $profile := partial "functions/get_author_profile" $author }}
|
||||
{{ $avatar := $profile.avatar }}
|
||||
|
||||
{{/* Avatar customization parameters */}}
|
||||
{{ $avatar_size := $block.design.avatar.size | default "large" }}
|
||||
{{ $avatar_shape := $block.design.avatar.shape | default "circle" }}
|
||||
|
||||
{{/* Profile name typography */}}
|
||||
{{ $name_size := $block.design.name.size | default "balanced" }}
|
||||
{{ $name_class_map := dict
|
||||
"compact" "text-3xl sm:text-4xl lg:text-5xl"
|
||||
"balanced" "text-4xl sm:text-5xl lg:text-6xl"
|
||||
"display" "text-5xl sm:text-6xl lg:text-7xl"
|
||||
}}
|
||||
{{ $name_class := index $name_class_map $name_size | default (index $name_class_map "balanced") }}
|
||||
|
||||
{{/* Size mappings optimized for 2025 standards: display_size -> [display_px, generation_px] */}}
|
||||
{{ $size_map := dict "small" (slice "150" "300") "medium" (slice "200" "400") "large" (slice "320" "640") "xl" (slice "400" "800") "xxl" (slice "500" "1000") }}
|
||||
{{ $size_config := index $size_map $avatar_size | default (index $size_map "large") }}
|
||||
@@ -68,40 +71,33 @@
|
||||
|
||||
{{/* Avatar */}}
|
||||
{{ if $avatar }}
|
||||
<div class="avatar-wrapper {{ if $img }}-mt-24{{else}}mb-4{{end}}" style="width: {{$display_size}}px; height: {{$display_size}}px;">
|
||||
<div class="avatar-wrapper {{ if $img }}-mt-24{{else}}mb-4{{end}}">
|
||||
{{ $avatar_image := $avatar.Fill (printf "%sx%s Center" $generation_size $generation_size) }}
|
||||
<img class="avatar {{$shape_class}} border-4 border-white shadow-2xl"
|
||||
src="{{ $avatar_image.RelPermalink }}"
|
||||
alt="{{$person_page.Title}}"
|
||||
alt="{{$profile.title}}"
|
||||
width="{{$display_size}}"
|
||||
height="{{$display_size}}"
|
||||
style="width: {{$display_size}}px; height: {{$display_size}}px; object-fit: cover;">
|
||||
{{with $person.status.icon}}<span class="avatar-emoji">{{.|emojify}}</span>{{end}}
|
||||
style="object-fit: cover;">
|
||||
{{with $profile.status.icon}}<span class="avatar-emoji">{{.|emojify}}</span>{{end}}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{/* Name and Role - Centered */}}
|
||||
<div class="space-y-3">
|
||||
<h1 class="text-5xl lg:text-6xl font-black text-gray-900 dark:text-white leading-tight">
|
||||
{{- if $person.name_pronunciation -}}
|
||||
<ruby>
|
||||
<rb>{{ $person_page.Title }}</rb>
|
||||
<rt class="text-sm text-gray-500 dark:text-gray-400">{{ $person.name_pronunciation }}</rt>
|
||||
</ruby>
|
||||
{{- else -}}
|
||||
{{- $person_page.Title -}}
|
||||
{{- end -}}
|
||||
<h1 class="{{ $name_class }} font-black text-gray-900 dark:text-white leading-tight">
|
||||
{{ $profile.title }}
|
||||
</h1>
|
||||
|
||||
{{- with $person.pronouns -}}
|
||||
{{- with $profile.pronouns -}}
|
||||
<p class="text-lg text-gray-600 dark:text-gray-400">({{ . }})</p>
|
||||
{{- end -}}
|
||||
|
||||
{{ with $person.role }}
|
||||
{{ with $profile.role }}
|
||||
<p class="text-2xl font-semibold text-primary-600 dark:text-primary-400">{{ . | markdownify | emojify }}</p>
|
||||
{{ end }}
|
||||
|
||||
{{ range $person.organizations }}
|
||||
{{ range $profile.affiliations }}
|
||||
<p class="text-lg text-gray-700 dark:text-gray-300">
|
||||
{{ with .url }}<a href="{{ . }}" target="_blank" rel="noopener" class="hover:text-primary-600 dark:hover:text-primary-400 transition-colors">{{ end }}
|
||||
{{ .name }}
|
||||
@@ -112,12 +108,7 @@
|
||||
|
||||
{{/* Social Icons */}}
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
{{ range $person.profiles }}
|
||||
{{ $pack := or .icon_pack "fas" }}
|
||||
{{ $pack_prefix := $pack }}
|
||||
{{ if in (slice "fab" "fas" "far" "fal") $pack }}
|
||||
{{ $pack_prefix = "fa" }}
|
||||
{{ end }}
|
||||
{{ range $profile.links }}
|
||||
{{ $link := .url | default .link }}
|
||||
{{ $scheme := (urls.Parse $link).Scheme }}
|
||||
{{ $target := "" }}
|
||||
@@ -143,7 +134,8 @@
|
||||
<div class="md:col-span-8">
|
||||
|
||||
{{/* Bio Section */}}
|
||||
{{ with ($block.content.text | emojify | $page.RenderString) | default $person_page.Content }}
|
||||
{{ $bio_content := ($block.content.text | emojify | $page.RenderString) | default $profile.bio }}
|
||||
{{ with $bio_content }}
|
||||
<div class="mb-12">
|
||||
<div class="flex items-center gap-4 mb-8">
|
||||
<div class="flex-shrink-0 w-12 h-12 bg-primary-100 dark:bg-primary-900/50 rounded-full flex items-center justify-center">
|
||||
@@ -174,7 +166,7 @@
|
||||
{{ end }}
|
||||
|
||||
{{/* Education Section */}}
|
||||
{{ with $person.education }}
|
||||
{{ with $profile.education }}
|
||||
<div class="mb-16">
|
||||
<div class="flex items-center gap-4 mb-8">
|
||||
<div class="flex-shrink-0 w-12 h-12 bg-primary-100 dark:bg-primary-900/50 rounded-full flex items-center justify-center">
|
||||
@@ -195,9 +187,12 @@
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="flex-1 flex-grow">
|
||||
{{ $degree := .degree | default .area }}
|
||||
{{ $year := .year | default (cond (and .start .end) (printf "%s - %s" .start .end) .start) }}
|
||||
<p class="text-xl font-bold text-gray-900 dark:text-white group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors">
|
||||
{{ .area }}{{ with .year }}, {{ . }}{{ end }}
|
||||
{{ $degree }}
|
||||
</p>
|
||||
{{ with $year }}<p class="text-gray-600 dark:text-gray-400 font-medium mt-1">{{ . }}</p>{{ end }}
|
||||
<p class="text-gray-600 dark:text-gray-400 font-medium mt-1">{{ .institution }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -208,7 +203,7 @@
|
||||
{{ end }}
|
||||
|
||||
{{/* Interests Section */}}
|
||||
{{ with $person.interests }}
|
||||
{{ with $profile.interests }}
|
||||
<div>
|
||||
<div class="flex items-center gap-4 mb-8">
|
||||
<div class="flex-shrink-0 w-12 h-12 bg-primary-100 dark:bg-primary-900/50 rounded-full flex items-center justify-center">
|
||||
@@ -232,4 +227,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -106,6 +106,18 @@
|
||||
"description": "Custom CSS styles for biography text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "object",
|
||||
"description": "Profile name typography controls",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "string",
|
||||
"enum": ["compact", "balanced", "display"],
|
||||
"description": "Heading size for the profile name to suit different name lengths",
|
||||
"default": "balanced"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,9 @@
|
||||
{{ $page := .wcPage }}
|
||||
{{ $block := .wcBlock }}
|
||||
|
||||
{{ $author := $block.content.username | default "admin" }}
|
||||
|
||||
{{ $person_page_path := (printf "/authors/%s" $author) }}
|
||||
{{ $person_page := site.GetPage $person_page_path }}
|
||||
{{ if not $person_page }}
|
||||
{{ errorf "Could not find an author page at `%s`. Please check the value of `author` in your About widget and create an associated author page if one does not already exist. See https://docs.hugoblox.com/page-builder/#about " $person_page_path }}
|
||||
{{end}}
|
||||
{{ $person := $person_page.Params }}
|
||||
{{ $avatar := ($person_page.Resources.ByType "image").GetMatch "*avatar*" }}
|
||||
{{ $author := $block.content.username | default "me" }}
|
||||
{{ $profile := partial "functions/get_author_profile" $author }}
|
||||
{{ $avatar := $profile.avatar }}
|
||||
|
||||
{{/* Avatar customization parameters */}}
|
||||
{{ $avatar_size := $block.design.avatar.size | default "medium" }}
|
||||
@@ -76,30 +70,23 @@
|
||||
|
||||
<div class="avatar-wrapper {{ if $img }}-mt-[105px]{{else}}mt-10{{end}}" style="width: {{$display_size}}px; height: {{$display_size}}px;">
|
||||
{{ $avatar_image := $avatar.Fill (printf "%sx%s Center" $generation_size $generation_size) }}
|
||||
<img class="avatar {{$shape_class}} bg-white dark:bg-gray-800 p-1" src="{{ $avatar_image.RelPermalink }}" alt="{{$person_page.Title}}"
|
||||
<img class="avatar {{$shape_class}} bg-white dark:bg-gray-800 p-1" src="{{ $avatar_image.RelPermalink }}" alt="{{$profile.title}}"
|
||||
width="{{$display_size}}" height="{{$display_size}}"
|
||||
style="width: {{$display_size}}px; height: {{$display_size}}px; object-fit: cover;">
|
||||
{{with $person.status.icon}}<span class="avatar-emoji">{{.|emojify}}</span>{{end}}
|
||||
{{with $profile.status.icon}}<span class="avatar-emoji">{{.|emojify}}</span>{{end}}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="text-3xl font-bold mb-2 mt-6">
|
||||
{{- if $person.name_pronunciation -}}
|
||||
<ruby>
|
||||
<rb>{{ $person_page.Title }}</rb>
|
||||
<rt>{{ $person.name_pronunciation }}</rt>
|
||||
</ruby>
|
||||
{{- else -}}
|
||||
{{- $person_page.Title -}}
|
||||
{{- end -}}
|
||||
{{- $profile.title -}}
|
||||
</div>
|
||||
{{- with $person.pronouns -}}
|
||||
{{- with $profile.pronouns -}}
|
||||
<div class="text-lg font-normal text-gray-600 dark:text-gray-400 -mt-1 mb-2">({{ . }})</div>
|
||||
{{- end -}}
|
||||
|
||||
{{ with $person.role }}<h3 class="font-semibold mb-1">{{ . | markdownify | emojify }}</h3>{{ end }}
|
||||
{{ with $profile.role }}<h3 class="font-semibold mb-1">{{ . | markdownify | emojify }}</h3>{{ end }}
|
||||
|
||||
{{ range $person.organizations }}
|
||||
{{ range $profile.affiliations }}
|
||||
<div class="mb-2">
|
||||
{{ with .url }}<a href="{{ . }}" target="_blank" rel="noopener">{{ end }}
|
||||
<div>{{ .name }}</div>
|
||||
@@ -107,13 +94,9 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if $profile.links }}
|
||||
<ul class="network-icon dark:text-zinc-100">
|
||||
{{ range $person.profiles }}
|
||||
{{ $pack := or .icon_pack "fas" }}
|
||||
{{ $pack_prefix := $pack }}
|
||||
{{ if in (slice "fab" "fas" "far" "fal") $pack }}
|
||||
{{ $pack_prefix = "fa" }}
|
||||
{{ end }}
|
||||
{{ range $profile.links }}
|
||||
{{ $link := .url | default .link }}
|
||||
{{ $scheme := (urls.Parse $link).Scheme }}
|
||||
{{ $target := "" }}
|
||||
@@ -131,8 +114,10 @@
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
{{ with ($block.content.text | emojify | $page.RenderString) | default $person_page.Content }}
|
||||
{{ $bio_content := ($block.content.text | emojify | $page.RenderString) | default $profile.bio }}
|
||||
{{ with $bio_content }}
|
||||
<div class="pt-2 d-flex justify-content-center prose prose-slate lg:prose-xl dark:prose-invert">
|
||||
<div class="bio-text" {{ with $block.design.biography.style }}{{ (printf "style=\"%s\"" .) | safe.HTMLAttr }}{{end}}>
|
||||
{{ . }}
|
||||
|
||||
@@ -7,13 +7,8 @@
|
||||
{{ $block := .wcBlock }}
|
||||
{{ $text := $block.content.text | emojify | $page.RenderString }}
|
||||
|
||||
{{ $author := $block.content.username | default "admin" }}
|
||||
{{ $person_page_path := (printf "/authors/%s" $author) }}
|
||||
{{ $person_page := site.GetPage $person_page_path }}
|
||||
{{ if not $person_page }}
|
||||
{{ errorf "Could not find an author page at `%s`. Please check the value of `author` in your About widget and create an associated author page if one does not already exist. See https://docs.hugoblox.com/page-builder/#about " $person_page_path }}
|
||||
{{end}}
|
||||
{{ $person := $person_page.Params }}
|
||||
{{ $author := $block.content.username | default "me" }}
|
||||
{{ $profile := partial "functions/get_author_profile" $author }}
|
||||
{{ $is_education_first := $block.design.is_education_first | default false }}
|
||||
|
||||
<div class="flex flex-col items-center mx-auto w-full max-w-prose justify-center">
|
||||
@@ -26,11 +21,12 @@
|
||||
<!-- Need Gap >= 3 when flex-row due to negative margin on cols (-start-3) -->
|
||||
<div class="flex flex-col lg:gap-x-6 w-full px-6 sm:px-0 {{ if $is_education_first }}flex-col-reverse{{end}}">
|
||||
|
||||
{{ if $person.work }}
|
||||
{{ $experience := or $profile.experience $profile.work }}
|
||||
{{ if $experience }}
|
||||
<div class="w-full">
|
||||
<h3 class="mb-6 text-3xl font-bold text-gray-900 dark:text-white text-center">{{ i18n "experience" | default "Experience" }}</h3>
|
||||
<ol class="relative w-full border-s border-gray-200 dark:border-gray-700">
|
||||
{{ range $idx, $key := $person.work }}
|
||||
{{ range $idx, $key := $experience }}
|
||||
<li class="mb-10 ms-6">
|
||||
<span class="absolute flex items-center justify-center w-6 h-6 bg-primary-100 rounded-full -start-3 ring-8 ring-white dark:ring-gray-900 dark:bg-primary-900">
|
||||
{{ if .icon }}
|
||||
@@ -39,27 +35,31 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 256 256" class="w-5 h-5 text-primary-800 dark:text-primary-300"><path d="M216,56H176V48a24,24,0,0,0-24-24H104A24,24,0,0,0,80,48v8H40A16,16,0,0,0,24,72V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V72A16,16,0,0,0,216,56ZM96,48a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96ZM216,72v41.61A184,184,0,0,1,128,136a184.07,184.07,0,0,1-88-22.38V72Zm0,128H40V131.64A200.19,200.19,0,0,0,128,152a200.25,200.25,0,0,0,88-20.37V200ZM104,112a8,8,0,0,1,8-8h32a8,8,0,0,1,0,16H112A8,8,0,0,1,104,112Z"></path></svg>
|
||||
{{end}}
|
||||
</span>
|
||||
<h3 class="flex items-center mb-1 text-lg font-semibold text-gray-900 dark:text-white">{{.position}}
|
||||
<h3 class="flex items-center mb-1 text-lg font-semibold text-gray-900 dark:text-white">{{ .role | default .position }}
|
||||
<!-- <span class="bg-blue-100 text-blue-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300 ms-3">Latest</span>-->
|
||||
</h3>
|
||||
<span class="block mb-2 text-sm font-normal leading-none text-gray-500 dark:text-gray-300">{{.company_name}}</span>
|
||||
<span class="block mb-2 text-sm font-normal leading-none text-gray-500 dark:text-gray-300">{{ .org | default .company_name }}</span>
|
||||
<time class="block mb-3 text-sm font-normal leading-none text-gray-500 dark:text-gray-300">
|
||||
{{ if .date_start}}
|
||||
{{ (time .date_start) | time.Format ($block.design.date_format | default "January 2006") }} –
|
||||
{{ $start := or .start .date_start }}
|
||||
{{ $end := or .end .date_end }}
|
||||
{{ if $start }}
|
||||
{{ (time $start) | time.Format ($block.design.date_format | default "January 2006") }} –
|
||||
{{ end }}
|
||||
{{ if .date_end}}
|
||||
{{ (time .date_end) | time.Format ($block.design.date_format | default "January 2006") }}
|
||||
{{else}}
|
||||
{{ if $end }}
|
||||
{{ (time $end) | time.Format ($block.design.date_format | default "January 2006") }}
|
||||
{{ else }}
|
||||
{{ i18n "present" | default "Present" }}
|
||||
{{end}}
|
||||
</time>
|
||||
<div class="mb-4 text-base font-normal text-gray-500 dark:text-gray-300 prose max-w-none prose-slate dark:prose-invert">{{.summary | $page.RenderString}}</div>
|
||||
|
||||
{{ with .button }}
|
||||
<a href="{{.url}}" target="_blank" rel="noopener" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg transition-colors hover:bg-gray-100 hover:text-gray-900 focus:z-10 focus:ring-4 focus:outline-none focus:ring-gray-200 focus:text-gray-900 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:text-white dark:focus:ring-gray-700"><svg class="w-3.5 h-3.5 me-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M14.707 7.793a1 1 0 0 0-1.414 0L11 10.086V1.5a1 1 0 0 0-2 0v8.586L6.707 7.793a1 1 0 1 0-1.414 1.414l4 4a1 1 0 0 0 1.416 0l4-4a1 1 0 0 0-.002-1.414Z"/>
|
||||
<path d="M18 12h-2.55l-2.975 2.975a3.5 3.5 0 0 1-4.95 0L4.55 12H2a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2Zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/>
|
||||
</svg> {{.text}}</a>
|
||||
<a href="{{.url}}" target="_blank" rel="noopener" class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg transition-colors hover:bg-gray-100 hover:text-gray-900 focus:z-10 focus:ring-4 focus:outline-none focus:ring-gray-200 focus:text-gray-900 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:text-white dark:focus:ring-gray-700">
|
||||
{{ with .icon }}
|
||||
{{ partial "functions/get_icon" (dict "name" . "attributes" "class='w-4 h-4'") }}
|
||||
{{ end }}
|
||||
{{ .text | default (i18n "learn_more" | default "Learn more") }}
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
</li>
|
||||
@@ -68,11 +68,11 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if $person.education }}
|
||||
{{ if $profile.education }}
|
||||
<div class="w-full">
|
||||
<h3 class="mb-6 text-3xl font-bold text-gray-900 dark:text-white text-center">{{ i18n "education" }}</h3>
|
||||
<ol class="relative w-full border-s border-gray-200 dark:border-gray-700">
|
||||
{{ range $idx, $key := $person.education }}
|
||||
{{ range $idx, $key := $profile.education }}
|
||||
<li class="mb-10 ms-6">
|
||||
<span class="absolute flex items-center justify-center w-6 h-6 bg-primary-100 rounded-full -start-3 ring-8 ring-white dark:ring-gray-900 dark:bg-primary-900">
|
||||
{{ if .icon }}
|
||||
@@ -81,27 +81,31 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 256 256" class="w-5 h-5 text-primary-800 dark:text-primary-300"><path d="M251.76,88.94l-120-64a8,8,0,0,0-7.52,0l-120,64a8,8,0,0,0,0,14.12L32,117.87v48.42a15.91,15.91,0,0,0,4.06,10.65C49.16,191.53,78.51,216,128,216a130,130,0,0,0,48-8.76V240a8,8,0,0,0,16,0V199.51a115.63,115.63,0,0,0,27.94-22.57A15.91,15.91,0,0,0,224,166.29V117.87l27.76-14.81a8,8,0,0,0,0-14.12ZM128,200c-43.27,0-68.72-21.14-80-33.71V126.4l76.24,40.66a8,8,0,0,0,7.52,0L176,143.47v46.34C163.4,195.69,147.52,200,128,200Zm80-33.75a97.83,97.83,0,0,1-16,14.25V134.93l16-8.53ZM188,118.94l-.22-.13-56-29.87a8,8,0,0,0-7.52,14.12L171,128l-43,22.93L25,96,128,41.07,231,96Z"></path></svg>
|
||||
{{end}}
|
||||
</span>
|
||||
<h3 class="flex items-center mb-1 text-lg font-semibold text-gray-900 dark:text-white">{{.area}}
|
||||
<h3 class="flex items-center mb-1 text-lg font-semibold text-gray-900 dark:text-white">{{ .degree | default .area }}
|
||||
<!-- <span class="bg-blue-100 text-blue-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300 ms-3">Latest</span>-->
|
||||
</h3>
|
||||
<span class="block mb-2 text-sm font-normal leading-none text-gray-500 dark:text-gray-300">{{.institution}}</span>
|
||||
<span class="block mb-2 text-sm font-normal leading-none text-gray-500 dark:text-gray-300">{{ .institution }}</span>
|
||||
<time class="block mb-3 text-sm font-normal leading-none text-gray-500 dark:text-gray-300">
|
||||
{{ if .date_start }}
|
||||
{{ (time .date_start) | time.Format ($block.design.date_format | default "January 2006") }} –
|
||||
{{ $start := or .start .date_start }}
|
||||
{{ $end := or .end .date_end }}
|
||||
{{ if $start }}
|
||||
{{ (time $start) | time.Format ($block.design.date_format | default "January 2006") }} –
|
||||
{{ end }}
|
||||
{{ if .date_end}}
|
||||
{{ (time .date_end) | time.Format ($block.design.date_format | default "January 2006") }}
|
||||
{{else}}
|
||||
{{ if $end }}
|
||||
{{ (time $end) | time.Format ($block.design.date_format | default "January 2006") }}
|
||||
{{ else }}
|
||||
{{ i18n "present" | default "Present" }}
|
||||
{{end}}
|
||||
</time>
|
||||
<div class="mb-4 text-base font-normal text-gray-500 dark:text-gray-300 prose max-w-none prose-slate dark:prose-invert">{{.summary | $page.RenderString}}</div>
|
||||
|
||||
{{ with .button }}
|
||||
<a href="{{.url}}" target="_blank" rel="noopener" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg transition-colors hover:bg-gray-100 hover:text-gray-900 focus:z-10 focus:ring-4 focus:outline-none focus:ring-gray-200 focus:text-gray-900 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:text-white dark:focus:ring-gray-700"><svg class="w-3.5 h-3.5 me-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M14.707 7.793a1 1 0 0 0-1.414 0L11 10.086V1.5a1 1 0 0 0-2 0v8.586L6.707 7.793a1 1 0 1 0-1.414 1.414l4 4a1 1 0 0 0 1.416 0l4-4a1 1 0 0 0-.002-1.414Z"/>
|
||||
<path d="M18 12h-2.55l-2.975 2.975a3.5 3.5 0 0 1-4.95 0L4.55 12H2a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2Zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/>
|
||||
</svg> {{.text}}</a>
|
||||
<a href="{{.url}}" target="_blank" rel="noopener" class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg transition-colors hover:bg-gray-100 hover:text-gray-900 focus:z-10 focus:ring-4 focus:outline-none focus:ring-gray-200 focus:text-gray-900 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:text-white dark:focus:ring-gray-700">
|
||||
{{ with .icon }}
|
||||
{{ partial "functions/get_icon" (dict "name" . "attributes" "class='w-4 h-4'") }}
|
||||
{{ end }}
|
||||
{{ .text | default (i18n "learn_more" | default "Learn more") }}
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
</li>
|
||||
|
||||
@@ -5,14 +5,9 @@
|
||||
{{/* Initialise */}}
|
||||
{{ $page := .wcPage }}
|
||||
{{ $block := .wcBlock }}
|
||||
{{ $author := $block.content.username | default "admin" }}
|
||||
|
||||
{{ $person_page_path := (printf "/authors/%s" $author) }}
|
||||
{{ $person_page := site.GetPage $person_page_path }}
|
||||
{{ if not $person_page }}
|
||||
{{ errorf "Could not find an author page at `%s`. Please check the value of `author` in your Skill block and create an associated author page if one does not already exist. See https://docs.hugoblox.com/page-builder/#about " $person_page_path }}
|
||||
{{end}}
|
||||
{{ $langs := $person_page.Params.languages }}
|
||||
{{ $author := $block.content.username | default "me" }}
|
||||
{{ $profile := partial "functions/get_author_profile" $author }}
|
||||
{{ $langs := $profile.languages }}
|
||||
|
||||
<div class="flex flex-col items-center max-w-prose mx-auto gap-3 justify-center">
|
||||
|
||||
@@ -22,8 +17,24 @@
|
||||
|
||||
{{ with $block.content.text }}<p>{{ . | markdownify | emojify }}</p>{{ end }}
|
||||
|
||||
<div class="flex items-center flex-col lg:flex-row gap-x-8">
|
||||
<div class="flex items-center flex-col lg:flex-row gap-y-10 lg:gap-y-0 lg:gap-x-8">
|
||||
{{ range $langs }}
|
||||
{{ $percent := 100.0 }}
|
||||
{{ $levelText := .level }}
|
||||
{{ $label := .label }}
|
||||
|
||||
{{ $levelStr := printf "%v" ($levelText | default "") }}
|
||||
{{ $numericLevel := gt (len (findRE "^[0-9]+(?:\\.[0-9]+)?$" $levelStr)) 0 }}
|
||||
|
||||
{{ if $numericLevel }}
|
||||
{{ $percent = mul (float $levelStr) 20 }}
|
||||
{{ else if .percent }}
|
||||
{{ $percent = float .percent }}
|
||||
{{ end }}
|
||||
|
||||
{{ if gt $percent 100 }}{{ $percent = 100 }}{{ end }}
|
||||
{{ if lt $percent 0 }}{{ $percent = 0 }}{{ end }}
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="flex items-center justify-center w-28 h-28">
|
||||
<svg class="transform -rotate-90" viewBox="0 0 288 288">
|
||||
@@ -31,11 +42,16 @@
|
||||
class="text-gray-200 dark:text-gray-700" />
|
||||
<circle cx="145" cy="145" r="120" stroke="currentColor" stroke-width="30" fill="transparent"
|
||||
class="text-primary-600 dark:text-primary-300"
|
||||
style="stroke-dasharray: calc(2 * 22 / 7 * 120); stroke-dashoffset: calc((2 * 22 / 7 * 120) - ((2 * 22 / 7 * 120) * {{.percent}}/100))" />
|
||||
style="stroke-dasharray: calc(2 * 22 / 7 * 120); stroke-dashoffset: calc((2 * 22 / 7 * 120) - ((2 * 22 / 7 * 120) * {{$percent}}/100))" />
|
||||
</svg>
|
||||
<span class="absolute text-3xl">{{.percent}}%</span>
|
||||
<span class="absolute text-3xl">{{ $percent }}%</span>
|
||||
</div>
|
||||
<span class="text-1xl">{{.name}}</span>
|
||||
{{ if $label }}
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ $label }}</span>
|
||||
{{ else if and $levelText (not $numericLevel) }}
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ . }}</span>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ Present your technical and professional competencies with the Resume Skills bloc
|
||||
- **Icon Integration**: Beautiful icons for each skill that enhance visual recognition
|
||||
- **Flexible Layout**: Side-by-side categories on larger screens, stacked on mobile
|
||||
- **Custom Colors**: Configurable progress bar colors to match your brand
|
||||
- **Toggle Control**: Option to show or hide percentage indicators
|
||||
- **Automatic Bars**: Bars appear when a skill has a level (1–5)
|
||||
- **Markdown Support**: Rich text formatting for skill names and descriptions
|
||||
|
||||
## 🎯 Perfect For
|
||||
@@ -64,4 +64,3 @@ Present your technical and professional competencies with the Resume Skills bloc
|
||||
Perfect for technical professionals, creative experts, and anyone who wants to present their skills in an organized, visually appealing format that helps employers quickly understand their capabilities and expertise levels.
|
||||
|
||||
Turn your skill set into a competitive advantage with professional presentation that clearly communicates your value proposition.
|
||||
|
||||
@@ -5,15 +5,9 @@
|
||||
{{/* Initialise */}}
|
||||
{{ $page := .wcPage }}
|
||||
{{ $block := .wcBlock }}
|
||||
{{ $author := $block.content.username | default "admin" }}
|
||||
|
||||
{{ $person_page_path := (printf "/authors/%s" $author) }}
|
||||
{{ $person_page := site.GetPage $person_page_path }}
|
||||
{{ if not $person_page }}
|
||||
{{ errorf "Could not find an author page at `%s`. Please check the value of `author` in your Skill block and create an associated author page if one does not already exist. See https://docs.hugoblox.com/page-builder/#about " $person_page_path }}
|
||||
{{end}}
|
||||
{{ $skills := $person_page.Params.skills }}
|
||||
{{ $show_show_skill_percentage := $block.design.show_skill_percentage | default true }}
|
||||
{{ $author := $block.content.username | default "me" }}
|
||||
{{ $profile := partial "functions/get_author_profile" $author }}
|
||||
{{ $skills := $profile.skills | default (slice) }}
|
||||
|
||||
<div class="flex flex-col items-center max-w-prose mx-auto gap-3 justify-center">
|
||||
|
||||
@@ -35,12 +29,7 @@
|
||||
{{ .name | markdownify | emojify }}
|
||||
{{ with .description }}<p>{{ . | markdownify | emojify }}</p>{{ end }}
|
||||
</div>
|
||||
{{ range .items }}
|
||||
{{ $pack := or .icon_pack "fas" }}
|
||||
{{ $pack_prefix := $pack }}
|
||||
{{ if in (slice "fab" "fas" "far" "fal") $pack }}
|
||||
{{ $pack_prefix = "fa" }}
|
||||
{{ end }}
|
||||
{{ range (.items | default (slice)) }}
|
||||
|
||||
<div class="skills-content">
|
||||
|
||||
@@ -50,13 +39,26 @@
|
||||
</span>
|
||||
{{ end }}
|
||||
|
||||
{{ $label := .label | default .name }}
|
||||
<span class="skills-name text-gray-700 dark:text-gray-300">
|
||||
{{ .name | markdownify | emojify }}
|
||||
{{ $label | markdownify | emojify }}
|
||||
{{ with .description }}<p class="skills-description">{{ . | markdownify | emojify }}</p>{{ end }}
|
||||
</span>
|
||||
{{ if .percent | and $show_show_skill_percentage }}
|
||||
{{/* Numeric level (1-5) only. */}}
|
||||
{{ $level := 0.0 }}
|
||||
{{ if isset . "level" }}
|
||||
{{ $raw := .level }}
|
||||
{{ $type := printf "%T" $raw }}
|
||||
{{ if or (eq $type "int") (eq $type "int64") (eq $type "int32") (eq $type "int16") (eq $type "int8") (eq $type "uint") (eq $type "uint64") (eq $type "uint32") (eq $type "uint16") (eq $type "uint8") (eq $type "float64") (eq $type "float32") }}
|
||||
{{ $level = float $raw }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if gt $level 5 }}{{ $level = 5 }}{{ end }}
|
||||
{{ if lt $level 0 }}{{ $level = 0 }}{{ end }}
|
||||
{{ if gt $level 0 }}
|
||||
{{ $levelPercent := mul $level 20 }}
|
||||
<div class="skills-wrapper" {{with $color_border}}{{ (printf "style=\"border-color: %s\"" .) | safeHTMLAttr }}{{end}}>
|
||||
<div class="skills-percent" style="width: {{ (printf "%s" (cast.ToString (.percent | default 100))) | safeCSS }}%; {{with $color}}{{ (printf "background-color: %s" .) | safeCSS }}{{end}}"></div>
|
||||
<div class="skills-percent" style="width: {{ printf "%.0f" $levelPercent }}%; {{with $color}}{{ (printf "background-color: %s" .) | safeCSS }}{{end}}"></div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
@@ -64,4 +66,3 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
@@ -39,13 +39,7 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"show_skill_percentage": {
|
||||
"type": "boolean",
|
||||
"description": "Display skill percentage bars",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
"properties": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -37,119 +37,180 @@
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{/* Team Grid */}}
|
||||
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
|
||||
{{ range $block.content.user_groups }}
|
||||
{{ $group_name := . }}
|
||||
{{ $query := where (where site.Pages "Section" "authors") ".Params.user_groups" "intersect" (slice .) }}
|
||||
|
||||
{{/* Sort */}}
|
||||
{{ $sort_by := $block.content.sort_by | default "Params.last_name" }}
|
||||
{{ $sort_by = partial "functions/get_sort_by_parameter" $sort_by }}
|
||||
{{ $sort_ascending := $block.content.sort_ascending | default true }}
|
||||
{{ $sort_order := cond $sort_ascending "asc" "desc" }}
|
||||
{{ $query = sort $query $sort_by $sort_order }}
|
||||
|
||||
{{/* Group Header (if multiple groups) */}}
|
||||
{{ if and $query (gt (len $block.content.user_groups) 1) }}
|
||||
<div class="col-span-full">
|
||||
{{/* Build profiles from data/authors */}}
|
||||
{{ $allProfiles := slice }}
|
||||
{{ range $slug, $_ := site.Data.authors }}
|
||||
{{ $allProfiles = $allProfiles | append (partial "functions/get_author_profile" (dict "slug" $slug)) }}
|
||||
{{ end }}
|
||||
|
||||
{{ $groups := $block.content.user_groups }}
|
||||
|
||||
{{ if $groups }}
|
||||
{{ range $group := $groups }}
|
||||
{{ $groupProfiles := slice }}
|
||||
{{ range $allProfiles }}
|
||||
{{ $u := .user_groups | default (slice) }}
|
||||
{{ if gt (len (intersect $u (slice $group))) 0 }}
|
||||
{{ $groupProfiles = $groupProfiles | append . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ $groupProfiles = sort $groupProfiles "title" }}
|
||||
|
||||
{{ if and $groupProfiles (gt (len $groups) 1) }}
|
||||
<div class="col-span-full mb-4">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6 pb-2 border-b border-gray-200 dark:border-gray-700">
|
||||
{{ $group_name | markdownify }}
|
||||
{{ $group | markdownify }}
|
||||
</h3>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{/* Team Members */}}
|
||||
{{ range $person := $query }}
|
||||
{{ $avatar := (.Resources.ByType "image").GetMatch "*avatar*" }}
|
||||
{{ $link := "" }}
|
||||
{{ with site.GetPage (printf "/authors/%s" (path.Base .File.Dir)) }}
|
||||
{{ $link = .RelPermalink }}
|
||||
|
||||
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 w-full">
|
||||
{{ range $profile := $groupProfiles }}
|
||||
{{ $avatar := $profile.avatar }}
|
||||
{{ $link := printf "/authors/%s/" $profile.slug }}
|
||||
|
||||
<div class="group relative">
|
||||
<div class="relative overflow-hidden rounded-2xl bg-white dark:bg-gray-800 shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1">
|
||||
|
||||
{{ if $avatar }}
|
||||
<a href="{{ $link }}" class="block relative h-64 overflow-hidden">
|
||||
{{ $image := $avatar.Fill "400x400 Center webp" }}
|
||||
<img src="{{ $image.RelPermalink }}"
|
||||
alt="{{ $profile.title }}"
|
||||
width="{{ $image.Width }}"
|
||||
height="{{ $image.Height }}"
|
||||
loading="lazy"
|
||||
class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-110">
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
<div class="p-6">
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-1">
|
||||
<a href="{{ $link }}" class="hover:text-primary-600 dark:hover:text-primary-400 transition-colors">
|
||||
{{ $profile.title }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
{{ if $show_role }}
|
||||
<div class="text-gray-600 dark:text-gray-400 mb-3">
|
||||
{{ with $profile.role }}<p class="font-medium">{{ . }}</p>{{ end }}
|
||||
{{ if and $show_organizations $profile.affiliations }}
|
||||
{{ range first 1 $profile.affiliations }}
|
||||
<p class="text-sm mt-1">{{ .name }}</p>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ with $profile.bio }}
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4 line-clamp-2">
|
||||
{{ . }}
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
{{ if and $show_interests $profile.interests }}
|
||||
<div class="mb-4">
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{{ range first 3 $profile.interests }}
|
||||
<span class="inline-block bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 text-xs px-2 py-1 rounded">
|
||||
{{ . }}
|
||||
</span>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if and $show_social $profile.links }}
|
||||
<div class="flex gap-3 pt-2 border-t border-gray-200 dark:border-gray-700">
|
||||
{{ range $profile.links }}
|
||||
{{ $l := .url | default .link }}
|
||||
{{ $scheme := (urls.Parse $l).Scheme }}
|
||||
{{ $target := "" }}
|
||||
{{ if not $scheme }}
|
||||
{{ $l = (.url | default .link) | relLangURL }}
|
||||
{{ if eq (path.Ext $l) ".pdf" }}{{ $target = "target=\"_blank\" rel=\"noopener\"" }}{{ end }}
|
||||
{{ else if in (slice "http" "https") $scheme }}
|
||||
{{ $target = "target=\"_blank\" rel=\"noopener\"" }}
|
||||
{{ end }}
|
||||
|
||||
<a href="{{ $l | safeURL }}"
|
||||
{{ $target | safeHTMLAttr }}
|
||||
aria-label="{{ .icon }}"
|
||||
{{ with .label }} title="{{ . }}"{{ end }}
|
||||
class="text-gray-500 hover:text-primary-600 dark:text-gray-400 dark:hover:text-primary-400 transition-colors">
|
||||
{{ partial "functions/get_icon" (dict "name" .icon "attributes" "class=\"w-5 h-5\"") }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ $allProfiles = sort $allProfiles "title" }}
|
||||
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
{{ range $profile := $allProfiles }}
|
||||
{{ $avatar := $profile.avatar }}
|
||||
{{ $link := printf "/authors/%s/" $profile.slug }}
|
||||
<div class="group relative">
|
||||
<div class="relative overflow-hidden rounded-2xl bg-white dark:bg-gray-800 shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1">
|
||||
|
||||
{{/* Avatar */}}
|
||||
{{ if $avatar }}
|
||||
<a href="{{ $link }}" class="block relative h-64 overflow-hidden">
|
||||
{{ $image := $avatar.Fill "400x400 Center webp" }}
|
||||
<img src="{{ $image.RelPermalink }}"
|
||||
alt="{{ .Title }}"
|
||||
alt="{{ $profile.title }}"
|
||||
width="{{ $image.Width }}"
|
||||
height="{{ $image.Height }}"
|
||||
loading="lazy"
|
||||
class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-110">
|
||||
|
||||
{{/* Gradient Overlay */}}
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
{{/* Content */}}
|
||||
<div class="p-6">
|
||||
{{/* Name */}}
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-1">
|
||||
<a href="{{ $link }}" class="hover:text-primary-600 dark:hover:text-primary-400 transition-colors">
|
||||
{{ .Title }}
|
||||
{{ $profile.title }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
{{/* Role & Organization */}}
|
||||
{{ if $show_role }}
|
||||
<div class="text-gray-600 dark:text-gray-400 mb-3">
|
||||
{{ with .Params.role }}
|
||||
<p class="font-medium">{{ . }}</p>
|
||||
{{ end }}
|
||||
|
||||
{{ if and $show_organizations .Params.organizations }}
|
||||
{{ range first 1 .Params.organizations }}
|
||||
{{ with $profile.role }}<p class="font-medium">{{ . }}</p>{{ end }}
|
||||
{{ if and $show_organizations $profile.affiliations }}
|
||||
{{ range first 1 $profile.affiliations }}
|
||||
<p class="text-sm mt-1">{{ .name }}</p>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{/* Bio */}}
|
||||
{{ with .Params.bio }}
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4 line-clamp-2">
|
||||
{{ . }}
|
||||
</p>
|
||||
{{ with $profile.bio }}
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4 line-clamp-2">{{ . }}</p>
|
||||
{{ end }}
|
||||
|
||||
{{/* Interests */}}
|
||||
{{ if and $show_interests .Params.interests }}
|
||||
{{ if and $show_interests $profile.interests }}
|
||||
<div class="mb-4">
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{{ range first 3 .Params.interests }}
|
||||
<span class="inline-block bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 text-xs px-2 py-1 rounded">
|
||||
{{ . }}
|
||||
</span>
|
||||
{{ range first 3 $profile.interests }}
|
||||
<span class="inline-block bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 text-xs px-2 py-1 rounded">{{ . }}</span>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{/* Social Links */}}
|
||||
{{ if $show_social }}
|
||||
{{ if and $show_social $profile.links }}
|
||||
<div class="flex gap-3 pt-2 border-t border-gray-200 dark:border-gray-700">
|
||||
{{ range .Params.social }}
|
||||
{{ $link := .url | default .link }}
|
||||
{{ $scheme := (urls.Parse $link).Scheme }}
|
||||
{{ range $profile.links }}
|
||||
{{ $l := .url | default .link }}
|
||||
{{ $scheme := (urls.Parse $l).Scheme }}
|
||||
{{ $target := "" }}
|
||||
{{ if not $scheme }}
|
||||
{{ $link = (.url | default .link) | relLangURL }}
|
||||
{{ if eq (path.Ext $link) ".pdf" }}{{ $target = "target=\"_blank\" rel=\"noopener\"" }}{{ end }}
|
||||
{{ $l = (.url | default .link) | relLangURL }}
|
||||
{{ if eq (path.Ext $l) ".pdf" }}{{ $target = "target=\"_blank\" rel=\"noopener\"" }}{{ end }}
|
||||
{{ else if in (slice "http" "https") $scheme }}
|
||||
{{ $target = "target=\"_blank\" rel=\"noopener\"" }}
|
||||
{{ end }}
|
||||
|
||||
<a href="{{ $link | safeURL }}"
|
||||
{{ $target | safeHTMLAttr }}
|
||||
aria-label="{{ .icon }}"
|
||||
{{ with .label }} title="{{ . }}"{{ end }}
|
||||
class="text-gray-500 hover:text-primary-600 dark:text-gray-400 dark:hover:text-primary-400 transition-colors">
|
||||
<a href="{{ $l | safeURL }}" {{ $target | safeHTMLAttr }} aria-label="{{ .icon }}" {{ with .label }} title="{{ . }}"{{ end }} class="text-gray-500 hover:text-primary-600 dark:text-gray-400 dark:hover:text-primary-400 transition-colors">
|
||||
{{ partial "functions/get_icon" (dict "name" .icon "attributes" "class=\"w-5 h-5\"") }}
|
||||
</a>
|
||||
{{ end }}
|
||||
@@ -159,8 +220,8 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{/* Call to Action */}}
|
||||
{{ with $block.content.cta }}
|
||||
|
||||
@@ -7,19 +7,18 @@
|
||||
{{ $publisher := $branding.organization }}
|
||||
|
||||
{{ $author := "" }}
|
||||
{{ $author_username := "" }}
|
||||
{{ $author_slug := "" }}
|
||||
|
||||
{{ if and (not $page.Params.authors) ($page.Scratch.Get "superuser_username") }}
|
||||
{{ $author_username = $page.Scratch.Get "superuser_username" }}
|
||||
{{ if and (not $page.Params.authors) ($page.Scratch.Get "superuser_slug") }}
|
||||
{{ $author_slug = $page.Scratch.Get "superuser_slug" }}
|
||||
{{ else if $page.Params.authors }}
|
||||
{{ $author = index $page.Params.authors 0 }}
|
||||
{{ $author_username = urlize $author }}
|
||||
{{ $author_slug = urlize $author }}
|
||||
{{ end }}
|
||||
|
||||
{{ $taxonomy := "authors" }}
|
||||
{{ $profile_page := site.GetPage (printf "/%s/%s" $taxonomy $author_username) }}
|
||||
{{ with $profile_page }}
|
||||
{{ $author = .Title }}
|
||||
{{ $profile := partial "functions/get_author_profile" (dict "slug" $author_slug) }}
|
||||
{{ if $profile.title }}
|
||||
{{ $author = $profile.title }}
|
||||
{{ else }}
|
||||
{{ $author = $author | default $publisher }}
|
||||
{{ end }}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
{{/*
|
||||
Return a normalized HugoBlox author/person profile from data.
|
||||
|
||||
Input (flexible):
|
||||
- dict with "slug" key, or a raw string slug.
|
||||
|
||||
Output (dict):
|
||||
- slug: string
|
||||
- title: string (display name, fallback to humanized slug)
|
||||
- role: string (optional)
|
||||
- bio: string (optional)
|
||||
- status: map (optional)
|
||||
- affiliations: array (optional)
|
||||
- ids: map (optional)
|
||||
- links: array (optional)
|
||||
- is_owner: bool (optional)
|
||||
- has_data: bool (true if found in data/authors)
|
||||
- avatar: resource (optional) – matching assets/media/authors/<slug>.*
|
||||
*/}}
|
||||
|
||||
{{- $input := . -}}
|
||||
{{- $slug := "" -}}
|
||||
|
||||
{{- $inputType := printf "%T" $input -}}
|
||||
|
||||
{{- if (reflect.IsMap $input) -}}
|
||||
{{- $slug = index $input "slug" | default "" -}}
|
||||
{{- else if eq $inputType "string" -}}
|
||||
{{- $slug = $input -}}
|
||||
{{- else -}}
|
||||
{{- $slug = printf "%v" $input -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $slug = $slug | urlize -}}
|
||||
|
||||
{{- $data := index site.Data.authors $slug -}}
|
||||
{{- $hasData := $data -}}
|
||||
|
||||
{{/* Structured name resolution */}}
|
||||
{{- $name := $data.name -}}
|
||||
{{- $display := "" -}}
|
||||
{{- $given := "" -}}
|
||||
{{- $family := "" -}}
|
||||
{{- $middle := "" -}}
|
||||
{{- $alternate := "" -}}
|
||||
{{- $namePronunciation := "" -}}
|
||||
{{- $namePronouns := "" -}}
|
||||
|
||||
{{- if $name.display }}{{ $display = $name.display }}{{ end }}
|
||||
{{- if $name.given }}{{ $given = $name.given }}{{ end }}
|
||||
{{- if $name.family }}{{ $family = $name.family }}{{ end }}
|
||||
{{- if $name.middle }}{{ $middle = $name.middle }}{{ end }}
|
||||
{{- if $name.alternate }}{{ $alternate = $name.alternate }}{{ end }}
|
||||
{{- if $name.pronunciation }}{{ $namePronunciation = $name.pronunciation }}{{ end }}
|
||||
{{- if $name.pronouns }}{{ $namePronouns = $name.pronouns }}{{ end }}
|
||||
|
||||
{{- $title := "" -}}
|
||||
{{- if $display -}}
|
||||
{{- $title = $display -}}
|
||||
{{- else if $data.title -}}
|
||||
{{- $title = $data.title -}}
|
||||
{{- else -}}
|
||||
{{- $title = $slug | humanize -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $role := $data.role -}}
|
||||
{{- $bio := $data.bio -}}
|
||||
{{- $status := $data.status -}}
|
||||
{{- $affiliations := $data.affiliations -}}
|
||||
{{- $ids := $data.ids -}}
|
||||
{{- $links := $data.links -}}
|
||||
{{- $isOwner := or ($data.is_owner) ($data.superuser) -}}
|
||||
{{- $pronouns := $namePronouns | default $data.pronouns -}}
|
||||
{{- $userGroups := $data.user_groups -}}
|
||||
{{- $interests := $data.interests -}}
|
||||
{{- $education := $data.education -}}
|
||||
{{- $experience := or $data.experience $data.work -}}
|
||||
{{- $skills := $data.skills -}}
|
||||
{{- $languages := $data.languages -}}
|
||||
{{- $awards := $data.awards -}}
|
||||
{{- $postnominals := slice -}}
|
||||
{{- if $data.postnominals -}}
|
||||
{{- if (reflect.IsSlice $data.postnominals) -}}
|
||||
{{- $postnominals = $data.postnominals -}}
|
||||
{{- else -}}
|
||||
{{- $postnominals = slice $data.postnominals -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* Avatar resolution: look in assets/media/authors/<slug>.* */ -}}
|
||||
{{- $avatar := resources.GetMatch (printf "media/authors/%s.*" $slug) -}}
|
||||
|
||||
{{- $profile := dict
|
||||
"slug" $slug
|
||||
"title" $title
|
||||
"name_display" $display
|
||||
"name_given" $given
|
||||
"name_family" $family
|
||||
"name_middle" $middle
|
||||
"name_alternate" $alternate
|
||||
"name_pronunciation" $namePronunciation
|
||||
"role" $role
|
||||
"bio" $bio
|
||||
"status" $status
|
||||
"affiliations" $affiliations
|
||||
"ids" $ids
|
||||
"links" $links
|
||||
"pronouns" $pronouns
|
||||
"user_groups" $userGroups
|
||||
"interests" $interests
|
||||
"education" $education
|
||||
"experience" $experience
|
||||
"skills" $skills
|
||||
"languages" $languages
|
||||
"awards" $awards
|
||||
"postnominals" $postnominals
|
||||
"is_owner" $isOwner
|
||||
"has_data" (not (eq $hasData nil))
|
||||
"avatar" $avatar
|
||||
-}}
|
||||
|
||||
{{- return $profile -}}
|
||||
@@ -3,16 +3,22 @@
|
||||
{{/* Don't show author box on normal pages or if author box disabled. */}}
|
||||
{{ if ne .Type "page" | and (not (or (eq site.Params.profile false) (eq .Params.profile false))) }}
|
||||
|
||||
{{/* Display superuser if superuser exists and page authors are not explicitly specified. */}}
|
||||
{{/* Otherwise, display first author if a profile for them exists. */}}
|
||||
{{ $authors := .Params.authors }}
|
||||
|
||||
{{ if and (not .Params.authors) (.Scratch.Get "superuser_username") }}
|
||||
{{ $author_page := site.GetPage (printf "/%s/%s" "authors" (.Scratch.Get "superuser_username")) }}
|
||||
{{ partial "page_author_card" (dict "author_page" $author_page) }}
|
||||
{{ else if .Params.authors }}
|
||||
{{ $taxonomy := "authors" }}
|
||||
{{ range $author_obj := (.GetTerms $taxonomy) }}
|
||||
{{ partial "page_author_card" (dict "author_page" $author_obj.Page) }}
|
||||
{{/* If authors not set, fallback to superuser/owner from Scratch */}}
|
||||
{{ if (not $authors) }}
|
||||
{{ $superuser := .Scratch.Get "superuser_slug" }}
|
||||
{{ if $superuser }}
|
||||
{{ $authors = (slice $superuser) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $authors }}
|
||||
{{ range $idx, $slug := $authors }}
|
||||
{{ $profile := partial "functions/get_author_profile" $slug }}
|
||||
{{ if $profile }}
|
||||
{{ partial "page_author_card" (dict "profile" $profile "page" .) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
{{ $profile := .profile }}
|
||||
{{ $page := .page }}
|
||||
{{ $author_page := .author_page }}
|
||||
{{ $site_type := site.Params.hugoblox.identity.type | humanize | default "Person" }}
|
||||
{{- $has_profile := not (eq nil $author_page.Params.superuser) -}}
|
||||
{{ $avatar_shape := site.Params.hugoblox.layout.avatar_shape | default "circle" }}
|
||||
|
||||
{{/* Check an author profile exists. */}}
|
||||
{{ if $has_profile }}
|
||||
{{/* If it's a personal site and primary page author is superuser, link to the homepage rather than their profile page. */}}
|
||||
{{ $profile_url := $author_page.RelPermalink }}
|
||||
{{ if and (eq $site_type "Person") (eq $author_page.Params.superuser true) }}
|
||||
{{ if $profile }}
|
||||
{{/* If it's a personal site and the profile is owner, link home */}}
|
||||
{{ $profile_url := printf "/authors/%s/" $profile.slug }}
|
||||
{{ if and (eq $site_type "Person") ($profile.is_owner) }}
|
||||
{{ $profile_url = site.BaseURL }}
|
||||
{{ end }}
|
||||
{{ $avatar := ($author_page.Resources.ByType "image").GetMatch "*avatar*" }}
|
||||
{{ $avatar_shape := site.Params.hugoblox.layout.avatar_shape | default "circle" }}
|
||||
|
||||
{{ $avatar := $profile.avatar }}
|
||||
|
||||
<div class="flex pt-12 pb-4">
|
||||
{{ if $avatar }}
|
||||
{{/* Use utility for high-res avatar processing (smart for Retina displays) */}}
|
||||
{{ $responsive := partial "functions/process_responsive_image.html" (dict
|
||||
"image" $avatar
|
||||
"mode" "fill"
|
||||
@@ -31,7 +29,7 @@
|
||||
src="{{ $responsive.fallback.RelPermalink }}"
|
||||
width="96"
|
||||
height="96"
|
||||
alt="{{$author_page.Title}}"
|
||||
alt="{{$profile.title}}"
|
||||
loading="lazy"
|
||||
/>
|
||||
{{ end }}
|
||||
@@ -42,29 +40,27 @@
|
||||
<div class="font-semibold leading-6 text-neutral-800 dark:text-neutral-300">
|
||||
<span class="inline-block">
|
||||
{{if $profile_url}}<a href="{{$profile_url}}" class="no-underline">{{end}}
|
||||
{{$author_page.Title}}
|
||||
{{$profile.title}}
|
||||
{{if $profile_url}}</a>{{end}}
|
||||
</span>
|
||||
{{- with $author_page.Params.pronouns -}}
|
||||
{{- with $profile.pronouns -}}
|
||||
<span class="text-sm font-normal text-gray-600 dark:text-gray-400 ml-1 inline-block">({{ . }})</span>
|
||||
{{- end -}}
|
||||
</div>
|
||||
|
||||
{{ with $author_page.Params.role }}
|
||||
{{ with $profile.role }}
|
||||
<div class="text-sm font-bold text-neutral-700 dark:text-neutral-300">
|
||||
{{. | markdownify | emojify}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
|
||||
{{ with $author_page.Params.bio }}
|
||||
{{ with $profile.bio }}
|
||||
<div class="text-sm text-neutral-700 dark:text-neutral-300">{{ . | markdownify | emojify }}</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="text-2xl sm:text-lg pt-1">
|
||||
|
||||
{{ partial "social_links" $author_page }}
|
||||
|
||||
{{ partial "social_links" (dict "Params" (dict "profiles" $profile.links)) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
{{/* Display author list. */}}
|
||||
|
||||
{{ if .Params.authors }}
|
||||
{{ range $index, $value := (.GetTerms "authors") }}
|
||||
{{- /* Highlight the author's name? */ -}}
|
||||
{{- $highlight_name := .Page.Params.highlight_name | default false -}}
|
||||
{{ range $index, $term := (.GetTerms "authors") }}
|
||||
{{- $slug := $term.Data.Term | urlize -}}
|
||||
{{- $profile := partial "functions/get_author_profile" (dict "slug" $slug) -}}
|
||||
{{- $display := $profile.title | default $term.LinkTitle -}}
|
||||
{{- $highlight_name := false -}}
|
||||
|
||||
{{- if gt $index 0 }}, {{ end -}}
|
||||
<span {{ if $highlight_name }}class="font-bold"{{end}}>
|
||||
{{/* Effectively check the page's `build` option as `build` is not exposed in Hugo's Page object. */}}
|
||||
{{- if .RelPermalink -}}
|
||||
<a href="{{.RelPermalink}}">{{.LinkTitle}}</a>
|
||||
{{- if $term.RelPermalink -}}
|
||||
<a href="{{ $term.RelPermalink }}">{{ $display }}</a>
|
||||
{{- else -}}
|
||||
{{ .LinkTitle }}
|
||||
{{ $display }}
|
||||
{{- end -}}
|
||||
</span>
|
||||
{{- if isset $.Params "author_notes" -}}
|
||||
|
||||
@@ -12,18 +12,30 @@
|
||||
<meta name="robots" content="noindex" />
|
||||
{{- end -}}
|
||||
|
||||
{{/* Attempt to load superuser. */}}
|
||||
{{ $superuser_name := "" }}
|
||||
{{ $superuser_username := "" }}
|
||||
{{ $superuser_role := "" }}
|
||||
{{ range first 1 (where (where site.Pages "Section" "authors") "Params.superuser" true) }}
|
||||
{{ $superuser_name = .Title }}
|
||||
{{ $superuser_username = path.Base .File.Dir }}
|
||||
{{ $superuser_role = .Params.role }}
|
||||
{{ end }}
|
||||
{{ $scr.Set "superuser_username" $superuser_username }}{{/* Set superuser globally for page_author.html. */}}
|
||||
{{/* Attempt to load superuser/person from data. */}}
|
||||
{{ $superuser_name := "" }}
|
||||
{{ $superuser_slug := "" }}
|
||||
{{ $superuser_role := "" }}
|
||||
|
||||
{{ with $superuser_name }}<meta name="author" content="{{ . }}" />{{ end }}
|
||||
{{/* Prefer is_owner flag, fallback to slug 'me' */}}
|
||||
{{ range $slug, $data := site.Data.authors }}
|
||||
{{ if and (not $superuser_slug) ($data.is_owner) }}
|
||||
{{ $superuser_slug = $slug }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if and (eq $superuser_slug "") (index site.Data.authors "me") }}
|
||||
{{ $superuser_slug = "me" }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $superuser_slug }}
|
||||
{{ $profile := partial "functions/get_author_profile" (dict "slug" $superuser_slug) }}
|
||||
{{ $superuser_name = $profile.title }}
|
||||
{{ $superuser_role = $profile.role }}
|
||||
{{ end }}
|
||||
|
||||
{{ $scr.Set "superuser_slug" $superuser_slug }}{{/* Set superuser globally for author rendering. */}}
|
||||
|
||||
{{ with $superuser_name }}<meta name="author" content="{{ . }}" />{{ end }}
|
||||
|
||||
{{/* Generate page description. */}}
|
||||
{{ $desc := "" }}
|
||||
@@ -114,15 +126,22 @@
|
||||
{{/* Get page image for sharing. */}}
|
||||
{{ $sharing_image := resources.GetMatch (path.Join "media" "sharing.*") }}
|
||||
{{ $featured_image := (.Resources.ByType "image").GetMatch "*featured*" }}
|
||||
{{ $avatar_image := (.Resources.ByType "image").GetMatch "avatar*" }}
|
||||
{{ $avatar_image := (.Resources.ByType "image").GetMatch "avatar*" }}
|
||||
{{ $has_logo := fileExists "assets/media/logo.png" | or (fileExists "assets/media/logo.svg") }}
|
||||
{{ $og_image := "" }}
|
||||
{{ $twitter_card := "summary_large_image" }}
|
||||
{{ if (and (eq .Kind "term") $avatar_image) }}
|
||||
{{/* Match image processing in About widget to prevent generating more images than necessary. */}}
|
||||
{{ $og_image = ($avatar_image.Fill "540x540 Center").Permalink }}
|
||||
{{ if and (eq .Kind "term") (eq .Data.Singular "author") }}
|
||||
{{/* Try data-driven avatar for author term pages */}}
|
||||
{{ $termSlug := .Data.Term | urlize }}
|
||||
{{ $profile := partial "functions/get_author_profile" (dict "slug" $termSlug) }}
|
||||
{{ with $profile.avatar }}
|
||||
{{ $og_image = (.Fill "540x540 Center").Permalink }}
|
||||
{{ $twitter_card = "summary" }}
|
||||
{{ else if $featured_image }}
|
||||
{{ end }}
|
||||
{{ else if (and (eq .Kind "term") $avatar_image) }}
|
||||
{{ $og_image = ($avatar_image.Fill "540x540 Center").Permalink }}
|
||||
{{ $twitter_card = "summary" }}
|
||||
{{ else if $featured_image }}
|
||||
{{ $og_image = $featured_image.Permalink }}
|
||||
{{ else if $sharing_image }}
|
||||
{{ $og_image = $sharing_image.Permalink }}
|
||||
|
||||
@@ -145,29 +145,20 @@
|
||||
<div class="flex items-center gap-3 text-xs text-zinc-500 dark:text-zinc-500 flex-wrap mb-3">
|
||||
{{ if $item.Params.authors }}
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
{{ $authorTerm := index ($item.GetTerms "authors") 0 }}
|
||||
{{ if $authorTerm }}
|
||||
{{/* Author page exists - show avatar or default icon */}}
|
||||
<div class="relative h-6 w-6 flex-shrink-0">
|
||||
{{ $avatar := ($authorTerm.Resources.ByType "image").GetMatch "*avatar*" }}
|
||||
{{ if $avatar }}
|
||||
{{ $avatar_48 := $avatar.Process "Fill 48x48 Center webp" }}
|
||||
<img alt="avatar" class="rounded-full object-cover" src="{{$avatar_48.RelPermalink}}" width="24" height="24" loading="lazy" decoding="async" />
|
||||
{{ else }}
|
||||
{{/* Default avatar icon when no image */}}
|
||||
<div class="w-6 h-6 bg-gray-100 dark:bg-gray-700 rounded-full flex items-center justify-center">
|
||||
{{ partial "functions/get_icon" (dict "name" "hero/user" "attributes" "class=\"w-4 h-4 text-gray-500 dark:text-gray-400\"") }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<span class="truncate max-w-[9rem] text-sm">{{ $authorTerm.Page.LinkTitle }}</span>
|
||||
{{ else }}
|
||||
{{/* No author page - just show team icon and first author name */}}
|
||||
<div class="w-6 h-6 bg-primary-100 dark:bg-primary-900/50 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
{{ partial "functions/get_icon" (dict "name" "hero/user-group" "attributes" "class=\"w-4 h-4 text-primary-600 dark:text-primary-400\"") }}
|
||||
</div>
|
||||
<span class="truncate max-w-[9rem] text-sm">{{ index $item.Params.authors 0 }}</span>
|
||||
{{ end }}
|
||||
{{ $slug := index $item.Params.authors 0 | urlize }}
|
||||
{{ $profile := partial "functions/get_author_profile" $slug }}
|
||||
{{ $avatar := $profile.avatar }}
|
||||
<div class="relative h-6 w-6 flex-shrink-0">
|
||||
{{ if $avatar }}
|
||||
{{ $avatar_48 := $avatar.Process "Fill 48x48 Center webp" }}
|
||||
<img alt="avatar" class="rounded-full object-cover" src="{{$avatar_48.RelPermalink}}" width="24" height="24" loading="lazy" decoding="async" />
|
||||
{{ else }}
|
||||
<div class="w-6 h-6 bg-gray-100 dark:bg-gray-700 rounded-full flex items-center justify-center">
|
||||
{{ partial "functions/get_icon" (dict "name" "hero/user" "attributes" "class=\"w-4 h-4 text-gray-500 dark:text-gray-400\"") }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<span class="truncate max-w-[9rem] text-sm">{{ $profile.title }}</span>
|
||||
</div>
|
||||
<span class="opacity-40">•</span>
|
||||
{{ end }}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
{{ define "main" }}
|
||||
|
||||
{{ $slug := .Data.Term | urlize }}
|
||||
{{ $profile := partial "functions/get_author_profile" (dict "slug" $slug) }}
|
||||
{{ $avatar := $profile.avatar }}
|
||||
{{ $avatar_shape := site.Params.hugoblox.layout.avatar_shape | default "circle" }}
|
||||
|
||||
<section class="max-w-5xl mx-auto px-6 py-10">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center gap-6">
|
||||
<div class="flex-shrink-0">
|
||||
{{ if $avatar }}
|
||||
{{ $responsive := partial "functions/process_responsive_image.html" (dict
|
||||
"image" $avatar
|
||||
"mode" "fill"
|
||||
"aspect_ratio" "1:1"
|
||||
"anchor" "Center"
|
||||
"sizes" (slice 160 240 320 480)
|
||||
) }}
|
||||
<img
|
||||
class="h-32 w-32 sm:h-40 sm:w-40 {{ if ne $avatar_shape "square" }}rounded-full{{ end }}"
|
||||
srcset="{{ $responsive.srcset }}"
|
||||
sizes="160px"
|
||||
src="{{ $responsive.fallback.RelPermalink }}"
|
||||
width="160"
|
||||
height="160"
|
||||
alt="{{ $profile.title }}"
|
||||
loading="lazy"
|
||||
/>
|
||||
{{ else }}
|
||||
<div class="h-32 w-32 sm:h-40 sm:w-40 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center">
|
||||
{{ partial "functions/get_icon" (dict "name" "hero/user" "attributes" "class=\"h-12 w-12 text-gray-400\"") }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<h1 class="text-3xl sm:text-4xl font-bold">{{ $profile.title }}</h1>
|
||||
{{ with $profile.status }}
|
||||
{{ with .icon }}
|
||||
<span class="text-2xl" aria-hidden="true">{{ . }}</span>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{ with $profile.role }}
|
||||
<div class="text-lg font-semibold text-neutral-700 dark:text-neutral-200">{{ . | markdownify | emojify }}</div>
|
||||
{{ end }}
|
||||
|
||||
{{ with $profile.affiliations }}
|
||||
<div class="text-neutral-600 dark:text-neutral-300">
|
||||
{{ range $index, $org := . }}
|
||||
{{ if gt $index 0 }} · {{ end }}
|
||||
{{ if $org.url }}<a href="{{ $org.url }}" class="underline">{{ $org.name }}</a>{{ else }}{{ $org.name }}{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ with $profile.bio }}
|
||||
<div class="prose prose-slate dark:prose-invert max-w-none">
|
||||
{{ . | markdownify | emojify }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if $profile.links }}
|
||||
<div class="pt-2">
|
||||
{{ partial "social_links" (dict "Params" (dict "profiles" $profile.links)) }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{ $view := "card" }}
|
||||
{{ $block := . }}
|
||||
{{ $paginator := .Paginate .Pages.ByDate.Reverse }}
|
||||
{{ $config := dict
|
||||
"columns" 2
|
||||
"len" (len $paginator.Pages)
|
||||
"fill_image" true
|
||||
"show_date" true
|
||||
"show_read_time" true
|
||||
"show_read_more" true
|
||||
}}
|
||||
|
||||
<div class="flex flex-col items-center px-6">
|
||||
{{ partial "functions/render_view" (dict "fragment" "start" "page" $block "item" . "view" $view "config" $config) }}
|
||||
|
||||
{{ range $index, $item := $paginator.Pages }}
|
||||
{{ partial "functions/render_view" (dict "page" . "item" . "view" $view "index" $index "config" $config) }}
|
||||
{{ end }}
|
||||
|
||||
{{ partial "functions/render_view" (dict "fragment" "end" "page" $block "item" . "view" $view) }}
|
||||
|
||||
{{ partial "components/paginator" . }}
|
||||
</div>
|
||||
|
||||
{{ end }}
|
||||
@@ -78,30 +78,22 @@
|
||||
<script>console.log('Author notes detected in single.html, Alpine.js should load');</script>
|
||||
{{ end }}
|
||||
|
||||
{{ $taxonomy := "authors" }}
|
||||
{{ range $i, $author_obj := (.GetTerms $taxonomy) }}
|
||||
{{ $author_page := $author_obj.Page }}
|
||||
{{ $avatar := ($author_page.Resources.ByType "image").GetMatch "*avatar*" }}
|
||||
{{- if and $i (not $avatar) }}<span class="mr-1">,</span>{{ end -}}
|
||||
{{ with $author_page.Params.website }}
|
||||
<a href="{{.}}" target="_blank" rel="noreferrer">
|
||||
{{ end }}
|
||||
{{ range $i, $slug := .Params.authors }}
|
||||
{{ $profile := partial "functions/get_author_profile" $slug }}
|
||||
{{ $avatar := $profile.avatar }}
|
||||
{{ if and $i (not $avatar) }}<span class="mr-1">,</span>{{ end }}
|
||||
<div class="group inline-flex items-center text-current gap-x-1.5 mx-1">
|
||||
{{ with $avatar }}
|
||||
{{/* Simple 2x retina image for small avatar */}}
|
||||
{{ $avatar_32 := $avatar.Process "Fill 32x32 Center webp" }}
|
||||
{{ $avatar_32 := .Process "Fill 32x32 Center webp" }}
|
||||
<img src="{{ $avatar_32.RelPermalink }}"
|
||||
width="16"
|
||||
height="16"
|
||||
alt="{{ $author_page.Title }}"
|
||||
alt="{{ $profile.title }}"
|
||||
class="inline-block h-4 w-4 rounded-full border border-current"
|
||||
loading="lazy" />
|
||||
{{ end }}
|
||||
<div {{if $author_page.Params.website}}class="group-hover:underline"{{end}}>{{ $author_page.Title }}</div>
|
||||
<div>{{ $profile.title }}</div>
|
||||
</div>
|
||||
{{ with $author_page.Params.website }}
|
||||
</a>
|
||||
{{ end }}
|
||||
{{/* Add author note tooltip if available */}}
|
||||
{{- if isset $.Params "author_notes" -}}
|
||||
{{- with (index $.Params.author_notes $i) -}}
|
||||
|
||||
+35
-23
@@ -9,7 +9,7 @@ Features:
|
||||
- Updates special module metadata (blox-tailwind data/hugoblox.yaml version)
|
||||
- Updates dependent modules' go.mod "require" versions when a dependency is released
|
||||
- Tags changed modules with annotated tags and pushes tags
|
||||
- Updates templates' go.mod to latest released module versions and bumps Hugo version in CI/Netlify config
|
||||
- Updates templates' go.mod to latest released module versions and bumps Hugo version in template configs (hugoblox.yaml, Netlify, devcontainer)
|
||||
|
||||
Usage examples:
|
||||
poetry run python scripts/release_modules.py --dry-run --log-level INFO
|
||||
@@ -113,6 +113,36 @@ def update_go_mod_require_pseudo_version(go_mod_text: str, dep_module_path: str,
|
||||
return re.sub(pattern_line, replacement_line, go_mod_text)
|
||||
|
||||
|
||||
def update_devcontainer_hugo(starter_dir: Path, latest_hugo: Optional[str], updated_paths: List[Path]) -> None:
|
||||
"""Update devcontainer Hugo feature version if present."""
|
||||
if not latest_hugo:
|
||||
return
|
||||
devcontainer = starter_dir / ".devcontainer" / "devcontainer.json"
|
||||
if not devcontainer.exists():
|
||||
return
|
||||
try:
|
||||
data = json.loads(devcontainer.read_text(encoding="utf-8"))
|
||||
except Exception as exc: # pragma: no cover - defensive
|
||||
logging.warning("starter %s: failed to parse devcontainer.json (%s)", starter_dir.name, exc)
|
||||
return
|
||||
|
||||
features = data.get("features", {})
|
||||
hugo_feature = features.get("ghcr.io/devcontainers/features/hugo:1")
|
||||
if not isinstance(hugo_feature, dict):
|
||||
return
|
||||
|
||||
current = hugo_feature.get("version")
|
||||
if current == latest_hugo:
|
||||
return
|
||||
|
||||
hugo_feature["version"] = latest_hugo
|
||||
features["ghcr.io/devcontainers/features/hugo:1"] = hugo_feature
|
||||
data["features"] = features
|
||||
devcontainer.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
||||
updated_paths.append(devcontainer)
|
||||
logging.info("starter %s: devcontainer Hugo version -> %s", starter_dir.name, latest_hugo)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Module:
|
||||
name: str # e.g., blox-tailwind
|
||||
@@ -512,17 +542,8 @@ def update_starters(modules: Dict[str, Module], commit: bool, push: bool) -> Non
|
||||
updated_paths.append(netlify)
|
||||
logging.info("starter %s: netlify.toml HUGO_VERSION -> %s", starter_dir.name, latest_hugo)
|
||||
|
||||
# bump deploy.yml env WC_HUGO_VERSION
|
||||
workflow = starter_dir / ".github" / "workflows" / "deploy.yml"
|
||||
if latest_hugo and workflow.exists():
|
||||
with workflow.open("r", encoding="utf-8") as f:
|
||||
wf = yaml.load(f) or {}
|
||||
if "env" in wf and wf["env"].get("WC_HUGO_VERSION") != latest_hugo:
|
||||
wf["env"]["WC_HUGO_VERSION"] = latest_hugo
|
||||
with workflow.open("w", encoding="utf-8") as f:
|
||||
yaml.dump(wf, f)
|
||||
updated_paths.append(workflow)
|
||||
logging.info("starter %s: deploy.yml WC_HUGO_VERSION -> %s", starter_dir.name, latest_hugo)
|
||||
# bump devcontainer Hugo version (new location for Hugo pin)
|
||||
update_devcontainer_hugo(starter_dir, latest_hugo, updated_paths)
|
||||
|
||||
if updated_paths:
|
||||
stage_and_maybe_commit(updated_paths, "chore(templates): bump modules and Hugo", commit, push)
|
||||
@@ -591,17 +612,8 @@ def update_starters_to_commits(modules: Dict[str, Module], commit: bool, push: b
|
||||
updated_paths.append(netlify)
|
||||
logging.info("starter %s: netlify.toml HUGO_VERSION -> %s", starter_dir.name, latest_hugo)
|
||||
|
||||
# bump deploy.yml env WC_HUGO_VERSION (same as regular update_starters)
|
||||
workflow = starter_dir / ".github" / "workflows" / "deploy.yml"
|
||||
if latest_hugo and workflow.exists():
|
||||
with workflow.open("r", encoding="utf-8") as f:
|
||||
wf = yaml.load(f) or {}
|
||||
if "env" in wf and wf["env"].get("WC_HUGO_VERSION") != latest_hugo:
|
||||
wf["env"]["WC_HUGO_VERSION"] = latest_hugo
|
||||
with workflow.open("w", encoding="utf-8") as f:
|
||||
yaml.dump(wf, f)
|
||||
updated_paths.append(workflow)
|
||||
logging.info("starter %s: deploy.yml WC_HUGO_VERSION -> %s", starter_dir.name, latest_hugo)
|
||||
# bump devcontainer Hugo version (same as regular update_starters)
|
||||
update_devcontainer_hugo(starter_dir, latest_hugo, updated_paths)
|
||||
|
||||
if updated_paths:
|
||||
stage_and_maybe_commit(updated_paths, "chore(templates): update modules to latest commits", commit, push)
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import re
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def update_file_regex(path, pattern, replacement):
|
||||
file_path = Path(path)
|
||||
if not file_path.exists():
|
||||
print(f"Warning: {path} not found.")
|
||||
return False
|
||||
|
||||
content = file_path.read_text()
|
||||
if re.search(pattern, content):
|
||||
new_content = re.sub(pattern, replacement, content)
|
||||
file_path.write_text(new_content)
|
||||
print(f"Updated {path}")
|
||||
return True
|
||||
else:
|
||||
print(f"Warning: Pattern not found in {path}")
|
||||
return False
|
||||
|
||||
def update_devcontainer(path, new_version):
|
||||
file_path = Path(path)
|
||||
if not file_path.exists():
|
||||
print(f"Warning: {path} not found.")
|
||||
return False
|
||||
|
||||
try:
|
||||
content = json.loads(file_path.read_text())
|
||||
# Update Hugo feature version
|
||||
features = content.get("features", {})
|
||||
hugo_feature = features.get("ghcr.io/devcontainers/features/hugo:1")
|
||||
if hugo_feature:
|
||||
hugo_feature["version"] = new_version
|
||||
file_path.write_text(json.dumps(content, indent=2) + "\n") # standard json formatting
|
||||
print(f"Updated {path}")
|
||||
return True
|
||||
else:
|
||||
print(f"Warning: Hugo feature not found in {path}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Error updating {path}: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Update Hugo version in template files")
|
||||
parser.add_argument("version", help="New Hugo version (e.g., 0.152.2)")
|
||||
args = parser.parse_args()
|
||||
|
||||
version = args.version
|
||||
|
||||
# List of templates to update
|
||||
templates = [
|
||||
"academic-cv",
|
||||
"blog",
|
||||
"documentation",
|
||||
"landing-page",
|
||||
"link-in-bio",
|
||||
"resume"
|
||||
]
|
||||
|
||||
for template in templates:
|
||||
print(f"\nProcessing template: {template}")
|
||||
template_dir = Path(f"templates/{template}")
|
||||
|
||||
# 1. Update hugoblox.yaml
|
||||
update_file_regex(
|
||||
template_dir / "hugoblox.yaml",
|
||||
r"hugo_version: .*",
|
||||
f"hugo_version: '{version}'"
|
||||
)
|
||||
|
||||
# 2. Update netlify.toml
|
||||
update_file_regex(
|
||||
template_dir / "netlify.toml",
|
||||
r'HUGO_VERSION = ".*"',
|
||||
f'HUGO_VERSION = "{version}"'
|
||||
)
|
||||
|
||||
# 3. Update devcontainer.json
|
||||
update_devcontainer(
|
||||
template_dir / ".devcontainer/devcontainer.json",
|
||||
version
|
||||
)
|
||||
|
||||
print(f"\nSuccessfully updated all templates to Hugo v{version}")
|
||||
print("Note: .github/workflows/deploy.yml is configured to read the version dynamically from hugoblox.yaml.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File renamed without changes.
@@ -12,7 +12,7 @@ sections:
|
||||
- block: resume-biography-3
|
||||
content:
|
||||
# Choose a user profile to display (a folder name within `content/authors/`)
|
||||
username: admin
|
||||
username: me
|
||||
text: ''
|
||||
# Show a call-to-action button under your biography? (optional)
|
||||
button:
|
||||
@@ -28,6 +28,10 @@ sections:
|
||||
gradient_mesh:
|
||||
enable: true
|
||||
|
||||
# Name heading sizing to accommodate long or short names
|
||||
name:
|
||||
size: balanced # Options: compact (long names), balanced (default), display (short names)
|
||||
|
||||
# Avatar customization
|
||||
avatar:
|
||||
size: medium # Options: small (150px), medium (200px, default), large (320px), xl (400px), xxl (500px)
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
---
|
||||
# Display name
|
||||
title: Alex Johnson
|
||||
|
||||
# Name pronunciation (optional)
|
||||
name_pronunciation: ''
|
||||
|
||||
# Full name (for SEO)
|
||||
first_name: Alex
|
||||
last_name: Johnson
|
||||
|
||||
# Pronouns (optional)
|
||||
pronouns: he/him
|
||||
|
||||
# Status emoji
|
||||
status:
|
||||
icon: 🚀
|
||||
|
||||
# Is this the primary user of the site?
|
||||
superuser: true
|
||||
|
||||
# Highlight the author in author lists? (true/false)
|
||||
highlight_name: true
|
||||
|
||||
# Role/position/tagline
|
||||
role: Senior AI Research Scientist
|
||||
|
||||
# Organizations/Affiliations to display in Biography blox
|
||||
organizations:
|
||||
- name: Meta AI
|
||||
url: https://ai.meta.com/
|
||||
|
||||
# Social network links
|
||||
# Need to use another icon? Simply download the SVG icon to your `assets/media/icons/` folder.
|
||||
profiles:
|
||||
- icon: at-symbol
|
||||
url: 'mailto:alex.johnson@meta.com'
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/AlexAIResearch
|
||||
- icon: brands/github
|
||||
url: https://github.com/alexjohnsonai
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/in/alexjohnsonai/
|
||||
- icon: academicons/google-scholar
|
||||
url: https://scholar.google.com/citations?user=alexjohnson
|
||||
- icon: academicons/orcid
|
||||
url: https://orcid.org/0000-0002-1825-0097
|
||||
|
||||
interests:
|
||||
- Large Language Models
|
||||
- Computer Vision
|
||||
- Reinforcement Learning
|
||||
- AI Ethics
|
||||
|
||||
education:
|
||||
- area: PhD Computer Science (AI Focus)
|
||||
institution: Stanford University
|
||||
icon: ""
|
||||
date_start: 2015-09-01
|
||||
date_end: 2019-06-30
|
||||
summary: |
|
||||
Thesis on _Scaling Laws for Neural Language Models_. Supervised by Prof. Andrew Ng. Published 5 papers in NeurIPS and ICML, with 2 best paper awards.
|
||||
button:
|
||||
text: 'Read Thesis'
|
||||
url: 'https://example.com/thesis.pdf'
|
||||
- area: MS Computer Science
|
||||
institution: Carnegie Mellon University
|
||||
icon: ""
|
||||
date_start: 2013-09-01
|
||||
date_end: 2015-05-31
|
||||
summary: |
|
||||
GPA: 4.0/4.0
|
||||
|
||||
Specialized in machine learning and robotics.
|
||||
- area: BS Computer Science
|
||||
institution: MIT
|
||||
icon: ""
|
||||
date_start: 2009-09-01
|
||||
date_end: 2013-05-31
|
||||
summary: |
|
||||
GPA: 3.9/4.0
|
||||
|
||||
Minored in Mathematics. President of AI Club.
|
||||
|
||||
work:
|
||||
- position: Senior AI Research Scientist
|
||||
company_name: Meta AI
|
||||
company_url: 'https://ai.meta.com/'
|
||||
icon: ''
|
||||
date_start: 2020-01-01
|
||||
date_end: ''
|
||||
summary: |2-
|
||||
Leading research on multimodal AI systems. Contributed to Llama 2 and other open-source models. 50+ citations in 3 years.
|
||||
- position: AI Research Intern
|
||||
company_name: OpenAI
|
||||
company_url: 'https://openai.com/'
|
||||
icon: ''
|
||||
date_start: 2019-06-01
|
||||
date_end: 2019-12-31
|
||||
summary: |
|
||||
Worked on GPT-3 scaling. Co-authored paper on prompt engineering.
|
||||
|
||||
# Skills
|
||||
# Add your own SVG icons to `assets/media/icons/`
|
||||
skills:
|
||||
- name: Technical Skills
|
||||
items:
|
||||
- name: Python & PyTorch
|
||||
description: ''
|
||||
percent: 95
|
||||
icon: code-bracket
|
||||
- name: Machine Learning
|
||||
description: ''
|
||||
percent: 100
|
||||
icon: chart-bar
|
||||
- name: Cloud Computing (AWS/GCP)
|
||||
description: ''
|
||||
percent: 85
|
||||
icon: cloud
|
||||
- name: Hobbies
|
||||
color: '#eeac02'
|
||||
color_border: '#f0bf23'
|
||||
items:
|
||||
- name: Hiking in the Rockies
|
||||
description: ''
|
||||
percent: 80
|
||||
icon: person-simple-walk
|
||||
- name: Building Custom PCs
|
||||
description: ''
|
||||
percent: 90
|
||||
icon: cpu-chip
|
||||
- name: Sci-Fi Reading
|
||||
description: ''
|
||||
percent: 70
|
||||
icon: book-open
|
||||
|
||||
languages:
|
||||
- name: English
|
||||
percent: 100
|
||||
- name: Spanish
|
||||
percent: 50
|
||||
|
||||
# Awards.
|
||||
# Add/remove as many awards below as you like.
|
||||
# Only `title`, `awarder`, and `date` are required.
|
||||
# Begin multi-line `summary` with YAML's `|` or `|2-` multi-line prefix and indent 2 spaces below.
|
||||
awards:
|
||||
- title: Best Paper Award
|
||||
url: https://neurips.cc/
|
||||
date: '2022-12-01'
|
||||
awarder: NeurIPS
|
||||
icon: hero/trophy
|
||||
summary: |
|
||||
Awarded for groundbreaking work on efficient training of large models.
|
||||
- title: AI Innovation Grant
|
||||
url: https://www.nsf.gov/
|
||||
date: '2021-06-15'
|
||||
awarder: National Science Foundation
|
||||
icon: hero/currency-dollar
|
||||
summary: |
|
||||
$500,000 grant for research in ethical AI development.
|
||||
- title: Outstanding PhD Thesis
|
||||
url: https://www.stanford.edu/
|
||||
date: '2019-06-30'
|
||||
awarder: Stanford University
|
||||
icon: hero/academic-cap
|
||||
summary: |
|
||||
Recognized for contributions to scaling laws in deep learning.
|
||||
---
|
||||
|
||||
Alex Johnson is a Senior AI Research Scientist at Meta AI, where he leads groundbreaking work on large language models and multimodal systems. His research has been published in top conferences like NeurIPS and ICML, with over 10,000 citations. Alex is passionate about pushing the boundaries of AI while ensuring ethical development. Outside of work, he enjoys hiking in the Rockies, building custom PCs, and mentoring the next generation of AI talent.
|
||||
@@ -3,7 +3,7 @@ title: 📈 Communicate your results effectively with the best data visualizatio
|
||||
summary: Use popular tools such as HuggingFace, Plotly, Mermaid, and data frames.
|
||||
date: 2023-10-25
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox
|
||||
|
||||
@@ -25,7 +25,7 @@ cover:
|
||||
name: "✨"
|
||||
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
- Ted
|
||||
|
||||
tags:
|
||||
|
||||
@@ -3,7 +3,7 @@ title: ⚡️ Turn Jupyter Notebooks into Blog Posts
|
||||
summary: Publish your data science and research directly from Jupyter Notebooks. No screenshots required.
|
||||
date: 2024-07-15
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo Blox
|
||||
- Jupyter
|
||||
|
||||
@@ -3,7 +3,7 @@ title: ✅ Manage your projects
|
||||
summary: Easily manage your projects - create ideation mind maps, Gantt charts, todo lists, and more!
|
||||
date: 2023-10-23
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo Blox
|
||||
- Markdown
|
||||
|
||||
@@ -3,7 +3,7 @@ title: 🧠 Sharpen your thinking with a second brain
|
||||
summary: Create a personal knowledge base and share your knowledge with your peers.
|
||||
date: 2023-10-26
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Second Brain
|
||||
- Markdown
|
||||
|
||||
@@ -4,7 +4,7 @@ summary: Embed videos, podcasts, code, LaTeX math, and even test students!
|
||||
date: 2023-10-24
|
||||
math: true
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox Builder
|
||||
|
||||
@@ -25,7 +25,7 @@ all_day: false
|
||||
publishDate: '2017-01-01T00:00:00Z'
|
||||
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
|
||||
tags: []
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ design:
|
||||
sections:
|
||||
- block: resume-experience
|
||||
content:
|
||||
username: admin
|
||||
username: me
|
||||
design:
|
||||
# Hugo date format
|
||||
date_format: 'January 2006'
|
||||
@@ -21,15 +21,13 @@ sections:
|
||||
- block: resume-skills
|
||||
content:
|
||||
title: Skills & Hobbies
|
||||
username: admin
|
||||
design:
|
||||
show_skill_percentage: false
|
||||
username: me
|
||||
- block: resume-awards
|
||||
content:
|
||||
title: Awards
|
||||
username: admin
|
||||
username: me
|
||||
- block: resume-languages
|
||||
content:
|
||||
title: Languages
|
||||
username: admin
|
||||
username: me
|
||||
---
|
||||
@@ -2,10 +2,10 @@
|
||||
title: 'An example conference paper'
|
||||
|
||||
# Authors
|
||||
# If you created a profile for a user (e.g. the default `admin` user), write the username (folder name) here
|
||||
# If you created a profile for a user (e.g. the default `me` user), write the username (folder name) here
|
||||
# and it will be replaced with their full name and linked to their profile.
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
- Robert Ford
|
||||
|
||||
# Author notes (optional)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "An example journal article"
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
- Robert Ford
|
||||
author_notes:
|
||||
- "Equal contribution"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "An example preprint / working paper"
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
date: "2019-04-07T00:00:00Z"
|
||||
|
||||
# Schedule page publish date (NOT publication's date).
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
schema: hugoblox/author/v1
|
||||
slug: me
|
||||
is_owner: true
|
||||
name:
|
||||
display: Dr. Alex Johnson
|
||||
given: Alex
|
||||
family: Johnson
|
||||
alternate: '' # Example: 王伟
|
||||
pronunciation: '' # Example: Wáng Wěi
|
||||
pronouns: he/him
|
||||
postnominals:
|
||||
- PhD
|
||||
- MIEEE
|
||||
status:
|
||||
icon: "☕️"
|
||||
role: Senior AI Research Scientist
|
||||
bio: |
|
||||
Alex Johnson is a Senior AI Research Scientist at Meta AI. His research
|
||||
has been published in top conferences like NeurIPS and ICML, with over
|
||||
10,000 citations. Alex is passionate about pushing the boundaries of AI
|
||||
while ensuring ethical development.
|
||||
|
||||
affiliations:
|
||||
- name: Meta AI
|
||||
url: https://ai.meta.com/
|
||||
|
||||
links:
|
||||
- icon: at-symbol
|
||||
url: mailto:alex.johnson@example.com
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/example
|
||||
- icon: brands/github
|
||||
url: https://github.com/example
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/in/example/
|
||||
- icon: academicons/google-scholar
|
||||
url: https://scholar.google.com/citations?user=example
|
||||
- icon: academicons/orcid
|
||||
url: https://orcid.org/0000-0002-1825-0097
|
||||
|
||||
interests:
|
||||
- Large Language Models
|
||||
- Computer Vision
|
||||
- Reinforcement Learning
|
||||
- AI Ethics
|
||||
|
||||
education:
|
||||
- degree: PhD Computer Science
|
||||
institution: Stanford University
|
||||
start: 2015-09-01
|
||||
end: 2019-06-30
|
||||
summary: |
|
||||
Thesis on scaling laws for neural language models. Published 5 papers in NeurIPS and ICML.
|
||||
button:
|
||||
text: Download dissertation
|
||||
url: /resume.pdf
|
||||
icon: hero/arrow-down-tray
|
||||
- degree: MS Computer Science
|
||||
institution: Carnegie Mellon University
|
||||
start: 2013-09-01
|
||||
end: 2015-05-31
|
||||
- degree: BS Computer Science
|
||||
institution: MIT
|
||||
start: 2009-09-01
|
||||
end: 2013-05-31
|
||||
|
||||
experience:
|
||||
- role: Senior AI Research Scientist
|
||||
org: Meta AI
|
||||
start: 2020-01-01
|
||||
summary: |
|
||||
Leading research on multimodal AI systems. Contributed to Llama 2 and other open-source models.
|
||||
button:
|
||||
text: View portfolio
|
||||
url: /
|
||||
icon: hero/arrow-down-tray
|
||||
- role: AI Research Intern
|
||||
org: OpenAI
|
||||
start: 2019-06-01
|
||||
end: 2019-12-31
|
||||
summary: |
|
||||
Worked on GPT-3 scaling. Co-authored paper on prompt engineering.
|
||||
|
||||
skills:
|
||||
- name: Technical Skills
|
||||
items:
|
||||
- label: Pytho
|
||||
level: 5
|
||||
- label: Machine Learning
|
||||
level: 5
|
||||
- label: Cloud Computing
|
||||
level: 4
|
||||
- name: Research & Communication
|
||||
items:
|
||||
- label: Academic Writing
|
||||
level: 5
|
||||
- label: Conference Presentations
|
||||
level: 4
|
||||
- label: Grant Proposals
|
||||
level: 4
|
||||
|
||||
languages:
|
||||
- name: English
|
||||
level: 5
|
||||
label: Native
|
||||
- name: Spanish
|
||||
level: 4
|
||||
label: Fluent
|
||||
|
||||
awards:
|
||||
- title: Best Paper Award
|
||||
awarder: NeurIPS
|
||||
date: "2022-12-01"
|
||||
summary: Awarded for groundbreaking work on efficient training of large models.
|
||||
icon: hero/trophy
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/hugo:1": {
|
||||
"extended": true,
|
||||
"version": "0.152.2"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"hugoblox.hugoblox-studio"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "pnpm install --no-frozen-lockfile && hugo --logLevel debug && pnpm dlx pagefind --source 'public' --verbose",
|
||||
"postAttachCommand": "(code --command workbench.view.extension.hugoblox-studio || true) && hugo server --disableFastRender -D --port 1313",
|
||||
"forwardPorts": [
|
||||
1313
|
||||
]
|
||||
}
|
||||
+7
-2
@@ -1,7 +1,6 @@
|
||||
name: Deploy website to GitHub Pages
|
||||
|
||||
env:
|
||||
WC_HUGO_VERSION: '0.152.2'
|
||||
NODE_VERSION: '20'
|
||||
|
||||
on:
|
||||
@@ -42,6 +41,12 @@ jobs:
|
||||
if: hashFiles('package.json') != ''
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Get Hugo Version
|
||||
id: hugo-version
|
||||
run: |
|
||||
VERSION=$(grep "hugo_version" hugoblox.yaml | awk '{print $2}' | tr -d "'\"")
|
||||
echo "HUGO_VERSION=$VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# Install Tailwind CLI if package.json exists
|
||||
@@ -53,7 +58,7 @@ jobs:
|
||||
- name: Setup Hugo
|
||||
uses: peaceiris/actions-hugo@v3
|
||||
with:
|
||||
hugo-version: ${{ env.WC_HUGO_VERSION }}
|
||||
hugo-version: ${{ env.HUGO_VERSION }}
|
||||
extended: true
|
||||
|
||||
# Cache dependencies (Go modules, node_modules) - stable, rarely changes
|
||||
|
||||
File renamed without changes.
@@ -5,8 +5,8 @@ type: landing
|
||||
sections:
|
||||
- block: resume-biography
|
||||
content:
|
||||
# The user's folder name in content/authors/
|
||||
username: admin
|
||||
# Author slug (data/authors/<slug>.yaml)
|
||||
username: me
|
||||
design:
|
||||
spacing:
|
||||
padding: [0, 0, 0, 0]
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
---
|
||||
# Display name
|
||||
title: 吳健雄
|
||||
|
||||
# Name pronunciation (optional)
|
||||
name_pronunciation: Chien Shiung Wu
|
||||
|
||||
# Full name (for SEO)
|
||||
first_name: Shiung Wu
|
||||
last_name: Chien
|
||||
|
||||
# Pronouns (optional)
|
||||
pronouns: she/her
|
||||
|
||||
# Status emoji
|
||||
status:
|
||||
icon: ☕️
|
||||
|
||||
# Is this the primary user of the site?
|
||||
superuser: true
|
||||
|
||||
# Role/position/tagline
|
||||
role: Professor of Artificial Intelligence
|
||||
|
||||
# Organizations/Affiliations to show in About widget
|
||||
organizations:
|
||||
- name: Stanford University
|
||||
url: https://www.stanford.edu/
|
||||
|
||||
# Short bio (displayed in user profile at end of posts)
|
||||
bio: My research interests include distributed robotics, mobile computing and programmable matter.
|
||||
|
||||
# Social Networking
|
||||
# Need to use another icon? Simply download the SVG icon to your `assets/media/icons/` folder.
|
||||
profiles:
|
||||
- icon: at-symbol
|
||||
url: 'mailto:your-email@example.com'
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/BuildLore
|
||||
- icon: brands/instagram
|
||||
url: https://www.instagram.com/
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/
|
||||
# Link to a PDF of your resume/CV - upload it to `static/uploads/resume.pdf`
|
||||
- icon: academicons/cv
|
||||
url: uploads/resume.pdf
|
||||
label: Download my resume
|
||||
- icon: rss
|
||||
url: ./post/index.xml
|
||||
label: Subscribe to my blog via RSS feed
|
||||
|
||||
# Highlight the author in author lists? (true/false)
|
||||
highlight_name: true
|
||||
|
||||
# Author's website URL
|
||||
website: ""
|
||||
---
|
||||
|
||||
Chien Shiung Wu is a professor of artificial intelligence at the Stanford AI Lab. Her research interests include
|
||||
distributed robotics, mobile computing and programmable matter. She leads the Robotic Neurobiology group, which develops
|
||||
self-reconfiguring robots, systems of self-organizing robots, and mobile sensor networks.
|
||||
@@ -3,7 +3,7 @@ title: 📈 Communicate your results effectively with the best data visualizatio
|
||||
summary: Use popular tools such as Plotly, Mermaid, and data frames.
|
||||
date: 2023-10-25
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox
|
||||
|
||||
@@ -9,7 +9,7 @@ image:
|
||||
caption: 'Image credit: [**Unsplash**](https://unsplash.com)'
|
||||
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
- Ted
|
||||
|
||||
tags:
|
||||
|
||||
@@ -3,7 +3,7 @@ title: ✅ Manage your projects
|
||||
summary: Easily manage your projects - create ideation mind maps, Gantt charts, todo lists, and more!
|
||||
date: 2023-10-23
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo Blox
|
||||
- Markdown
|
||||
|
||||
@@ -3,7 +3,7 @@ title: 🧠 Sharpen your thinking with a second brain
|
||||
summary: Create a personal knowledge base and share your knowledge with your peers.
|
||||
date: 2023-10-26
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Second Brain
|
||||
- Markdown
|
||||
|
||||
@@ -4,7 +4,7 @@ summary: Embed videos, podcasts, code, LaTeX math, and even test students!
|
||||
date: 2023-10-24
|
||||
math: true
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox Builder
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
schema: hugoblox/author/v1
|
||||
slug: me
|
||||
is_owner: true
|
||||
name:
|
||||
display: 吳健雄
|
||||
given: Shiung Wu
|
||||
family: Chien
|
||||
pronunciation: Chien Shiung Wu
|
||||
pronouns: she/her
|
||||
status:
|
||||
icon: "☕️"
|
||||
role: Professor of Artificial Intelligence
|
||||
bio: My research interests include distributed robotics, mobile computing and programmable matter.
|
||||
affiliations:
|
||||
- name: Stanford University
|
||||
url: https://www.stanford.edu/
|
||||
links:
|
||||
- icon: at-symbol
|
||||
url: mailto:your-email@example.com
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/BuildLore
|
||||
- icon: brands/instagram
|
||||
url: https://www.instagram.com/
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/
|
||||
- icon: academicons/cv
|
||||
url: uploads/resume.pdf
|
||||
label: Download my resume
|
||||
- icon: rss
|
||||
url: ./post/index.xml
|
||||
label: Subscribe to my blog via RSS feed
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/hugo:1": {
|
||||
"extended": true,
|
||||
"version": "0.152.2"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"hugoblox.hugoblox-studio"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "pnpm install --no-frozen-lockfile && hugo --logLevel debug && pnpm dlx pagefind --source 'public' --verbose",
|
||||
"postAttachCommand": "(code --command workbench.view.extension.hugoblox-studio || true) && hugo server --disableFastRender -D --port 1313",
|
||||
"forwardPorts": [
|
||||
1313
|
||||
]
|
||||
}
|
||||
+7
-2
@@ -1,7 +1,6 @@
|
||||
name: Deploy website to GitHub Pages
|
||||
|
||||
env:
|
||||
WC_HUGO_VERSION: '0.152.2'
|
||||
NODE_VERSION: '20'
|
||||
|
||||
on:
|
||||
@@ -42,6 +41,12 @@ jobs:
|
||||
if: hashFiles('package.json') != ''
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Get Hugo Version
|
||||
id: hugo-version
|
||||
run: |
|
||||
VERSION=$(grep "hugo_version" hugoblox.yaml | awk '{print $2}' | tr -d "'\"")
|
||||
echo "HUGO_VERSION=$VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# Install Tailwind CLI if package.json exists
|
||||
@@ -53,7 +58,7 @@ jobs:
|
||||
- name: Setup Hugo
|
||||
uses: peaceiris/actions-hugo@v3
|
||||
with:
|
||||
hugo-version: ${{ env.WC_HUGO_VERSION }}
|
||||
hugo-version: ${{ env.HUGO_VERSION }}
|
||||
extended: true
|
||||
|
||||
# Cache dependencies (Go modules, node_modules) - stable, rarely changes
|
||||
|
||||
File renamed without changes.
@@ -1,62 +0,0 @@
|
||||
---
|
||||
# Display name
|
||||
title: 吳健雄
|
||||
|
||||
# Name pronunciation (optional)
|
||||
name_pronunciation: Chien Shiung Wu
|
||||
|
||||
# Full name (for SEO)
|
||||
first_name: Shiung Wu
|
||||
last_name: Chien
|
||||
|
||||
# Pronouns (optional)
|
||||
pronouns: she/her
|
||||
|
||||
# Status emoji
|
||||
status:
|
||||
icon: ☕️
|
||||
|
||||
# Is this the primary user of the site?
|
||||
superuser: true
|
||||
|
||||
# Role/position/tagline
|
||||
role: Professor of Artificial Intelligence
|
||||
|
||||
# Organizations/Affiliations to show in About widget
|
||||
organizations:
|
||||
- name: Stanford University
|
||||
url: https://www.stanford.edu/
|
||||
|
||||
# Short bio (displayed in user profile at end of posts)
|
||||
bio: My research interests include distributed robotics, mobile computing and programmable matter.
|
||||
|
||||
# Social Networking
|
||||
# Need to use another icon? Simply download the SVG icon to your `assets/media/icons/` folder.
|
||||
profiles:
|
||||
- icon: at-symbol
|
||||
url: 'mailto:your-email@example.com'
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/BuildLore
|
||||
- icon: brands/instagram
|
||||
url: https://www.instagram.com/
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/
|
||||
# Link to a PDF of your resume/CV - upload it to `static/uploads/resume.pdf`
|
||||
- icon: academicons/cv
|
||||
url: uploads/resume.pdf
|
||||
label: Download my resume
|
||||
- icon: rss
|
||||
url: ./post/index.xml
|
||||
label: Subscribe to my blog via RSS feed
|
||||
|
||||
# Highlight the author in author lists? (true/false)
|
||||
highlight_name: true
|
||||
|
||||
# Author's website URL
|
||||
website: ""
|
||||
---
|
||||
|
||||
Chien Shiung Wu is a professor of artificial intelligence at the Stanford AI Lab. Her research interests include
|
||||
distributed robotics, mobile computing and programmable matter. She leads the Robotic Neurobiology group, which develops
|
||||
self-reconfiguring robots, systems of self-organizing robots, and mobile sensor networks.
|
||||
@@ -3,7 +3,7 @@ title: v1.0.0 Released!
|
||||
summary: Hugo v1.0.0 released. Download now and follow the guide to get started in 5 minutes!
|
||||
date: 2023-01-01
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox
|
||||
|
||||
@@ -3,7 +3,7 @@ title: v2.0.0 Released!
|
||||
summary: Hugo v2.0.0 released. Download now and follow the guide to get started in 5 minutes!
|
||||
date: 2024-01-19
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
title: Nvidia
|
||||
summary: nvidia.com
|
||||
external_link: https://research.nvidia.com/labs/toronto-ai/
|
||||
links:
|
||||
- type: site
|
||||
url: https://research.nvidia.com/labs/toronto-ai/
|
||||
date: 2024-02-17
|
||||
---
|
||||
@@ -0,0 +1,32 @@
|
||||
schema: hugoblox/author/v1
|
||||
slug: me
|
||||
is_owner: true
|
||||
name:
|
||||
display: 吳健雄
|
||||
given: Shiung Wu
|
||||
family: Chien
|
||||
pronunciation: Chien Shiung Wu
|
||||
pronouns: she/her
|
||||
status:
|
||||
icon: "☕️"
|
||||
role: Professor of Artificial Intelligence
|
||||
bio: My research interests include distributed robotics, mobile computing and programmable matter.
|
||||
affiliations:
|
||||
- name: Stanford University
|
||||
url: https://www.stanford.edu/
|
||||
links:
|
||||
- icon: at-symbol
|
||||
url: mailto:your-email@example.com
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/BuildLore
|
||||
- icon: brands/instagram
|
||||
url: https://www.instagram.com/
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/
|
||||
- icon: academicons/cv
|
||||
url: uploads/resume.pdf
|
||||
label: Download my resume
|
||||
- icon: rss
|
||||
url: ./post/index.xml
|
||||
label: Subscribe to my blog via RSS feed
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/hugo:1": {
|
||||
"extended": true,
|
||||
"version": "0.152.2"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"hugoblox.hugoblox-studio"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "pnpm install --no-frozen-lockfile && hugo --logLevel debug && pnpm dlx pagefind --source 'public' --verbose",
|
||||
"postAttachCommand": "(code --command workbench.view.extension.hugoblox-studio || true) && hugo server --disableFastRender -D --port 1313",
|
||||
"forwardPorts": [
|
||||
1313
|
||||
]
|
||||
}
|
||||
+7
-2
@@ -1,7 +1,6 @@
|
||||
name: Deploy website to GitHub Pages
|
||||
|
||||
env:
|
||||
WC_HUGO_VERSION: '0.152.2'
|
||||
NODE_VERSION: '20'
|
||||
|
||||
on:
|
||||
@@ -42,6 +41,12 @@ jobs:
|
||||
if: hashFiles('package.json') != ''
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Get Hugo Version
|
||||
id: hugo-version
|
||||
run: |
|
||||
VERSION=$(grep "hugo_version" hugoblox.yaml | awk '{print $2}' | tr -d "'\"")
|
||||
echo "HUGO_VERSION=$VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# Install Tailwind CLI if package.json exists
|
||||
@@ -53,7 +58,7 @@ jobs:
|
||||
- name: Setup Hugo
|
||||
uses: peaceiris/actions-hugo@v3
|
||||
with:
|
||||
hugo-version: ${{ env.WC_HUGO_VERSION }}
|
||||
hugo-version: ${{ env.HUGO_VERSION }}
|
||||
extended: true
|
||||
|
||||
# Cache dependencies (Go modules, node_modules) - stable, rarely changes
|
||||
|
||||
File renamed without changes.
@@ -1,62 +0,0 @@
|
||||
---
|
||||
# Display name
|
||||
title: 吳健雄
|
||||
|
||||
# Name pronunciation (optional)
|
||||
name_pronunciation: Chien Shiung Wu
|
||||
|
||||
# Full name (for SEO)
|
||||
first_name: Shiung Wu
|
||||
last_name: Chien
|
||||
|
||||
# Pronouns (optional)
|
||||
pronouns: she/her
|
||||
|
||||
# Status emoji
|
||||
status:
|
||||
icon: ☕️
|
||||
|
||||
# Is this the primary user of the site?
|
||||
superuser: true
|
||||
|
||||
# Role/position/tagline
|
||||
role: Professor of Artificial Intelligence
|
||||
|
||||
# Organizations/Affiliations to show in About widget
|
||||
organizations:
|
||||
- name: Stanford University
|
||||
url: https://www.stanford.edu/
|
||||
|
||||
# Short bio (displayed in user profile at end of posts)
|
||||
bio: My research interests include distributed robotics, mobile computing and programmable matter.
|
||||
|
||||
# Social Networking
|
||||
# Need to use another icon? Simply download the SVG icon to your `assets/media/icons/` folder.
|
||||
profiles:
|
||||
- icon: at-symbol
|
||||
url: 'mailto:your-email@example.com'
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/BuildLore
|
||||
- icon: brands/instagram
|
||||
url: https://www.instagram.com/
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/
|
||||
# Link to a PDF of your resume/CV - upload it to `static/uploads/resume.pdf`
|
||||
- icon: academicons/cv
|
||||
url: uploads/resume.pdf
|
||||
label: Download my resume
|
||||
- icon: rss
|
||||
url: ./post/index.xml
|
||||
label: Subscribe to my blog via RSS feed
|
||||
|
||||
# Highlight the author in author lists? (true/false)
|
||||
highlight_name: true
|
||||
|
||||
# Author's website URL
|
||||
website: ""
|
||||
---
|
||||
|
||||
Chien Shiung Wu is a professor of artificial intelligence at the Stanford AI Lab. Her research interests include
|
||||
distributed robotics, mobile computing and programmable matter. She leads the Robotic Neurobiology group, which develops
|
||||
self-reconfiguring robots, systems of self-organizing robots, and mobile sensor networks.
|
||||
@@ -3,7 +3,7 @@ title: 📈 Communicate your results effectively with the best data visualizatio
|
||||
summary: Use popular tools such as Plotly, Mermaid, and data frames.
|
||||
date: 2023-10-25
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox
|
||||
|
||||
@@ -9,7 +9,7 @@ image:
|
||||
caption: 'Image credit: [**Unsplash**](https://unsplash.com)'
|
||||
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
- Ted
|
||||
|
||||
tags:
|
||||
|
||||
@@ -3,7 +3,7 @@ title: ✅ Manage your projects
|
||||
summary: Easily manage your projects - create ideation mind maps, Gantt charts, todo lists, and more!
|
||||
date: 2023-10-23
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo Blox
|
||||
- Markdown
|
||||
|
||||
@@ -3,7 +3,7 @@ title: 🧠 Sharpen your thinking with a second brain
|
||||
summary: Create a personal knowledge base and share your knowledge with your peers.
|
||||
date: 2023-10-26
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Second Brain
|
||||
- Markdown
|
||||
|
||||
@@ -4,7 +4,7 @@ summary: Embed videos, podcasts, code, LaTeX math, and even test students!
|
||||
date: 2023-10-24
|
||||
math: true
|
||||
authors:
|
||||
- admin
|
||||
- me
|
||||
tags:
|
||||
- Hugo
|
||||
- Hugo Blox Builder
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
schema: hugoblox/author/v1
|
||||
slug: me
|
||||
is_owner: true
|
||||
name:
|
||||
display: 吳健雄
|
||||
given: Shiung Wu
|
||||
family: Chien
|
||||
pronunciation: Chien Shiung Wu
|
||||
pronouns: she/her
|
||||
status:
|
||||
icon: "☕️"
|
||||
role: Professor of Artificial Intelligence
|
||||
bio: My research interests include distributed robotics, mobile computing and programmable matter.
|
||||
affiliations:
|
||||
- name: Stanford University
|
||||
url: https://www.stanford.edu/
|
||||
links:
|
||||
- icon: at-symbol
|
||||
url: mailto:your-email@example.com
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/BuildLore
|
||||
- icon: brands/instagram
|
||||
url: https://www.instagram.com/
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/
|
||||
- icon: academicons/cv
|
||||
url: uploads/resume.pdf
|
||||
label: Download my resume
|
||||
- icon: rss
|
||||
url: ./post/index.xml
|
||||
label: Subscribe to my blog via RSS feed
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/hugo:1": {
|
||||
"extended": true,
|
||||
"version": "0.152.2"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"hugoblox.hugoblox-studio"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "pnpm install --no-frozen-lockfile && hugo --logLevel debug && pnpm dlx pagefind --source 'public' --verbose",
|
||||
"postAttachCommand": "(code --command workbench.view.extension.hugoblox-studio || true) && hugo server --disableFastRender -D --port 1313",
|
||||
"forwardPorts": [
|
||||
1313
|
||||
]
|
||||
}
|
||||
+7
-2
@@ -1,7 +1,6 @@
|
||||
name: Deploy website to GitHub Pages
|
||||
|
||||
env:
|
||||
WC_HUGO_VERSION: '0.152.2'
|
||||
NODE_VERSION: '20'
|
||||
|
||||
on:
|
||||
@@ -42,6 +41,12 @@ jobs:
|
||||
if: hashFiles('package.json') != ''
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Get Hugo Version
|
||||
id: hugo-version
|
||||
run: |
|
||||
VERSION=$(grep "hugo_version" hugoblox.yaml | awk '{print $2}' | tr -d "'\"")
|
||||
echo "HUGO_VERSION=$VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# Install Tailwind CLI if package.json exists
|
||||
@@ -53,7 +58,7 @@ jobs:
|
||||
- name: Setup Hugo
|
||||
uses: peaceiris/actions-hugo@v3
|
||||
with:
|
||||
hugo-version: ${{ env.WC_HUGO_VERSION }}
|
||||
hugo-version: ${{ env.HUGO_VERSION }}
|
||||
extended: true
|
||||
|
||||
# Cache dependencies (Go modules, node_modules) - stable, rarely changes
|
||||
|
||||
File renamed without changes.
@@ -13,7 +13,7 @@ sections:
|
||||
- block: resume-biography
|
||||
content:
|
||||
# The user's folder name in content/authors/
|
||||
username: admin
|
||||
username: me
|
||||
design:
|
||||
biography:
|
||||
style: 'text-align: justify; font-size: 0.8em;'
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
---
|
||||
# Display name
|
||||
title: Alex Johnson
|
||||
|
||||
# Name pronunciation (optional)
|
||||
name_pronunciation: ''
|
||||
|
||||
# Full name (for SEO)
|
||||
first_name: Alex
|
||||
last_name: Johnson
|
||||
|
||||
# Pronouns (optional)
|
||||
pronouns: he/him
|
||||
|
||||
# Status emoji
|
||||
status:
|
||||
icon: 🚀
|
||||
|
||||
# Is this the primary user of the site?
|
||||
superuser: true
|
||||
|
||||
# Highlight the author in author lists? (true/false)
|
||||
highlight_name: true
|
||||
|
||||
# Role/position/tagline
|
||||
role: Senior AI Research Scientist
|
||||
|
||||
# Organizations/Affiliations to display in Biography blox
|
||||
organizations:
|
||||
- name: Meta AI
|
||||
url: https://ai.meta.com/
|
||||
|
||||
# Social network links
|
||||
# Need to use another icon? Simply download the SVG icon to your `assets/media/icons/` folder.
|
||||
profiles:
|
||||
- icon: at-symbol
|
||||
url: 'mailto:alex.johnson@meta.com'
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/AlexAIResearch
|
||||
- icon: brands/github
|
||||
url: https://github.com/alexjohnsonai
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/in/alexjohnsonai/
|
||||
- icon: academicons/google-scholar
|
||||
url: https://scholar.google.com/citations?user=alexjohnson
|
||||
- icon: academicons/orcid
|
||||
url: https://orcid.org/0000-0002-1825-0097
|
||||
|
||||
interests:
|
||||
- Large Language Models
|
||||
- Computer Vision
|
||||
- Reinforcement Learning
|
||||
- AI Ethics
|
||||
|
||||
education:
|
||||
- area: PhD Computer Science (AI Focus)
|
||||
institution: Stanford University
|
||||
date_start: 2015-09-01
|
||||
date_end: 2019-06-30
|
||||
summary: |
|
||||
Thesis on _Scaling Laws for Neural Language Models_. Supervised by Prof. Andrew Ng. Published 5 papers in NeurIPS and ICML, with 2 best paper awards.
|
||||
button:
|
||||
text: 'Read Thesis'
|
||||
url: 'https://example.com/thesis.pdf'
|
||||
- area: MS Computer Science
|
||||
institution: Carnegie Mellon University
|
||||
date_start: 2013-09-01
|
||||
date_end: 2015-05-31
|
||||
summary: |
|
||||
GPA: 4.0/4.0
|
||||
|
||||
Specialized in machine learning and robotics.
|
||||
- area: BS Computer Science
|
||||
institution: MIT
|
||||
date_start: 2009-09-01
|
||||
date_end: 2013-05-31
|
||||
summary: |
|
||||
GPA: 3.9/4.0
|
||||
|
||||
Minored in Mathematics. President of AI Club.
|
||||
|
||||
work:
|
||||
- position: Senior AI Research Scientist
|
||||
company_name: Meta AI
|
||||
company_url: 'https://ai.meta.com/'
|
||||
company_logo: ''
|
||||
date_start: 2020-01-01
|
||||
date_end: ''
|
||||
summary: |2-
|
||||
Leading research on multimodal AI systems. Contributed to Llama 2 and other open-source models. 50+ citations in 3 years.
|
||||
- position: AI Research Intern
|
||||
company_name: OpenAI
|
||||
company_url: 'https://openai.com/'
|
||||
company_logo: ''
|
||||
date_start: 2019-06-01
|
||||
date_end: 2019-12-31
|
||||
summary: |
|
||||
Worked on GPT-3 scaling. Co-authored paper on prompt engineering.
|
||||
|
||||
# Skills
|
||||
# Add your own SVG icons to `assets/media/icons/`
|
||||
skills:
|
||||
- name: Technical Skills
|
||||
items:
|
||||
- name: Python & PyTorch
|
||||
description: ''
|
||||
percent: 95
|
||||
icon: code-bracket
|
||||
- name: Machine Learning
|
||||
description: ''
|
||||
percent: 100
|
||||
icon: chart-bar
|
||||
- name: Cloud Computing (AWS/GCP)
|
||||
description: ''
|
||||
percent: 85
|
||||
icon: cloud
|
||||
- name: Hobbies
|
||||
color: '#eeac02'
|
||||
color_border: '#f0bf23'
|
||||
items:
|
||||
- name: Hiking in the Rockies
|
||||
description: ''
|
||||
percent: 80
|
||||
icon: person-simple-walk
|
||||
- name: Building Custom PCs
|
||||
description: ''
|
||||
percent: 90
|
||||
icon: cpu-chip
|
||||
- name: Sci-Fi Reading
|
||||
description: ''
|
||||
percent: 70
|
||||
icon: book-open
|
||||
|
||||
languages:
|
||||
- name: English
|
||||
percent: 100
|
||||
- name: Spanish
|
||||
percent: 50
|
||||
|
||||
# Awards.
|
||||
# Add/remove as many awards below as you like.
|
||||
# Only `title`, `awarder`, and `date` are required.
|
||||
# Begin multi-line `summary` with YAML's `|` or `|2-` multi-line prefix and indent 2 spaces below.
|
||||
awards:
|
||||
- title: Best Paper Award
|
||||
url: https://neurips.cc/
|
||||
date: '2022-12-01'
|
||||
awarder: NeurIPS
|
||||
icon: hero/trophy
|
||||
summary: |
|
||||
Awarded for groundbreaking work on efficient training of large models.
|
||||
- title: AI Innovation Grant
|
||||
url: https://www.nsf.gov/
|
||||
date: '2021-06-15'
|
||||
awarder: National Science Foundation
|
||||
icon: hero/currency-dollar
|
||||
summary: |
|
||||
$500,000 grant for research in ethical AI development.
|
||||
- title: Outstanding PhD Thesis
|
||||
url: https://www.stanford.edu/
|
||||
date: '2019-06-30'
|
||||
awarder: Stanford University
|
||||
icon: hero/academic-cap
|
||||
summary: |
|
||||
Recognized for contributions to scaling laws in deep learning.
|
||||
---
|
||||
|
||||
Alex Johnson is a Senior AI Research Scientist at Meta AI, where he leads groundbreaking work on large language models and multimodal systems. His research has been published in top conferences like NeurIPS and ICML, with over 10,000 citations. Alex is passionate about pushing the boundaries of AI while ensuring ethical development. Outside of work, he enjoys hiking in the Rockies, building custom PCs, and mentoring the next generation of AI talent.
|
||||
@@ -0,0 +1,125 @@
|
||||
schema: hugoblox/author/v1
|
||||
slug: me
|
||||
is_owner: true
|
||||
name:
|
||||
display: Alex Johnson
|
||||
given: Alex
|
||||
family: Johnson
|
||||
pronouns: he/him
|
||||
status:
|
||||
icon: "🚀"
|
||||
role: Senior AI Research Scientist
|
||||
bio: >
|
||||
Alex Johnson is a Senior AI Research Scientist at Meta AI, where he leads groundbreaking work on large language models
|
||||
and multimodal systems. His research has been published in top conferences like NeurIPS and ICML, with over 10,000
|
||||
citations. Alex is passionate about pushing the boundaries of AI while ensuring ethical development. Outside of work,
|
||||
he enjoys hiking in the Rockies, building custom PCs, and mentoring the next generation of AI talent.
|
||||
affiliations:
|
||||
- name: Meta AI
|
||||
url: https://ai.meta.com/
|
||||
links:
|
||||
- icon: at-symbol
|
||||
url: mailto:alex.johnson@meta.com
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/AlexAIResearch
|
||||
- icon: brands/github
|
||||
url: https://github.com/alexjohnsonai
|
||||
- icon: brands/linkedin
|
||||
url: https://www.linkedin.com/in/alexjohnsonai/
|
||||
- icon: academicons/google-scholar
|
||||
url: https://scholar.google.com/citations?user=alexjohnson
|
||||
- icon: academicons/orcid
|
||||
url: https://orcid.org/0000-0002-1825-0097
|
||||
interests:
|
||||
- Large Language Models
|
||||
- Computer Vision
|
||||
- Reinforcement Learning
|
||||
- AI Ethics
|
||||
education:
|
||||
- degree: PhD Computer Science (AI Focus)
|
||||
institution: Stanford University
|
||||
start: 2015-09-01
|
||||
end: 2019-06-30
|
||||
summary: |
|
||||
Thesis on _Scaling Laws for Neural Language Models_. Supervised by Prof. Andrew Ng. Published 5 papers in NeurIPS and ICML, with 2 best paper awards.
|
||||
button:
|
||||
text: 'Read Thesis'
|
||||
url: 'https://example.com/thesis.pdf'
|
||||
- degree: MS Computer Science
|
||||
institution: Carnegie Mellon University
|
||||
start: 2013-09-01
|
||||
end: 2015-05-31
|
||||
summary: |
|
||||
GPA: 4.0/4.0
|
||||
|
||||
Specialized in machine learning and robotics.
|
||||
- degree: BS Computer Science
|
||||
institution: MIT
|
||||
start: 2009-09-01
|
||||
end: 2013-05-31
|
||||
summary: |
|
||||
GPA: 3.9/4.0
|
||||
|
||||
Minored in Mathematics. President of AI Club.
|
||||
experience:
|
||||
- role: Senior AI Research Scientist
|
||||
org: Meta AI
|
||||
start: 2020-01-01
|
||||
summary: |
|
||||
Leading research on multimodal AI systems. Contributed to Llama 2 and other open-source models. 50+ citations in 3 years.
|
||||
- role: AI Research Intern
|
||||
org: OpenAI
|
||||
start: 2019-06-01
|
||||
end: 2019-12-31
|
||||
summary: |
|
||||
Worked on GPT-3 scaling. Co-authored paper on prompt engineering.
|
||||
skills:
|
||||
- name: Technical Skills
|
||||
items:
|
||||
- label: Python & PyTorch
|
||||
level: 5
|
||||
icon: code-bracket
|
||||
- label: Machine Learning
|
||||
level: 5
|
||||
icon: chart-bar
|
||||
- label: Cloud Computing (AWS/GCP)
|
||||
level: 4
|
||||
icon: cloud
|
||||
- name: Hobbies
|
||||
color: '#eeac02'
|
||||
color_border: '#f0bf23'
|
||||
items:
|
||||
- label: Hiking in the Rockies
|
||||
level: 4
|
||||
icon: person-simple-walk
|
||||
- label: Building Custom PCs
|
||||
level: 5
|
||||
icon: cpu-chip
|
||||
- label: Sci-Fi Reading
|
||||
level: 4
|
||||
icon: book-open
|
||||
languages:
|
||||
- name: English
|
||||
level: 5
|
||||
- name: Spanish
|
||||
level: 3
|
||||
awards:
|
||||
- title: Best Paper Award
|
||||
url: https://neurips.cc/
|
||||
date: '2022-12-01'
|
||||
awarder: NeurIPS
|
||||
icon: hero/trophy
|
||||
summary: Awarded for groundbreaking work on efficient training of large models.
|
||||
- title: AI Innovation Grant
|
||||
url: https://www.nsf.gov/
|
||||
date: '2021-06-15'
|
||||
awarder: National Science Foundation
|
||||
icon: hero/currency-dollar
|
||||
summary: $500,000 grant for research in ethical AI development.
|
||||
- title: Outstanding PhD Thesis
|
||||
url: https://www.stanford.edu/
|
||||
date: '2019-06-30'
|
||||
awarder: Stanford University
|
||||
icon: hero/academic-cap
|
||||
summary: Recognized for contributions to scaling laws in deep learning.
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/hugo:1": {
|
||||
"extended": true,
|
||||
"version": "0.152.2"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"hugoblox.hugoblox-studio"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "pnpm install --no-frozen-lockfile && hugo --logLevel debug && pnpm dlx pagefind --source 'public' --verbose",
|
||||
"postAttachCommand": "(code --command workbench.view.extension.hugoblox-studio || true) && hugo server --disableFastRender -D --port 1313",
|
||||
"forwardPorts": [
|
||||
1313
|
||||
]
|
||||
}
|
||||
+7
-2
@@ -1,7 +1,6 @@
|
||||
name: Deploy website to GitHub Pages
|
||||
|
||||
env:
|
||||
WC_HUGO_VERSION: '0.152.2'
|
||||
NODE_VERSION: '20'
|
||||
|
||||
on:
|
||||
@@ -42,6 +41,12 @@ jobs:
|
||||
if: hashFiles('package.json') != ''
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Get Hugo Version
|
||||
id: hugo-version
|
||||
run: |
|
||||
VERSION=$(grep "hugo_version" hugoblox.yaml | awk '{print $2}' | tr -d "'\"")
|
||||
echo "HUGO_VERSION=$VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# Install Tailwind CLI if package.json exists
|
||||
@@ -53,7 +58,7 @@ jobs:
|
||||
- name: Setup Hugo
|
||||
uses: peaceiris/actions-hugo@v3
|
||||
with:
|
||||
hugo-version: ${{ env.WC_HUGO_VERSION }}
|
||||
hugo-version: ${{ env.HUGO_VERSION }}
|
||||
extended: true
|
||||
|
||||
# Cache dependencies (Go modules, node_modules) - stable, rarely changes
|
||||
|
||||
File renamed without changes.
@@ -13,7 +13,7 @@ design:
|
||||
sections:
|
||||
- block: biography
|
||||
content:
|
||||
username: admin
|
||||
username: me
|
||||
# Show a call-to-action button under your biography? (optional)
|
||||
button:
|
||||
text: Download Résumé
|
||||
@@ -31,7 +31,7 @@ sections:
|
||||
shape: rounded # Options: circle (default), square, rounded
|
||||
- block: experience
|
||||
content:
|
||||
username: admin
|
||||
username: me
|
||||
design:
|
||||
# Hugo date format
|
||||
date_format: 'January 2006'
|
||||
@@ -40,13 +40,13 @@ sections:
|
||||
- block: skills
|
||||
content:
|
||||
title: Skills & Hobbies
|
||||
username: admin
|
||||
username: me
|
||||
- block: awards
|
||||
content:
|
||||
title: Awards
|
||||
username: admin
|
||||
username: me
|
||||
- block: languages
|
||||
content:
|
||||
title: Languages
|
||||
username: admin
|
||||
username: me
|
||||
---
|
||||
+49
-92
@@ -1,37 +1,24 @@
|
||||
---
|
||||
# Display name
|
||||
title: 吳健雄
|
||||
|
||||
# Name pronunciation (optional)
|
||||
name_pronunciation: Chien Shiung Wu
|
||||
|
||||
# Full name (for SEO)
|
||||
first_name: Shiung Wu
|
||||
last_name: Chien
|
||||
|
||||
# Pronouns (optional)
|
||||
pronouns: she/her
|
||||
|
||||
# Status emoji
|
||||
schema: hugoblox/author/v1
|
||||
slug: me
|
||||
is_owner: true
|
||||
name:
|
||||
display: 吳健雄
|
||||
given: Shiung Wu
|
||||
family: Chien
|
||||
pronunciation: Chien Shiung Wu
|
||||
pronouns: she/her
|
||||
status:
|
||||
icon: ☕️
|
||||
|
||||
# Is this the primary user of the site?
|
||||
superuser: true
|
||||
|
||||
# Role/position/tagline
|
||||
icon: "☕️"
|
||||
role: Director of Cloud Infrastructure
|
||||
|
||||
# Organizations/Affiliations to display in Biography blox
|
||||
organizations:
|
||||
bio: >
|
||||
I am currently Director of Cloud Infrastructure at GenCoin where I am leading
|
||||
teams on edge computing, deep sea data center architecture, and hivemind optimization.
|
||||
affiliations:
|
||||
- name: GenCoin
|
||||
url: https://www.example.com/
|
||||
|
||||
# Social network links
|
||||
# Need to use another icon? Simply download the SVG icon to your `assets/media/icons/` folder.
|
||||
profiles:
|
||||
links:
|
||||
- icon: at-symbol
|
||||
url: 'mailto:your-email@example.com'
|
||||
url: mailto:your-email@example.com
|
||||
label: E-mail Me
|
||||
- icon: brands/x
|
||||
url: https://x.com/BuildLore
|
||||
@@ -41,21 +28,20 @@ profiles:
|
||||
url: https://www.linkedin.com/
|
||||
- icon: brands/instagram
|
||||
url: https://www.instagram.com/
|
||||
|
||||
education:
|
||||
- area: PhD Artificial Intelligence
|
||||
- degree: PhD Artificial Intelligence
|
||||
institution: Stanford University
|
||||
date_start: 2016-01-01
|
||||
date_end: 2020-12-31
|
||||
start: 2016-01-01
|
||||
end: 2020-12-31
|
||||
summary: |
|
||||
Thesis on _Why LLMs are awesome_. Supervised by [Prof Joe Smith](https://example.com). Presented papers at 5 IEEE conferences with the contributions being published in 2 Springer journals.
|
||||
button:
|
||||
text: 'Read Thesis'
|
||||
url: 'https://example.com'
|
||||
- area: MEng Artificial Intelligence
|
||||
- degree: MEng Artificial Intelligence
|
||||
institution: Massachusetts Institute of Technology
|
||||
date_start: 2016-01-01
|
||||
date_end: 2020-12-31
|
||||
start: 2016-01-01
|
||||
end: 2020-12-31
|
||||
summary: |
|
||||
GPA: 3.8/4.0
|
||||
|
||||
@@ -63,10 +49,10 @@ education:
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- area: BSc Artificial Intelligence
|
||||
- degree: BSc Artificial Intelligence
|
||||
institution: Massachusetts Institute of Technology
|
||||
date_start: 2016-01-01
|
||||
date_end: 2020-12-31
|
||||
start: 2016-01-01
|
||||
end: 2020-12-31
|
||||
summary: |
|
||||
GPA: 3.4/4.0
|
||||
|
||||
@@ -74,76 +60,50 @@ education:
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
work:
|
||||
- position: Director of Cloud Infrastructure
|
||||
company_name: GenCoin
|
||||
company_url: ''
|
||||
company_logo: ''
|
||||
date_start: 2021-01-01
|
||||
date_end: ''
|
||||
summary: |2-
|
||||
experience:
|
||||
- role: Director of Cloud Infrastructure
|
||||
org: GenCoin
|
||||
start: 2021-01-01
|
||||
summary: |
|
||||
Responsibilities include:
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- position: Backend Software Engineer
|
||||
company_name: X
|
||||
company_url: ''
|
||||
company_logo: ''
|
||||
date_start: 2016-01-01
|
||||
date_end: 2020-12-31
|
||||
- role: Backend Software Engineer
|
||||
org: X
|
||||
start: 2016-01-01
|
||||
end: 2020-12-31
|
||||
summary: |
|
||||
Responsibilities include:
|
||||
- Migrated infrastructure to a new data center
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
- lorem ipsum dolor sit amet, consectetur adipiscing elit
|
||||
|
||||
# Skills
|
||||
# Add your own SVG icons to `assets/media/icons/`
|
||||
skills:
|
||||
- name: Technical Skills
|
||||
items:
|
||||
- name: Python
|
||||
description: ''
|
||||
percent: 80
|
||||
icon: devicon/python
|
||||
- name: RStudio
|
||||
description: ''
|
||||
percent: 100
|
||||
icon: devicon/rstudio
|
||||
- name: PyTorch
|
||||
description: ''
|
||||
percent: 40
|
||||
icon: devicon/pytorch
|
||||
- label: Python
|
||||
level: 4
|
||||
- label: RStudio
|
||||
level: 5
|
||||
- label: PyTorch
|
||||
level: 2
|
||||
- name: Hobbies
|
||||
color: '#eeac02'
|
||||
color_border: '#f0bf23'
|
||||
items:
|
||||
- name: Hiking
|
||||
description: ''
|
||||
percent: 60
|
||||
icon: person-simple-walk
|
||||
- name: Cats
|
||||
description: ''
|
||||
percent: 100
|
||||
icon: cat
|
||||
- name: Photography
|
||||
description: ''
|
||||
percent: 80
|
||||
icon: camera
|
||||
|
||||
- label: Hiking
|
||||
level: 3
|
||||
- label: Cats
|
||||
level: 5
|
||||
- label: Photography
|
||||
level: 4
|
||||
languages:
|
||||
- name: English
|
||||
percent: 100
|
||||
level: 5
|
||||
- name: Chinese
|
||||
percent: 75
|
||||
level: 4
|
||||
- name: Portuguese
|
||||
percent: 25
|
||||
|
||||
# Awards.
|
||||
# Add/remove as many awards below as you like.
|
||||
# Only `title`, `awarder`, and `date` are required.
|
||||
# Begin multi-line `summary` with YAML's `|` or `|2-` multi-line prefix and indent 2 spaces below.
|
||||
level: 1
|
||||
awards:
|
||||
- title: Neural Networks and Deep Learning
|
||||
url: https://www.coursera.org/learn/neural-networks-deep-learning
|
||||
@@ -170,6 +130,3 @@ awards:
|
||||
icon: brands/datacamp
|
||||
summary: |
|
||||
Object-oriented programming (OOP) lets you specify relationships between functions and the objects that they can act on, helping you manage complexity in your code. This is an intermediate level course, providing an introduction to OOP, using the S3 and R6 systems. S3 is a great day-to-day R programming tool that simplifies some of the functions that you write. R6 is especially useful for industry-specific analyses, working with web APIs, and building GUIs.
|
||||
---
|
||||
|
||||
I am currently Director of Cloud Infrastructure at GenCoin where I am leading teams on edge computing, deep sea data center architecture, and hivemind optimization.
|
||||
Reference in new issue
Block a user