Init Commit

This commit is contained in:
2026-05-18 11:46:02 +02:00
commit 2de3502fbc
382 changed files with 19583 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
{{ define "main" }}
<section id="main-content" class="section four-o-four">
<div class="container text-center">
<h1 class="display-1">404</h1>
<h4>{{ i18n "404_title" }}</h4>
<p>
{{ i18n "404_description" }}
</p>
<a href="{{ .Site.BaseURL | absURL }}" class="btn btn-primary">{{ i18n "404_button" }}</a>
</div>
</section>
{{ end }}
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="{{- $.Lang }}"
{{- if .Site.Params.colorTheme.auto.disable }}
data-bs-theme="{{ .Site.Params.colorTheme.forced.theme }}"
theme-forced="true"
theme-auto="false"
{{- end }}>
<head>
{{ partial "head.html" . }}
{{ partial "head_custom.html" . }}
</head>
<body class="{{- if .IsHome }}home{{- end }}{{- with .File }} page-{{- .ContentBaseName }}{{- end }}">
{{ partial "header.html" . }}
<main class="container">
{{ block "main" . }}{{ end }}
</main>
<div class="d-print-none">
{{ partial "footer.html" . }}
</div>
{{ partial "base-foot.html" . }}
{{ block "footerfiles" . }}
{{ end }}
</body>
</html>
@@ -0,0 +1,72 @@
<!-- inject:../components/baseHead/baseHeadStart.html -->
<!DOCTYPE html>
<html lang="{{- $.Lang }}"
{{- if .Site.Params.colorTheme.auto.disable }}
data-bs-theme="{{ .Site.Params.colorTheme.forced.theme }}"
theme-forced="true"
theme-auto="false"
{{- end }}>
<head>
{{ partial "head.html" . }}
{{ partial "head_custom.html" . }}
</head>
{{/*
This template iterates through all pages in the site and logs debugging information.
For each page, it prints:
- File path (if file exists)
- Draft status
- Page type
- Section
- Kind
If a page doesn't have an associated file, it logs that information separately.
Warning levels are used to make the output visible in Hugo's build logs.
*/}}
{{ range .Site.Pages }}
{{ if .File }}
{{ warnf "Path: %s | Lang: %s | IsDraft: %t | Type: %s | Section: %s | Kind: %s" .File.Path .Lang .Draft .Type .Section .Kind }}
{{ else }}
{{ warnf "No .File for this page: Type=%s, Section=%s, Kind=%s" .Type .Section .Kind }}
{{ end }}
{{ end }}
<body class="{{ if .IsHome }}home{{ end }}">
{{ partial "header.html" . }}
{{ $home := where (where .Site.Pages "Type" "home") "Lang" .Lang }}
{{ $homeCount := len $home }}
{{ range $home }}
{{ if .File }}
{{ warnf "[HOME] Path: %s | Lang: %s | IsDraft: %t | Type: %s | Section: %s | Kind: %s" .File.Path .Lang .Draft .Type .Section .Kind }}
{{ end }}
{{ end }}
{{ if lt $homeCount 1 }}
<!-- DEFAULT -->
{{ warnf "Adritian: No homepage found for lang '%s' (%d 'home' items). Please create a home in your content folder." .Lang ($homeCount) }}
{{ warnf "Adritian: (deprecated) Using Site.Params.Sections to render homepage for lang '%s'." .Lang }}
{{ range .Site.Params.sections }}
{{ partial . $ }}
{{ end }}
{{ else }}
{{ range (sort $home "Date" "desc") }}
{{ warnf "Adritian: Using 'home' content type to render homepage." }}
<div class="container home-container">
{{ .Content | safeHTML }}
</div>
{{ end }}
{{ end }}
{{ partial "footer.html" . }}
{{ partial "base-foot.html" . }}
</body>
</html>
<!-- endinject -->
@@ -0,0 +1,5 @@
{{- $.Scratch.Add "index" slice -}}
{{- range .Site.RegularPages -}}
{{- $.Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}
@@ -0,0 +1,32 @@
{{ define "main" }}
<div class="list flex-grow-1">
<section id="main-content" class="section list-{{ .Kind }}">
<h1>{{ .Title }}</h1>
{{ if eq .Kind "taxonomy" }}
<ul class="list list-{{ .Kind }}">
{{ range .Data.Terms.ByCount }}
<li class="item item-{{ .Page.Kind }}">
<a href="{{ .Page.RelPermalink }}">{{ .Page.Title }}</a> ({{ .Count }})
</li>
{{ end }}
</ul>
{{ else }}
{{ if eq .Site.Params.blog.listStyle "summary" }}
<div class="posts-list">
{{ range .Pages }}
<div class="row row--padded rad-animation-group rad-fade-down rad-waiting rad-animate section--border-bottom">
{{ .Render "summary" }}
</div>
{{ end }}
</div>
{{ else }}
<ul class="posts-list-simple">
{{ range .Pages }}
{{ .Render "li" }}
{{ end }}
</ul>
{{ end }}
{{ end }}
</section>
</div>
{{ end }}
@@ -0,0 +1,49 @@
{{ define "footerfiles" }}
<script src="{{ "js/fuse.min.js" | absURL }}"></script>
<script src="{{ "js/search.js" | absURL }}"></script>
<script src="{{ "js/purify.min.js" | absURL }}"></script>
{{ end }}
{{ define "main" }}
<section id="main-content" class="search-section p-3 p-lg-5 d-flex flex-column align-items-center bg-light rounded shadow-sm">
<div class="my-auto w-100" style="max-width: 760px;">
<h2 class="mb-4 text-center">Search the Site</h2>
<noscript>
<div class="alert alert-warning" role="alert">
JavaScript is required to use the search functionality, because the search takes place client-side in the web browser.
<br/>
Please enable JavaScript in your browser to use this functionality.
</div>
</noscript>
<div class="mb-5">
<form action="{{ "search" | absURL }}">
<div class="input-group">
<input id="search-query" name="s" class="form-control form-control-lg" type="search" placeholder="Type to search..." autocomplete="off" aria-label="Search" />
<button type="submit" class="input-group-text">
<i class="icon-circle-arrow-right"></i>
</button>
</div>
</form>
</div>
<div id="search-results" class="card border-0">
<div class="card-body">
<h3 class="card-title">Matching pages</h3>
<!-- Results will appear here -->
</div>
</div>
</div>
</section>
<!-- this template is sucked in by search.js and appended to the search-results div above. So editing here will adjust style -->
<script id="search-result-template" type="text/x-js-template">
<div id="summary-${key}" class="mb-4 p-3 border-bottom">
<h4 class="mb-1"><a href="${link}" class="text-decoration-none">${title}</a></h4>
<p class="mb-2 text-muted small">${snippet}</p>
${ isset tags }<span class="badge bg-primary me-1">Tags: ${tags}</span>${ end }
${ isset categories }<span class="badge bg-secondary">Categories: ${categories}</span>${ end }
</div>
</script>
{{ end }}
@@ -0,0 +1,37 @@
{{ define "main" }}
<div class="section">
<div class="container">
<div class="row">
<div class="col-12">
<h1>{{ .Title }}</h1>
{{ if .Params.description }}
<p class="lead">{{ .Params.description }}</p>
{{ end }}
<div class="content">
{{ .Content }}
</div>
{{ if .Pages }}
<div class="section-posts mt-5">
<div class="posts-list">
{{ $paginator := .Paginate (.Pages.ByDate.Reverse) }}
{{ range $paginator.Pages }}
<article class="post mb-4">
<h3><a href="{{ .Permalink }}">{{ .Title }}</a></h3>
{{ if .Summary }}
<div>{{ .Summary | safeHTML }}</div>
{{ end }}
<div class="post-meta">
<small class="text-muted">{{ .Date.Format "January 2, 2006" }}</small>
</div>
</article>
{{ end }}
</div>
</div>
{{ end }}
</div>
</div>
</div>
</div>
{{ end }}
@@ -0,0 +1,12 @@
{{ define "main" }}
<section id="main">
{{ if not .Params.hideTitle }}
<h1 id="title">{{ .Title }}</h1>
{{ end }}
<div>
<article id="content">
{{ .Content }}
</article>
</div>
</section>
{{ end }}
+4
View File
@@ -0,0 +1,4 @@
<li class="post">
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
+157
View File
@@ -0,0 +1,157 @@
{{ define "main" }}
<div id="main-content" class="blog flex-grow-1">
<div class="section">
<div
class="row {{ if or (eq .Site.Params.blog.layout "sidebar") (eq .Site.Params.blog.layout "sidebar-right") }}
has-sidebar
{{ end }}">
{{ if eq .Site.Params.blog.layout "sidebar" }}
<div
class="col-sidebar"
style="width: {{ .Site.Params.blog.sidebarWidth }}%">
{{ partial "blog-sidebar.html" . }}
</div>
{{ end }}
<div
class="col-content {{ if ne .Site.Params.blog.narrowContent false }}narrow-content{{ end }}"
{{ if or (eq .Site.Params.blog.layout "sidebar") (eq .Site.Params.blog.layout "sidebar-right") }}
style="width: calc(100% - {{ .Site.Params.blog.sidebarWidth }}%)"
{{ end }}>
<h1 class="rad-fade-down rad-waiting rad-animate">{{ .Title }}</h1>
{{ .Content }}
<!-- Main Featured Post - Full Width Design -->
<div class="featured-post-container">
{{ $featuredPosts := where .Pages ".Params.featured" true }}
{{ if isset .Site.Params "blog" }}
{{ if isset .Site.Params.blog "featured_sort_by_weight" }}
{{ if .Site.Params.blog.featured_sort_by_weight }}
{{ $featuredPosts = sort $featuredPosts "Weight" }}
{{ end }}
{{ else }}
{{ $featuredPosts = sort $featuredPosts "Date" "desc" }}
{{ end }}
{{ else }}
{{ $featuredPosts = sort $featuredPosts "Date" "desc" }}
{{ end }}
{{ $mainFeaturedPost := first 1 $featuredPosts }}
{{ if $mainFeaturedPost }}
{{ range $mainFeaturedPost }}
<div class="p-4 p-md-5 mb-4 rounded text-body-emphasis bg-body-secondary">
<div class="row align-items-center">
<div class="col-lg-8 px-0">
<h2 class="display-4 fst-italic">
{{ .Title }}
</h2>
<div class="lead my-3">
{{ .Summary | plainify | safeHTML }}
</div>
<p class="lead mb-0">
<a href="{{ .RelPermalink }}" class="text-body-emphasis fw-bold">
Continue reading...
</a>
</p>
</div>
{{ if isset .Params "images" }}
{{ with .Params.images }}
{{ if isset . "featured_image" }}
<div class="col-lg-4 d-flex justify-content-center align-items-center mt-4 mt-lg-0">
<img src="{{ .featured_image }}" alt="{{ $.Title }}" class="featured-thumbnail img-fluid rounded">
</div>
{{ end }}
{{ end }}
{{ end }}
</div>
</div>
{{ end }}
{{ else }}
<!-- no featured post is found -->
{{ end }}
</div>
<div class="row mb-2">
<!-- Secondary featured posts (2-3rd featured posts) -->
{{ $secondaryFeaturedPosts := after 1 $featuredPosts | first 2 }}
{{ if $secondaryFeaturedPosts }}
{{ range $secondaryFeaturedPosts }}
<div class="col-md-6">
<div class="row g-0 border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
<div class="col p-4 d-flex flex-column position-static">
{{ with .GetTerms "topics" }}
{{ range first 1 . }}
<strong class="d-inline-block mb-2 text-primary-emphasis">
{{ .LinkTitle }}
</strong>
{{ end }}
{{ end }}
<h3 class="mb-0">{{ .Title }}</h3>
<div class="mb-1 text-body-secondary">{{ .Date.Format "Jan 2, 2006" }}</div>
<div class="card-text mb-auto">
{{ .Summary | plainify | truncate 120 }}
</div>
<a href="{{ .RelPermalink }}" class="icon-link gap-1 icon-link-hover stretched-link">
Continue reading
<svg class="bi" aria-hidden="true" width="16" height="16" focusable="false">
<use xlink:href="#chevron-right"></use>
</svg>
</a>
</div>
<div class="col-auto d-none d-lg-block">
{{ if isset .Params "images" }}
{{ with .Params.images }}
{{ if isset . "featured_image" }}
<img src="{{ .featured_image }}" width="200" height="250" alt="{{ $.Title }}" class="secondary-featured-img">
{{ else }}
<svg class="bd-placeholder-img" width="200" height="250" xmlns="http://www.w3.org/2000/svg"
role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice"
focusable="false">
<title>Placeholder</title>
<rect width="100%" height="100%" fill="#55595c"></rect>
<text x="50%" y="50%" fill="#eceeef" dy=".3em">Thumbnail</text>
</svg>
{{ end }}
{{ end }}
{{ else }}
<svg class="bd-placeholder-img" width="200" height="250" xmlns="http://www.w3.org/2000/svg"
role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice"
focusable="false">
<title>Placeholder</title>
<rect width="100%" height="100%" fill="#55595c"></rect>
<text x="50%" y="50%" fill="#eceeef" dy=".3em">Thumbnail</text>
</svg>
{{ end }}
</div>
</div>
</div>
{{ end }}
{{ end }}
</div>
<div class="posts-list">
{{ $allPosts := .Pages }}
{{ $nonFeaturedPosts := where $allPosts ".Params.featured" "!=" true }}
{{ range $nonFeaturedPosts }}
<div
class="row row--padded rad-animation-group rad-fade-down rad-waiting rad-animate section--border-bottom">
{{ .Render "summary" }}
</div>
{{ end }}
</div>
</div>
{{ if eq .Site.Params.blog.layout "sidebar-right" }}
<div
class="col-sidebar"
style="width: {{ .Site.Params.blog.sidebarWidth }}%">
{{ partial "blog-sidebar.html" . }}
</div>
{{ end }}
</div>
</div>
</div>
{{ end }}
+65
View File
@@ -0,0 +1,65 @@
{{ define "main" }}
<section id="blog-single" class="blog-single section section--border-bottom rad-animation-group flex-grow-1">
<div id="main-content">
<h1><a href="{{ .RelPermalink }}">{{ .Title }}</a></h1>
<aside id="meta" class="light-border-bottom">
<div>
<section>
{{ i18n "published_on" }}&nbsp;<h4 id="date">{{ .Date.Format "Mon Jan 2, 2006" }}</h4>
·
<h4 id="wordcount">{{ .WordCount }} Words</h4>
{{ $readingTime := div .WordCount 200 }}
{{ if lt $readingTime 1 }}
{{ $readingTime = 1 }}
{{ end }}
&nbsp;·&nbsp;
<h4 id="reading-time">{{ $readingTime }} {{ i18n "min_read" | default "min read" }}</h4>
{{ if .Params.lastmod }}
&nbsp;·&nbsp;
<h4 id="last-modified">{{ i18n "last_updated" | default "Updated" }}: {{ .Lastmod.Format "Jan 2, 2006" }}</h4>
{{ end }}
</section>
{{ with .GetTerms "topics" }}
<ul id="topics">
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
{{ end }} {{ with .GetTerms "tags" }}
<ul class="tags">
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
{{ end }}
</div>
</aside>
{{ partial "toc.html" . }}
<div class="row flex-column-reverse flex-md-row rad-fade-down">
<div class="col-12">{{ .Content | safeHTML }}</div>
</div>
{{ partial "social-sharing.html" . }}
{{ partial "related-posts.html" . }}
<aside class="content-browser light-border-top">
{{ i18n "continue_reading" }}
<div>
{{ with .PrevInSection }}
<a class="previous" href="{{ .RelPermalink }}">↩ {{ .LinkTitle }}</a>
{{ end }}
{{ with .NextInSection }}
<a class="next" href="{{ .RelPermalink }}"> {{ .LinkTitle }} ↪</a>
{{ end }}
</div>
</aside>
{{ partial "comments.html" . }}
</div>
</section>
{{ end }}
+40
View File
@@ -0,0 +1,40 @@
<article class="post summary col-12">
<header>
<h2 class="post-title"><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
<div class="post-meta">
<div>
<div class="post-meta-info">
<span class="published-label">{{ i18n "published_on" }}</span>
<time class="date" datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "Mon Jan 2, 2006" }}</time> ·
<span class="wordcount">{{ .WordCount }} Words</span>
</div>
{{ with .GetTerms "topics" }}
<ul class="topics">
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
{{ end }} {{ with .GetTerms "tags" }}
<ul class="tags">
{{ range . }}
<li class="border"><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
{{ end }}
</div>
</div>
</header>
<div class="post-summary post-content">
{{ .Summary | safeHTML }}
</div>
<footer class="">
<div class="row">
<div class="col-12 col-lg-4">
<a class="btn btn-outline-secondary btn-sm" href="{{ .RelPermalink }}"
>{{ i18n "read_more" }}&nbsp;&raquo;</a
>
</div>
</div>
</footer>
</article>
@@ -0,0 +1,3 @@
{{ define "main" }}
{{ partial "experience.html" . }}
{{ end }}
@@ -0,0 +1,68 @@
{{ define "main" }}
<section
id="experience"
class="section section--border-bottom rad-animation-group flex-grow-1"
>
<div id="main-content">
<div class="row flex-column-reverse flex-md-row rad-fade-down">
<div class="col-12 col-md-5 mt-5 mt-sm-0">
{{ $baseLangSite := .Sites.Default }}
{{ $currentPageID := .Page.File.UniqueID }}
{{ $xp := (where .Site.RegularPages.ByDate.Reverse "Type" "experience") }}
{{ $xp = $xp | lang.Merge (where $baseLangSite.RegularPages.ByDate.Reverse "Type" "experience") }}
{{ range $xp }}
<div class="experience {{ if eq .Page.File.UniqueID $currentPageID }} selected {{ end }}" >
<a href="{{.Permalink | relURL}}">
{{/* The context, ".", is now each one of the pages as it goes
through the loop */}}
{{ $img := resources.Get .Params.companyLogo }}
{{ with $img }}
{{ $imgWebp := $img.Resize (printf "%dx%d webp q75 Lanczos picture" $img.Width $img.Height) }}
<div class="experience__header with-company-logo">
<img
src="{{ $imgWebp.RelPermalink }}"
alt="{{ .Params.company }} logo"
class="experience__company-logo"
loading="lazy"
>
{{ else }}
<div class="experience__header no-company-logo">
{{ end }}
<div class="experience__meta">
<div class="experience__date">{{ .Params.duration }}</div>
<div class="experience__title">{{ .Params.jobTitle }}</div>
<div class="experience__company">{{ .Params.company }}. <span class="experience__location">
{{ .Params.location }}</span></div>
</div>
</div>
</a>
</div>
{{ end }}
</div>
<div class="col-12 col-md-7 mt-7 mt-sm-0">
{{ if (default true .Site.Params.experience.showJobCard) }}
<div class="job-card mb-5">
{{ $img := resources.Get .Params.companyLogo }}
{{ with $img }}
<div class="with-company-logo d-flex align-items-center mb-3">
{{ $imgWebp := $img.Resize (printf "%dx%d webp q75 Lanczos picture" $img.Width $img.Height) }}
<img src="{{ $imgWebp.RelPermalink }}" alt="{{ $.Params.company }} logo" class="company-logo me-3" style="max-height: 50px;">
{{ else }}
<div class="no-company-logo d-flex align-items-center mb-3">
{{ end }}
<div>
<h2 class="h4 mb-1">{{ .Params.jobTitle }}</h2>
<div class="job-card__location text-muted">{{ .Params.company }} • {{ .Params.location }}</div>
<div class="job-card__dates text-muted">{{ .Params.duration }}</div>
</div>
</div>
</div>
{{ end }}
<h1>{{ .Params.title }}</h1>
{{ .Content | safeHTML }}
</div>
</div>
</div>
</section>
{{ end }}
+5
View File
@@ -0,0 +1,5 @@
{{/*
This is an empty template for footer section list pages.
It intentionally does not generate any HTML output when accessed directly.
This prevents the generation of both index.html and index.xml for the footer section.
*/}}
+5
View File
@@ -0,0 +1,5 @@
{{/*
This is an empty template for footer section RSS feeds.
It intentionally does not generate any XML output.
This prevents the generation of index.xml for the footer section.
*/}}
@@ -0,0 +1,5 @@
{{/*
This is an empty template for footer type content.
It intentionally does not generate any HTML output when accessed directly.
The footer content is only meant to be included in other templates via partial or shortcode calls.
*/}}
@@ -0,0 +1,98 @@
{{- $contextType := printf "%T" . -}}
{{- $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") -}}
{{/* ---------------------------------------------------------------------------
TITLE AND CONTENT
--------------------------------------------------------------------------- */}}
{{- $title := "" -}}
{{- $content := "" -}}
{{- if $isShortcode }}
{{- $title = .Get "title" | default ( i18n "about_title" ) -}}
{{- $content = .Get "content" | default ( i18n "about_content" ) | safeHTML -}}
{{ else }}
{{- $title = i18n "about_title" -}}
{{- $content = i18n "about_content" | safeHTML -}}
{{ end }}
{{/* ---------------------------------------------------------------------------
IMAGES
--------------------------------------------------------------------------- */}}
{{- $imgSrc := "" -}}
{{- $imgWidth := 0 -}}
{{- $imgHeight := 0 -}}
{{- $imgScale := 0.5 -}}
{{- if $isShortcode }}
{{- $imgSrc = .Get "imgSrc" | default .Site.Data.homepage.about.image.src -}}
{{- $imgWidth = .Get "imgWidth" | default .Site.Data.homepage.about.image.width -}}
{{- $imgHeight = .Get "imgHeight" | default .Site.Data.homepage.about.image.height -}}
{{- $imgScale = .Get "imgScale" | default .Site.Data.homepage.about.image.scale -}}
{{ else }}
{{- $imgSrc = .Site.Data.homepage.about.image.src -}}
{{- $imgWidth = .Site.Data.homepage.about.image.width -}}
{{- $imgHeight = .Site.Data.homepage.about.image.height -}}
{{- $imgScale = .Site.Data.homepage.about.image.scale -}}
{{ end }}
{{/* ---------------------------------------------------------------------------
ALIGNMENT
--------------------------------------------------------------------------- */}}
{{- $vAlign := "center" -}}
{{- $hAlign := "left" -}}
{{- if $isShortcode }}
{{- /* Support both v_align and text_align for backwards compatibility */ -}}
{{- $vAlign = .Get "v_align" | default (.Get "text_align") | default "center" -}}
{{- $hAlign = .Get "h_align" | default "left" -}}
{{ else }}
{{- /* Support both v_align and text_align for backwards compatibility */ -}}
{{- $vAlign = .Site.Data.homepage.about.v_align | default .Site.Data.homepage.about.text_align | default "center" -}}
{{- $hAlign = .Site.Data.homepage.about.h_align | default "left" -}}
{{ end }}
{{/* ---------------------------------------------------------------------------
BUTTON
--------------------------------------------------------------------------- */}}
{{- $btnURL := "" -}}
{{- $btnIcon := "" -}}
{{- $btnText := "" -}}
{{- if $isShortcode }}
{{- $btnURL = .Get "button_url" | default .Site.Data.homepage.about.button.URL -}}
{{- $btnIcon = .Get "button_icon" | default .Site.Data.homepage.about.button.icon -}}
{{- $btnText = .Get "button_text" | default false -}}
{{ else }}
{{- $btnURL = .Site.Data.homepage.about.button.URL -}}
{{- $btnIcon = .Site.Data.homepage.about.button.icon -}}
{{- $btnText = i18n "about_button" -}}
{{ end }}
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "about" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section rad-animation-group pb-0">
<div class="rad-fade-down">
<div class="row d-flex flex-column-reverse flex-md-row">
<div class="about__profile-picture col-12 col-md-6">
{{ partial "lazypicture" (dict "src" $imgSrc "width" $imgWidth "height" $imgHeight "scale" $imgScale "class" "image-left-overflow")}}
</div>
<div class="col-12 col-md-6{{ if eq $vAlign "center" }} my-auto{{ else if eq $vAlign "top" }} align-self-start{{ else if eq $vAlign "bottom" }} align-self-end{{ end }}{{ if eq $hAlign "center" }} text-center{{ else if eq $hAlign "right" }} text-end{{ end }}">
<h1>{{ $title }}</h1>
<div class="about-me content lead">
{{ $content }}
</div>
{{ if $btnText }}
<a href="{{ $btnURL | absURL }}" target="_blank" class="btn btn-primary">
<i class="{{ $btnIcon }}"></i>
{{ $btnText }}
</a>
{{ end }}
</div>
</div>
</div>
</section>
@@ -0,0 +1,43 @@
<!-- Optimized lazy loading initialization -->
<script>
window.addEventListener("load", function() {
if (typeof lozad !== 'undefined') {
try {
var observer = window.lozad(".lozad", {
rootMargin: window.innerHeight / 2 + "px 0px",
threshold: 0.01,
loaded: function(el) {
el.setAttribute('data-loaded', 'true');
}
});
observer.observe();
} catch(e) {
console.error('Lozad initialization error:', e);
}
}
});
</script>
<!-- Non-critical scripts loaded with defer for better performance -->
<script defer src='{{ "js/rad-animations.js" | absURL }}'></script>
<script defer src='{{ "js/library/smooth-scroll.polyfills.min.js" | absURL }}'></script>
<script defer src='{{ "js/sticky-header.js" | absURL }}'></script>
<script defer src='{{ "js/smooth-scroll-init.js" | absURL }}'></script>
{{- $bootstrapJs := resources.Get "js/vendor/bootstrap.bundle.min.js" | fingerprint | resources.Copy "/assets/js/vendor/bootstrap.bundle.min.js" }}
<script defer src="{{ $bootstrapJs.RelPermalink }}"></script>
<!-- vercel insights -->
{{- $vercelPageInsights := .Site.Params.analytics.vercelPageInsights }}
{{- $vercelAnalytics := .Site.Params.analytics.vercelAnalytics }}
<script>
window.si = window.si || function () { (window.siq = window.siq || []).push(arguments); };
</script>
{{- if $vercelPageInsights }}
<script defer src="/_vercel/speed-insights/script.js"></script>
{{- end }}
{{- if $vercelAnalytics }}
<script defer src="/_vercel/insights/script.js"></script>
{{- end }}
@@ -0,0 +1,30 @@
<aside class="blog-sidebar">
{{ if .Site.Params.blog.showCategories }}
<div class="sidebar-section categories">
<h3>{{ i18n "categories" | default "Categories" }}</h3>
{{ if .Site.Taxonomies.tags }}
<ul class="tags">
{{ range $name, $taxonomy := .Site.Taxonomies.tags }}
<li>
<a href="{{ "/tags/" | relLangURL }}{{ $name | urlize }}">{{ $name }}</a>
</li>
{{ end }}
</ul>
{{ end }}
</div>
{{ end }}
{{ if .Site.Params.blog.showRecentPosts }}
<div class="sidebar-section recent-posts">
<h3>{{ i18n "recent_posts" | default "Recent Posts" }}</h3>
<ul>
{{ range first .Site.Params.blog.recentPostCount (where .Site.RegularPages "Type" "blog") }}
<li>
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
<span class="post-date">{{ .Date.Format "Jan 2, 2006" }}</span>
</li>
{{ end }}
</ul>
</div>
{{ end }}
</aside>
@@ -0,0 +1,78 @@
<section id="breadcrumb-bar" class="breadcrumb-bar container">
<nav aria-label="breadcrumb" class="d-print-none">
<ol class="breadcrumbs">
<li class="breadcrumb-item">
<a href="{{ relURL "" }}" class="breadcrumb-link">
<span class="breadcrumb-icon" aria-hidden="true">🏠</span>
<span class="breadcrumb-text">Home</span>
</a>
</li>
{{- $.Scratch.Set "url" "" -}}
{{- $taxonomy := .Data.Plural -}}
{{- range $index, $element := (split (trim .RelPermalink "/") "/") -}}
{{- $.Scratch.Add "url" (print "/" . ) -}}
{{- if eq $index 0 -}}
{{- if eq . "tags" -}}
<li class="breadcrumb-item">
<a href="{{ $.Scratch.Get `url` }}" class="breadcrumb-link">
<span class="breadcrumb-text">Tags</span>
</a>
</li>
{{- else if eq . "categories" -}}
<li class="breadcrumb-item">
<a href="{{ $.Scratch.Get `url` }}" class="breadcrumb-link">
<span class="breadcrumb-text">Categories</span>
</a>
</li>
{{- else -}}
{{- $section := $.Site.GetPage "section" . -}}
{{- if $section -}}
<li class="breadcrumb-item">
<a href="{{ $.Scratch.Get `url` }}" class="breadcrumb-link">
<span class="breadcrumb-text">{{ $section.Title }}</span>
</a>
</li>
{{- else -}}
<li class="breadcrumb-item">
<a href="{{ $.Scratch.Get `url` }}" class="breadcrumb-link">
<span class="breadcrumb-text">{{ humanize . }}</span>
</a>
</li>
{{- end -}}
{{- end -}}
{{- else -}}
{{- if eq $taxonomy "tags" -}}
<li class="breadcrumb-item active" aria-current="page">
<span class="breadcrumb-text">{{ humanize . }}</span>
</li>
{{- else if eq $taxonomy "categories" -}}
<li class="breadcrumb-item active" aria-current="page">
<span class="breadcrumb-text">{{ humanize . }}</span>
</li>
{{- else -}}
{{- $currentPage := $.Site.GetPage ($.Scratch.Get "url") -}}
{{- if $currentPage -}}
{{- if $currentPage.IsPage -}}
<li class="breadcrumb-item active" aria-current="page">
<span class="breadcrumb-text">{{ $currentPage.Title }}</span>
</li>
{{- else -}}
<li class="breadcrumb-item">
<a href="{{ $.Scratch.Get `url` }}" class="breadcrumb-link">
<span class="breadcrumb-text">{{ $currentPage.Title }}</span>
</a>
</li>
{{- end -}}
{{- else -}}
<li class="breadcrumb-item">
<a href="{{ $.Scratch.Get `url` }}" class="breadcrumb-link">
<span class="breadcrumb-text">{{ humanize . }}</span>
</a>
</li>
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
</ol>
</nav>
</section>
@@ -0,0 +1,102 @@
{{/* Used for the Client&Works section in the homepage */}}
{{/* If some content is missing/not displayed, check the images for the client/work */}}
{{- $contextType := printf "%T" . -}}
{{- $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") -}}
{{/* ---------------------------------------------------------------------------
SECTION TITLE
--------------------------------------------------------------------------- */}}
{{- $sectionTitle := "" -}}
{{- if $isShortcode -}}
{{- $sectionTitle = .Get "title" -}}
{{- else -}}
{{- $sectionTitle = i18n "client_work_title" -}}
{{- end -}}
{{/* ---------------------------------------------------------------------------
CLIENTS
--------------------------------------------------------------------------- */}}
{{- $clients := slice -}}
{{- if not $isShortcode -}}
{{- $baseLangSite := .Sites.Default -}}
{{- $clients = (where .Site.RegularPages.ByDate.Reverse "Type" "client-work" | lang.Merge (where $baseLangSite.RegularPages.ByDate.Reverse "Type" "client-work") ) -}}
{{- else -}}
{{- $clients = (where .Site.RegularPages.ByDate.Reverse "Type" "client-work") -}}
{{- end -}}
{{/* ---------------------------------------------------------------------------
PROJECTS
--------------------------------------------------------------------------- */}}
{{- $projects := (where .Site.RegularPages.ByDate.Reverse "Type" "projects") -}}
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "client-and-work-section" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section section--border-bottom">
<div class="client-works-container">
<h2 class="rad-animation-group rad-fade-down">
{{ $sectionTitle }}
</h2>
<div class="row row--padded rad-animation-group rad-fade-down">
<div class="col-12">
<div class="clients">
{{ range $clients }}
<div class="clients__item">
<a href="{{ .Params.link }}" aria-label="Link to the client site for {{ .Params.title }} (opens in a new window)" target="_blank">
{{ partial "lazypicture" (dict "src" .Params.logo.src "scale" .Params.logo.scale "class" "portfolio-project img-responsive")}}
</a>
</div>
{{ end }}
</div>
</div>
</div>
{{/* Projects */}}
{{ range $index, $element := $projects }}
{{ $is_even := eq (mod $index 2) 0 }}
{{ with $element }}
<div
class="row row--padded rad-animation-group rad-fade-down
{{ if $is_even }}flex-column-reverse flex-md-row even-row{{ else }}uneven-row{{ end }}"
>
{{ if $is_even }}
<div class="col-12 col-md-5 mt-4 mt-md-0 my-md-auto even">
<h3>{{ .Params.title }}</h3>
<div class="lead">
{{ .Page.Content }}
</div>
<a href="{{ .Params.button.URL | absURL }}" class="btn btn-primary"
>{{ .Params.button.btnText }}<i class="{{ .Params.button.icon }}"></i
></a>
</div>
<div class="col-12 col-md-7 pl-md-0 text-right">
{{ partial "lazypicture" (dict "src" .Params.image.src "scale" .Params.image.scale "class" "picture-works even")}}
</div>
{{ else }}
<div class="col-12 col-md-7 pl-md-0 text-right not-even">
{{ partial "lazypicture" (dict "src" .Params.image.src "scale" .Params.image.scale "class" "picture-works odd")}}
</div>
<div class="col-12 col-md-5 mt-4 mt-md-0 my-md-auto">
<h3>{{ .Params.title }}</h3>
<div class="lead">
{{ .Page.Content }}
</div>
<a href="{{ .Params.button.URL | absURL }}" class="btn btn-primary"
>{{ .Params.button.btnText }}<i class="{{ .Params.button.icon }}"></i
></a>
</div>
{{ end }}
</div>
{{ end }}
{{ end }}
</div>
</section>
@@ -0,0 +1,45 @@
{{ if .Site.Params.comments.enabled }}
<aside class="comments-section light-border-top">
<h3>{{ i18n "comments" | default "Comments" }}</h3>
{{ if eq .Site.Params.comments.provider "disqus" }}
{{ if .Site.DisqusShortname }}
{{ template "_internal/disqus.html" . }}
{{ end }}
{{ end }}
{{ if eq .Site.Params.comments.provider "giscus" }}
{{ with .Site.Params.comments.giscus }}
<script src="https://giscus.app/client.js"
data-repo="{{ .repo }}"
data-repo-id="{{ .repoId }}"
data-category="{{ .category }}"
data-category-id="{{ .categoryId }}"
data-mapping="{{ .mapping | default "pathname" }}"
data-strict="{{ .strict | default "0" }}"
data-reactions-enabled="{{ .reactionsEnabled | default "1" }}"
data-emit-metadata="{{ .emitMetadata | default "0" }}"
data-input-position="{{ .inputPosition | default "bottom" }}"
data-theme="{{ .theme | default "preferred_color_scheme" }}"
data-lang="{{ .lang | default "en" }}"
data-loading="{{ .loading | default "lazy" }}"
crossorigin="anonymous"
async>
</script>
{{ end }}
{{ end }}
{{ if eq .Site.Params.comments.provider "utterances" }}
{{ with .Site.Params.comments.utterances }}
<script src="https://utteranc.es/client.js"
repo="{{ .repo }}"
issue-term="{{ .issueTerm | default "pathname" }}"
label="{{ .label }}"
theme="{{ .theme | default "preferred-color-scheme" }}"
crossorigin="anonymous"
async>
</script>
{{ end }}
{{ end }}
</aside>
{{ end }}
@@ -0,0 +1,193 @@
{{/*
contact.html, used via {{ partial "contact.html" . }}
from contact-section.html
Arguments:
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{- $contextType := printf "%T" . -}}
{{- $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") -}}
{{ $sectionId := "contact" }}
{{ if $isShortcode }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
{{ end }}
{{/*----------------------------------------------
TITLE
------------------------------------------------*/}}
{{ $title := "" }}
{{ if $isShortcode }}
{{ $title = .Get "title" | default (i18n "contact_title") }}
{{ else }}
{{ $title = i18n "contact_title" }}
{{ end }}
{{/*----------------------------------------------
FORM CONFIGURATION
------------------------------------------------*/}}
{{ $form_action := "" }}
{{ $form_method := "" }}
{{ if $isShortcode }}
{{ $form_action = .Get "form_action" | default .Site.Data.homepage.contact.form_action }}
{{ $form_method = .Get "form_method" | default .Site.Data.homepage.contact.form_method }}
{{ else }}
{{ $form_action = .Site.Data.homepage.contact.form_action }}
{{ $form_method = .Site.Data.homepage.contact.form_method }}
{{ end }}
{{/*----------------------------------------------
FORM FIELD PLACEHOLDERS
------------------------------------------------*/}}
{{ $name_placeholder := "" }}
{{ if $isShortcode }}
{{ $name_placeholder = .Get "contact_form_name" | default (.Get "name_placeholder") | default .Site.Data.homepage.contact.form_name_placeholder | default (i18n "contact_name_placeholder") }}
{{ else }}
{{ $name_placeholder = .Site.Data.homepage.contact.form_name_placeholder | default (i18n "contact_name_placeholder") }}
{{ end }}
{{ $name_placeholder_attr := "" }}
{{ if $name_placeholder }}
{{ $name_placeholder_attr = printf "placeholder=%q" $name_placeholder }}
{{ end }}
{{ $email_placeholder := "" }}
{{ if $isShortcode }}
{{ $email_placeholder = .Get "contact_form_email" | default (.Get "email_placeholder") | default .Site.Data.homepage.contact.form_email_placeholder | default (i18n "contact_email_placeholder") }}
{{ else }}
{{ $email_placeholder = .Site.Data.homepage.contact.form_email_placeholder | default (i18n "contact_email_placeholder") }}
{{ end }}
{{ $email_placeholder_attr := "" }}
{{ if $email_placeholder }}
{{ $email_placeholder_attr = printf "placeholder=%q" $email_placeholder }}
{{ end }}
{{ $phone_placeholder := "" }}
{{ if $isShortcode }}
{{ $phone_placeholder = .Get "contact_form_phone" | default (.Get "phone_placeholder") | default .Site.Data.homepage.contact.form_phone_placeholder | default (i18n "contact_phone_placeholder") }}
{{ else }}
{{ $phone_placeholder = .Site.Data.homepage.contact.form_phone_placeholder | default (i18n "contact_phone_placeholder") }}
{{ end }}
{{ $phone_placeholder_attr := "" }}
{{ if $phone_placeholder }}
{{ $phone_placeholder_attr = printf "placeholder=%q" $phone_placeholder }}
{{ end }}
{{ $message_placeholder := "" }}
{{ if $isShortcode }}
{{ $message_placeholder = .Get "contact_form_message" | default (.Get "message_placeholder") | default .Site.Data.homepage.contact.form_message_placeholder | default (i18n "contact_message_placeholder") }}
{{ else }}
{{ $message_placeholder = .Site.Data.homepage.contact.form_message_placeholder | default (i18n "contact_message_placeholder") }}
{{ end }}
{{ $message_placeholder_attr := "" }}
{{ if $message_placeholder }}
{{ $message_placeholder_attr = printf "placeholder=%q" $message_placeholder }}
{{ end }}
{{/*----------------------------------------------
TEXTAREA ROWS
------------------------------------------------*/}}
{{ $message_rows := 2 }}
{{ if $isShortcode }}
{{ $message_rows = .Get "contact_form_rows" | default (.Get "message_rows") | default 2 }}
{{ end }}
{{/*----------------------------------------------
BUTTON TEXT
------------------------------------------------*/}}
{{ $button_text := "" }}
{{ if $isShortcode }}
{{ $button_text = .Get "contact_button" | default (.Get "button_text") | default .Site.Data.homepage.contact.button_text | default (i18n "contact_button_text") }}
{{ else }}
{{ $button_text = .Site.Data.homepage.contact.button_text | default (i18n "contact_button_text") }}
{{ end }}
{{/*----------------------------------------------
CONTACT INFORMATION FIELDS
------------------------------------------------*/}}
{{ $phone := "" }}
{{ $phone_display := "" }}
{{ $email := "" }}
{{ $location := "" }}
{{ if $isShortcode }}
{{ $phone = .Get "contact_phone_number" | default (.Get "phone") | default .Site.Data.homepage.contact.phone }}
{{ $phone_display = .Get "contact_phone_number" | default (.Get "phone_display") | default .Site.Data.homepage.contact.phone_display | default $phone }}
{{ $email = .Get "contact_email_email" | default (.Get "email") | default .Site.Data.homepage.contact.email }}
{{ $location = .Get "contact_address_address" | default (.Get "location") | default .Site.Data.homepage.contact.location }}
{{ else }}
{{ $phone = .Site.Data.homepage.contact.phone }}
{{ $phone_display = .Site.Data.homepage.contact.phone_display | default $phone }}
{{ $email = .Site.Data.homepage.contact.email }}
{{ $location = .Site.Data.homepage.contact.location }}
{{ end }}
{{/*----------------------------------------------
HEADING LABELS
------------------------------------------------*/}}
{{ $phone_heading := "" }}
{{ $email_heading := "" }}
{{ $location_heading := "" }}
{{ if $isShortcode }}
{{ $phone_heading = .Get "contact_phone_title" | default (.Get "phone_heading") | default .Site.Data.homepage.contact.phone_heading | default (i18n "contact_phone_heading") }}
{{ $email_heading = .Get "contact_email_title" | default (.Get "email_heading") | default .Site.Data.homepage.contact.email_heading | default (i18n "contact_email_heading") }}
{{ $location_heading = .Get "contact_address_title" | default (.Get "location_heading") | default .Site.Data.homepage.contact.location_heading | default (i18n "contact_location_heading") }}
{{ else }}
{{ $phone_heading = .Site.Data.homepage.contact.phone_heading | default (i18n "contact_phone_heading") }}
{{ $email_heading = .Site.Data.homepage.contact.email_heading | default (i18n "contact_email_heading") }}
{{ $location_heading = .Site.Data.homepage.contact.location_heading | default (i18n "contact_location_heading") }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section section--contact pt-0">
<div class="container">
<div class="contact w-100">
<h2>{{ $title }}</h2>
<div class="row pt-2">
<div class="col-12 col-lg-7">
<form action="{{ $form_action }}" method="{{ $form_method }}" class="contact__form">
<div class="row">
<div class="col-12 col-sm-6">
<input type="text" name="full_name" class="form-control" {{ $name_placeholder_attr | safeHTMLAttr }}>
</div>
<div class="col-12 col-sm-6">
<input type="email" name="email" class="form-control" {{ $email_placeholder_attr | safeHTMLAttr }}>
</div>
</div>
<div class="row pt-4">
<div class="col-12">
<input type="tel" name="phone" class="form-control" {{ $phone_placeholder_attr | safeHTMLAttr }}>
</div>
</div>
<div class="row pt-4">
<div class="col-12">
<textarea name="message" class="form-control" rows="{{ $message_rows }}" {{ $message_placeholder_attr | safeHTMLAttr }}></textarea>
</div>
</div>
<div class="row pt-4">
<div class="col-12">
<button type="submit" class="btn btn-primary">{{ $button_text }}</button>
</div>
</div>
</form>
</div>
<div class="col-12 col-lg-5 contact__info">
{{ if $phone }}
<h3>{{ $phone_heading }}</h3>
<span>{{ $phone | safeHTML }}</span>
{{ end }}
{{ if $email }}
<h3>{{ $email_heading }}</h3>
<span>{{ $email | safeHTML }}</span>
{{ end }}
{{ if $location }}
<h3>{{ $location_heading }}</h3>
<span>{{ $location | safeHTML }}</span>
{{ end }}
</div>
</div>
</div>
</div>
</section>
@@ -0,0 +1,42 @@
{{- $contextType := printf "%T" . -}}
{{- $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") -}}
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "education" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
{{- /* Title */}}
{{- $title := "" -}}
{{- if $isShortcode }}
{{- $title = .Get "title" | default ( i18n "education_title" ) -}}
{{ else }}
{{- $title = i18n "education_title" -}}
{{ end }}
<section
id="{{ $sectionId }}"
class="section section--border-bottom rad-animation-group"
>
<div class="container-education">
<div class="row rad-fade-down">
<div class="col-12">
<h2>{{ $title }}</h2>
<div class="row pt-2 pt-md-4">
{{ range where .Site.RegularPages "Type" "education" }}
<div class="col-12 col-sm-6 mb-4 mb-sm-0">
<div class="education">
<div class="education__date">{{ .Params.year }}</div>
<div class="education__title">{{ .Params.university }}</div>
<div class="education__degree">{{ .Params.degree }}</div>
</div>
</div>
{{ end }}
</div>
</div>
</div>
</div>
</section>
@@ -0,0 +1,178 @@
{{/*This partial is used from
- layouts/shortcodes/experience.html, anywhere via shortcode (commonly in homepage)
- layouts/experience/list.html, in "/experience" page(s))
*/}}
{{- $contextType := printf "%T" . -}}
{{- $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") -}}
{{/* ---------------------------------------------------------------------------
INTRO TITLE / DESCRIPTION
--------------------------------------------------------------------------- */}}
{{- /* Intro title/description */}}
{{- $introTitle := "" -}}
{{- $introDescription := "" -}}
{{- if $isShortcode }}
{{/* Shortcode params */}}
{{- $introTitle = .Get "intro_title" | default false -}}
{{- $introDescription = .Get "intro_description" | default ( i18n "experience_description" ) | safeHTML -}}
{{ else }}
{{/* Fallback to the content of the markdown in /experience/_index.md */}}
{{/* Base fields from content */}}
{{- $introTitle = .Title -}}
{{- $introDescription = .Content | safeHTML -}}
{{ end }}
{{/* ---------------------------------------------------------------------------
BUTTON #1
--------------------------------------------------------------------------- */}}
{{- /* Button #1 */}}
{{- $btn1Enable := false -}}
{{- $btn1Icon := "" -}}
{{- $btn1URL := "" -}}
{{- $btn1Text := "" -}}
{{- if $isShortcode }}
{{- $btn1Enable = true -}}
{{- $btn1Icon = .Get "button1_icon" | default .Site.Data.homepage.experience.button.icon -}}
{{- $btn1URL = .Get "button1_url" | default ( i18n "experience_button_url" ) -}}
{{- $btn1Text = .Get "button1_text" | default ( i18n "experience_button" ) -}}
{{ else }}
{{- $btn1Enable = .Site.Data.homepage.experience.button.enable -}}
{{- $btn1Icon = .Site.Data.homepage.experience.button.icon -}}
{{- $btn1URL = i18n "experience_button_url" -}}
{{- $btn1Text = i18n "experience_button" -}}
{{ end }}
{{/* ---------------------------------------------------------------------------
BUTTON #2
--------------------------------------------------------------------------- */}}
{{- /* Button #2 */}}
{{- $btn2Enable := false -}}
{{- $btn2Icon := "" -}}
{{- $btn2URL := "" -}}
{{- $btn2Text := "" -}}
{{- if $isShortcode }}
{{- $btn2Enable = true -}}
{{- $hideViewAll := .Get "hideViewAll" -}}
{{- if eq $hideViewAll "true" -}}
{{- $btn2Enable = false -}}
{{- end -}}
{{- $btn2Icon = .Get "button2_icon" | default .Site.Data.homepage.experience.button2.icon -}}
{{- $btn2URL = .Get "button2_url" | default ( i18n "experience_button2_url" ) -}}
{{- $btn2Text = .Get "button2_text" | default ( i18n "experience_button2" ) -}}
{{ else }}
{{- $btn2Enable = .Site.Data.homepage.experience.button2.enable -}}
{{- $btn2Icon = .Site.Data.homepage.experience.button2.icon -}}
{{- $btn2URL = i18n "experience_button2_url" -}}
{{- $btn2Text = i18n "experience_button2" -}}
{{ end }}
{{/* ---------------------------------------------------------------------------
BUTTON #3
--------------------------------------------------------------------------- */}}
{{- /* Button #3 */}}
{{- $btn3Enable := false -}}
{{- $btn3Icon := "" -}}
{{- $btn3URL := "" -}}
{{- $btn3Text := "" -}}
{{- if $isShortcode }}
{{- $btn3Enable = true -}}
{{- $hideViewAll := .Get "hideViewAll" -}}
{{- if eq $hideViewAll "true" -}}
{{- $btn3Enable = false -}}
{{- end -}}
{{- $btn3Icon = .Get "button3_icon" | default .Site.Data.homepage.experience.button3.icon -}}
{{- $btn3URL = .Get "button3_url" | default ( i18n "experience_button3_url" ) -}}
{{- $btn3Text = .Get "button3_text" | default ( i18n "experience_button3" ) -}}
{{ else }}
{{- $btn3Enable = .Site.Data.homepage.experience.button3.enable -}}
{{- $btn3Icon = .Site.Data.homepage.experience.button3.icon -}}
{{- $btn3URL = i18n "experience_button3_url" -}}
{{- $btn3Text = i18n "experience_button3" -}}
{{ end }}
{{/* Fields from front matter */}}
{{- with .Params.button1_icon }}
{{- $btn1Icon = . -}}
{{ end }}
{{- with .Params.button1_url }}
{{- $btn1URL = . -}}
{{ end }}
{{- with .Params.button1_text }}
{{- $btn1Enable = true -}}
{{- $btn1Text = . -}}
{{ end }}
{{- with .Params.button2_icon }}
{{- $btn2Icon = . -}}
{{ end }}
{{- with .Params.button2_url }}
{{- $btn2URL = . -}}
{{ end }}
{{- with .Params.button2_text }}
{{- $btn2Enable = true -}}
{{- $btn2Text = . -}}
{{ end }}
{{- with .Params.button3_icon }}
{{- $btn3Icon = . -}}
{{ end }}
{{- with .Params.button3_url }}
{{- $btn3URL = . -}}
{{ end }}
{{- with .Params.button3_text }}
{{- $btn3Enable = true -}}
{{- $btn3Text = . -}}
{{ end }}
<div class="container-experience">
<div class="row">
<h2>{{ $introTitle }}</h2>
<div class="lead">{{ $introDescription }}</div>
</div>
<div class="row">
{{ if $btn1Enable }}
<div class="col-12 col-lg-4">
<a
href='{{ $btn1URL | absURL }}'
class="btn btn-primary btn-block w-100"
target="_blank"
rel="noopener noreferrer"
>
{{ if $btn1Icon }}<i class="{{ $btn1Icon }}"></i>{{ end }}
{{ $btn1Text }}
<i class="icon-arrow-right"></i>
</a>
</div>
{{ end }}
{{ if $btn2Enable }}
<div class="col-12 col-lg-4">
<a
href='{{ $btn2URL | absURL }}'
class="btn btn-frameless w-100"
target="_blank"
rel="noopener noreferrer"
>
{{ if $btn2Icon }}<i class="{{ $btn2Icon }}"></i>{{ end }}
{{ $btn2Text }}
</a>
</div>
{{ end }}
{{ if $btn3Enable }}
<div class="col-12 col-lg-4">
<a
href='{{ $btn3URL | absURL }}'
class="btn btn-frameless w-100"
rel="noopener noreferrer"
>
{{ if $btn3Icon }}<i class="{{ $btn3Icon }}"></i>{{ end }}
{{ $btn3Text }}
</a>
</div>
{{ end }}
</div>
</div>
@@ -0,0 +1,92 @@
{{ $contextType := printf "%T" . }}
{{ $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") }}
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used.
hideViewAll: Optional argument to hide the "View All" button. Set to "true" to hide the button. */}}
{{ $sectionId := "experience-single" }}
{{ $showViewAll := true }}
{{ if $isShortcode }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
{{ $hideViewAllParam := .Get "hideViewAll" }}
{{ if eq $hideViewAllParam "true" }}
{{ $showViewAll = false }}
{{ end }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section-experience section section--border-bottom rad-animation-group flex-grow-1">
<div class="row flex-column-reverse flex-md-row rad-fade-down">
<div class="experience-list col-12 col-md-6">
<h2>
{{ if $isShortcode }}
{{ .Get "title" | default "" }}
{{ else }}
{{ i18n "experience_title" }}
{{ end }}
</h2>
{{ $xp := where .Site.RegularPages.ByDate "Type" "experience" }}
{{ if not $isShortcode }}
{{ $baseLangSite := .Sites.Default }}
{{ $xp = $xp | lang.Merge (where $baseLangSite.RegularPages.ByDate.Reverse "Type" "experience") }}
{{ end }}
{{ $xpCount := len $xp }}
{{/* in the homepage we limit to the homepageExperienceCount param (6 by default) in the inner page (experience) we display the all */}}
{{ $totalCount := .Site.Params.homepageExperienceCount }}
{{ if not $isShortcode }}
{{ if not .IsHome }}
{{ $totalCount = $xpCount }}
{{ end }}
{{ end }}
{{ range first $totalCount (sort $xp "Date" "desc") }}
<div class="experience">
<a href="{{ .Permalink | relURL }}" class="experience__link">
<div class="experience__header">
{{ $img := resources.Get .Params.companyLogo }}
{{ with $img }}
{{ $imgWebp := $img.Resize (printf "%dx%d webp q75 Lanczos picture" $img.Width $img.Height) }}
<img
src="{{ $imgWebp.RelPermalink }}"
alt="{{ .Params.company }} logo"
class="experience__company-logo"
loading="lazy"
/>
{{ end }}
<div class="experience__meta">
<div class="experience__date">{{ .Params.duration }}</div>
<div class="experience__title">{{ .Params.jobTitle }}</div>
<div class="experience__company">
{{ .Params.company }}.
<span class="experience__location">{{ .Params.location }}</span>
</div>
</div>
<div class="experience__description d-none d-print-block">
<h1>{{ .Params.title }}</h1>
{{ .Content | safeHTML | transform.Plainify }}
</div>
</div>
</a>
</div>
{{ end }}
{{ if and (gt $xpCount $totalCount) $showViewAll }}
<div class="all-experience-container">
{{ $xpExtra := sub $xpCount $totalCount }}
<em>And {{ $xpExtra }} more</em><br />
<a href="{{ absURL "experience" | relLangURL }}" class="btn btn-primary btn-all-experience">
<i class="{{ .Site.Data.homepage.experience.button3.icon }}"></i>
{{ i18n "experience_button3" }}
</a>
</div>
{{ end }}
</div>
<div class="experience-description col-12 col-md-6">
{{ partial "experience-description.html" . }}
</div>
</div>
</section>
@@ -0,0 +1,56 @@
<footer class="footer w-100 d-print-none">
{{ $footer := where (where .Site.Pages "Type" "footer") "Lang" .Lang }}
{{ range (sort $footer "Date" "desc") }}
{{ if .File }}
{{ warnf "[FOOTER] Path: %s | Lang: %s | IsDraft: %t | Type: %s | Section: %s | Kind: %s" .File.Path .Lang .Draft .Type .Section .Kind }}
{{ end }}
{{ .Content | safeHTML }}
{{ end }}
<div class="container items">
<div class="container">
<div class="row w-100 align-items-center">
<div class="footer_left col-12 col-lg-4 mb-3 mb-lg-0 text-center text-lg-start">
<div class="footer__copy">
<span>{{ i18n "footer_notice" | safeHTML }}</span>
</div>
</div>
<div class="footer_links col-12 col-lg-6 mb-3 mb-lg-0 text-center text-lg-start">
<ul class="navbar-nav w-100 align-items-center justify-content-center justify-content-lg-start d-flex flex-wrap gap-2">
{{ range .Site.Menus.footer }}
<li class="nav-item">
<a class="nav-link" href="{{ .URL | relURL }}"
>{{ if .Pre }}
<i class="icon-{{ .Pre }}" aria-label="{{ or .Name .Pre }}"></i>
{{ else }}
{{ .Name | upper }}
{{ end }}</a
>
</li>
{{ end }}
</ul>
</div>
<div class="footer_right col-12 col-lg-2 mb-3 mb-lg-0 text-center text-lg-end">
<div class="d-flex flex-column flex-lg-row justify-content-center align-items-center gap-2 d-grid col-12 ">
{{- if hugo.IsMultilingual }}
{{- if not .Site.Params.languages.selector.disable.footer }}
{{ .Scratch.Set "selectorPlacement" "footer" }}
{{ .Scratch.Set "dropdownDirection" "up" }}
{{ partial "selector-language.html" . }}
{{- end }}
{{- end }}
{{- if not .Site.Params.colorTheme.selector.disable.footer }}
{{ .Scratch.Set "selectorPlacement" "footer" }}
{{ .Scratch.Set "dropdownDirection" "up" }}
{{ partial "selector-theme.html" . }}
{{- end }}
</div>
</div>
</div>
</div>
</div>
</footer>
+141
View File
@@ -0,0 +1,141 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="theme-color" content="#478079" />
{{- if .Site.Params.analytics.googleTagManager.enabled }}
<link rel="preconnect" href="https://www.googletagmanager.com" />
{{- end }}
{{- if .Site.Params.analytics.googleAnalytics.enabled }}
{{- if .Site.Params.analytics.googleAnalytics.code }}
<!-- Google tag (gtag.js) - moved to bottom for non-blocking -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ .Site.Params.analytics.googleAnalytics.code}}');
</script>
<script
async
src="https://www.googletagmanager.com/gtag/js?id={{ .Site.Params.analytics.googleAnalytics.code }}"></script>
{{- end }}
{{- end }}
<title>
{{ if .IsHome }}
{{ else }}
{{ if .Title }}{{ .Title }} |{{ end }}
{{ end }}
{{ i18n "head_title" }}
</title>
<meta name="description" content="{{ i18n "head_description" }}" />
<meta name="generator-mode" content="{{ hugo.Environment }}" />
{{- $critical := resources.Get "css/critical.css" | resources.Minify }}
<style data-generator="critical-css">
{{- $critical.Content | safeCSS }}
</style>
{{- $cssResources := slice }}
{{- range .Site.Params.plugins.css }}
{{- if findRE "^http" .URL }}
<link rel="stylesheet" href="{{ .URL | absURL }}" />
{{- else }}
{{- with resources.Get .URL }}
{{- $cssResources = $cssResources | append . }}
{{- end }}
{{- end }}
{{- end }}
{{- if gt (len $cssResources) 0 }}
{{- $cssBundle := $cssResources | resources.Concat "css/bundle.css" }}
{{- $css := $cssBundle }}
{{- if hugo.IsProduction }}
{{- $css = $css | minify | fingerprint | resources.PostProcess }}
{{- end }}
<link
rel="preload"
href="{{ $css.RelPermalink }}"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
{{ if hugo.IsProduction }}
integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous"
{{ end }} />
<noscript>
<link
rel="stylesheet"
href="{{ $css.RelPermalink }}"
{{ if hugo.IsProduction }}
integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous"
{{ end }} />
</noscript>
{{- end }}
{{- range .Site.Params.plugins.scss }}
{{/* no external scss processing - as they need to be processed by the theme */}}
{{- $scss := resources.Get .URL }}
{{- $style := false }}
{{- if $scss }}
{{- $style = $scss | css.Sass }}
{{- else }}
{{- warnf "SCSS file not found: %s" .URL }}
{{- end }}
{{- if hugo.IsProduction }}
{{- $style = $scss | css.Sass | resources.Minify | resources.Fingerprint }}
{{- end }}
{{- if $style }}
<link
rel="stylesheet"
href="{{ $style.Permalink }}"
integrity="{{ $style.Data.Integrity }}"
crossorigin="anonymous" />
{{- end }}
{{- end }}
<!-- printed only it not disabled -->
{{- if not .Site.Params.colorTheme.auto.disable }}
{{/* Inline script to prevent theme flash */}}
<script>
// Simple script to set initial theme to prevent flash
(function() {
const storedTheme = localStorage.getItem('theme');
if (storedTheme) {
if (storedTheme === 'auto') {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.setAttribute('data-bs-theme', isDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme-auto', 'true');
} else {
document.documentElement.setAttribute('data-bs-theme', storedTheme);
}
} else {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.setAttribute('data-bs-theme', isDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme-auto', 'true');
}
})();
</script>
{{- $colorModesScript := resources.Get "js/color-modes.js" }}
{{- if hugo.IsProduction }}
{{- $colorModesScript = $colorModesScript | resources.Minify | resources.Fingerprint }}
{{- end }}
<script defer src="{{ $colorModesScript.Permalink }}"></script>
{{- else }}
<!-- disabled color theme selector -->
{{- end }}
{{- if .Site.Params.analytics.google_tag_manager.enabled }}
<!-- Google tag (gtag.js), google analytics -->
<script
defer
src="https://www.googletagmanager.com/gtag/js?id={{ .Site.Params.analytics.google_tag_manager.code }}"></script>
{{- $analytics := resources.Get "js/gtag.js" | resources.Minify }}
<script defer src="{{ $analytics.Permalink }}"></script>
{{- else }}
<!-- no google tag displayed -->
{{- end }}
<!-- Preload lozad for faster image loading -->
<link rel="preload" href="{{ "js/library/lozad.min.js" | absURL }}" as="script">
<script async src="{{ "js/library/lozad.min.js" | absURL }}"></script>
{{ template "_internal/opengraph.html" . }}
@@ -0,0 +1 @@
@@ -0,0 +1,83 @@
<!-- if you want to enable google tag manager you can check in your theme toml -->
{{ if .Site.Params.analytics.google_tag_manager.enabled }}
<!-- Google Tag Manager (noscript) -->
<noscript
><iframe
src="https://www.googletagmanager.com/ns.html?id={{ .Site.Params.analytics.google_tag_manager.id }}"
height="0"
width="0"
style="display: none; visibility: hidden"
></iframe
></noscript>
<!-- End Google Tag Manager (noscript) -->
{{ end }}
{{ partial "skip-to-content.html" }}
<header class="header fixed-top rad-animation-group" id="header">
<div class="container rad-fade-in">
<nav class="navbar bd-navbar navbar-expand-lg navbar-light p-0">
<div class="container-fluid">
<a class="navbar-brand mx-auto" href="{{ .Site.BaseURL | relLangURL }}">
{{ if .Site.Params.logo }}
<img
src="{{ .Site.Params.logo | absURL }}"
alt="{{ i18n "logo_alt" }}"
class="logo"
/>
{{ end }}
<span>{{ i18n "logo_text1" }}</span>
<span>{{ i18n "logo_text2" }}</span>
</a>
<button
class="navbar-toggler collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent, #header"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label='{{ i18n "toggle_navigation" }}'
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-lg-auto">
{{- range .Site.Menus.header }}
<li class="nav-item">
<a data-scroll class="nav-link" href="{{ .URL | relURL }}"
>{{ if .Pre }}
<i class="icon-{{ .Pre }}" aria-label="{{ or .Name .Pre }}"></i>
{{ else }}
{{ .Name | upper }}
{{ end }}</a
>
</li>
{{- end }}
{{- if hugo.IsMultilingual }}
{{- if not .Site.Params.languages.selector.disable.header }}
{{ .Scratch.Set "selectorPlacement" "header" }}
{{ .Scratch.Set "dropdownDirection" "down" }}
<li class="dropdown language-selector nav-item">
{{ partial "selector-language.html" . }}
</li>
{{- end }}
{{- end }}
{{- if not .Site.Params.colorTheme.selector.disable.header }}
<li class="dropdown theme-selector nav-item">
{{ .Scratch.Set "selectorPlacement" "header" }}
{{ .Scratch.Set "dropdownDirection" "down" }}
{{ partial "selector-theme.html" . }}
</li>
{{- end }}
</ul>
</div>
</div>
</nav>
</div>
</header>
{{- if not .IsHome }}
{{ partial "breadcrumb.html" . }}
{{- end }}
@@ -0,0 +1,73 @@
{{/*.src is the image path*/}}
{{/*.height is used for resizing*/}}
{{/*.width is used for resizing*/}}
{{/*.scale is used for resizing*/}}
{{/*.alt alternate text*/}}
{{/*.class is added to the image*/}}
{{/*.pictureclass is added to the picture*/}}
{{ $img := resources.Get .src }}
{{ if $img }}
{{- $target1 := "" -}}
{{- $target2 := "" -}}
{{- if (and .width .height) }}
{{/* {{ warnf "lazypicture.html: width and height" }}*/}}
{{ $swidth := int .width }}
{{ $sheight := int .height }}
{{- $target1 = (printf "%dx%d" $swidth $sheight) -}}
{{- $target2 = (printf "%dx%d" (mul 2 $swidth) (mul 2 $sheight)) -}}
{{- else if .width }}
{{/* {{ warnf "lazypicture.html: width" }}*/}}
{{ $swidth := int .width }}
{{- $target1 = (printf "%dx" $swidth) -}}
{{- $target2 = (printf "%dx" (mul 2 $swidth)) -}}
{{- else if .height }}
{{/* {{ warnf "lazypicture.html: height" }}*/}}
{{ $sheight := int .height }}
{{- $target1 = (printf "x%d" $sheight) -}}
{{- $target2 = (printf "x%d" (mul 2 $sheight)) -}}
{{- else if .scale }}
{{/* {{ warnf "lazypicture.html: scale" }}*/}}
{{ $swidth := int (mul (float $img.Width) (float .scale) ) }}
{{ $sheight := int (mul (float $img.Height) (float .scale) ) }}
{{- $target1 = (printf "%dx%d" $swidth $sheight) -}}
{{- $target2 = (printf "%dx%d" (mul 2 $swidth) (mul 2 $sheight)) -}}
{{ else }}
{{- $target1 = (printf "%dx%d" $img.Width $img.Height) -}}
{{ end }}
{{/* {{ warnf "lazypicture.html: target1 %s" $target1 }}*/}}
{{ $imgOri := $img.Resize (printf "%s q75 Lanczos picture" $target1) }}
{{ $imgWebp := $img.Resize (printf "%s webp q75 Lanczos picture" $target1) }}
<picture class="{{ .pictureclass }}">
{{- if $target2 }}
{{ $imgOri2 := $img.Resize (printf "%s q75 Lanczos picture" $target2) }}
{{ $imgWebp2 := $img.Resize (printf "%s webp q75 Lanczos picture" $target2) }}
<source srcset="{{ $imgWebp.RelPermalink }} 1x, {{ $imgWebp2.RelPermalink }} 2x" type="image/webp" />
<source srcset="{{ $imgOri.RelPermalink }} 1x, {{ $imgOri2.RelPermalink }} 2x" type="{{ $imgOri.MediaType.Type }}">
{{- else }}
<source srcset="{{ $imgWebp.RelPermalink }} 1x" type="image/webp" />
<source srcset="{{ $imgOri.RelPermalink }} 1x" type="{{ $imgOri.MediaType.Type }}">
{{- end }}
<img
width="{{ $imgOri.Width }}"
height="{{ $imgOri.Height }}"
class="lozad img-responsive {{ .class }}"
data-src="{{ $imgOri.RelPermalink }}"
alt='{{ .alt }}'
src="data:image/gif;base64,R0lGODlhBwACAIAAAP///wAAACH5BAEAAAEALAAAAAAHAAIAAAIDjI9YADs="
loading="lazy"
decoding="async"
/>
</picture>
{{ else }}
{{ warnf "lazypicture.html: Image src was not found: %q" .src }}
{{ end }}
@@ -0,0 +1,88 @@
{{ $contextType := printf "%T" . }}
{{ $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") }}
{{/* ---------------------------------------------------------------------------
NEWSLETTER FORM CONFIGURATION
--------------------------------------------------------------------------- */}}
{{- /* Form action and method */}}
{{- $formAction := "" -}}
{{- $formMethod := "" -}}
{{- if $isShortcode }}
{{- $formAction = .Get "form_action" | default .Site.Data.homepage.newsletter.form.action -}}
{{- $formMethod = .Get "form_method" | default .Site.Data.homepage.newsletter.form.method -}}
{{ else }}
{{- $formAction = .Site.Data.homepage.newsletter.form.action -}}
{{- $formMethod = .Site.Data.homepage.newsletter.form.method -}}
{{ end }}
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "newsletter" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section section--cta">
<div class="container d-flex justify-content-center align-items-center">
<div class="row">
<div class="col-12 text-center">
<h2>
{{ if $isShortcode }}
{{ .Get "newsletter_title" }}
{{ else }}
{{ i18n "newsletter_title" }}
{{ end }}
</h2>
<div class="rad-subscription-group">
<form
id="rad-subscription"
action="{{ $formAction }}"
method="{{ $formMethod }}"
>
<input
id="rad-subscription-email"
type="email"
class="form-control"
aria-describedby="emailHelp"
placeholder='{{ if $isShortcode }} {{ .Get "newsletter_placeholder" }} {{ else }} {{ i18n "newsletter_placeholder" }} {{ end }}'
aria-label='{{ if $isShortcode }} {{ .Get "newsletter_placeholder" }} {{ else }} {{ i18n "newsletter_placeholder" }} {{ end }}'
>
<button type="submit" id="rad-subscription-submit" class="btn btn-light btn-rounded">
{{ if $isShortcode }}
{{ .Get "newsletter_button" }}
{{ else }}
{{ i18n "newsletter_button" }}
{{ end }}
</button>
</form>
<div id="rad-subscription-success" class="d-none">
<p class="lead">
{{ if $isShortcode }}
{{ .Get "newsletter_success_message" }}
{{ else }}
{{ i18n "newsletter_success_message" }}
{{ end }}
</p>
</div>
<div id="rad-subscription-fail" class="d-none">
<p>
{{ if $isShortcode }}
{{ .Get "newsletter_error_message" }}
{{ else }}
{{ i18n "newsletter_error_message" }}
{{ end }}
</p>
</div>
<script src='{{ "js/subscription.js" | absURL }}'></script>
</div>
<small id="emailHelp" class="form-text text-muted">
{{ if $isShortcode }}
{{ .Get "newsletter_note" }}
{{ else }}
{{ i18n "newsletter_note" }}
{{ end }}
</small>
</div>
</div>
</div>
</section>
@@ -0,0 +1,30 @@
{{ $related := .Site.RegularPages.Related . | first 3 }}
{{ with $related }}
<aside class="related-posts light-border-top">
<h3>{{ i18n "related_posts" | default "Related Posts" }}</h3>
<ul class="related-posts-list">
{{ range . }}
<li class="related-post-item">
<a href="{{ .RelPermalink }}">
<h4>{{ .Title }}</h4>
{{ with .Description }}
<p class="related-post-excerpt">{{ . }}</p>
{{ else }}
<p class="related-post-excerpt">{{ .Summary | plainify | truncate 120 }}</p>
{{ end }}
<div class="related-post-meta">
<span class="post-date">{{ .Date.Format "Jan 2, 2006" }}</span>
{{ with .GetTerms "tags" }}
<span class="post-tags">
{{ range first 2 . }}
<span class="tag">{{ .LinkTitle }}</span>
{{ end }}
</span>
{{ end }}
</div>
</a>
</li>
{{ end }}
</ul>
</aside>
{{ end }}
@@ -0,0 +1,29 @@
{{/* indicates where the partial is placed
so far the placement can either be header or footer */}}
{{- $placement := .Scratch.Get "selectorPlacement" }}
{{- $direction := .Scratch.Get "dropdownDirection" }}
<div id='{{ $placement }}-language-selector'
class='d-grid gap-2 col-6 mx-auto nav-link dropdown {{ if (eq $direction "up") }}dropup{{ end }} {{ if eq $placement "mobile-header" }}nav-link{{ end }}'>
{{ range .Site.Languages }}
{{ if eq . $.Site.Language }}
<button class="btn btn-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center show"
id='btn-select-language-{{ $placement }}' type="button" aria-expanded="true"
aria-controls="languages-dropdown-{{ $placement }}" data-bs-toggle="dropdown" data-bs-display="static"
aria-label='{{ i18n "language" }}'>
<span class="label">{{ i18n "language" }}</span>
</button>
<ul class='dropdown-menu dropdown-menu-end {{ if (eq $direction "up") }}dropup{{ end }}'
id="languages-dropdown-{{ $placement }}" data-bs-popper="static">
<li class="dropdown-item current selected">
<span>✔️ {{ .LanguageName }}</span>
</li>
{{ end }}
{{ end }}
{{ range $.Translations }}
<li class="dropdown-item choice">
<a class="dropdown-item translation btn-link d-flex align-items-center show" title="{{ .Language.LanguageName }}"
href="{{ .Permalink }}">{{ .Language.LanguageName }}</a>
</li>
{{ end }}
</ul>
</div>
@@ -0,0 +1,38 @@
{{/* indicates where the partial is placed
so far the placement can either be header or footer */}}
{{- $placement := .Scratch.Get "selectorPlacement" }}
{{- $direction := .Scratch.Get "dropdownDirection" }}
<div id='{{ .Scratch.Get "selectorPlacement" }}-color-selector'
class='d-grid gap-2 col-6 mx-auto nav-link dropdown {{ if eq $direction "up" }}dropup{{ end }} {{ if eq $placement "mobile-header" }}nav-link{{ end }}'>
<button class="btn btn-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center show bd-theme-selector"
id='bd-theme-{{ .Scratch.Get "selectorPlacement" }}' type="button" aria-expanded="true" data-bs-toggle="dropdown"
data-bs-display="static" aria-label='{{ i18n "toggle_theme" }}'>
<span class="theme-icon auto d-none" aria-hidden="true">{{ i18n "theme_auto_short" }}</span>
<span class="current-theme">{{ i18n "theme_auto" }}</span>
<span class="d-lg-none ms-2 visually-hidden bd-theme-text" id="bd-theme-text-{{ $placement }}">{{ i18n
"toggle_theme" }}</span>
</button>
<ul id="theme-dropdown-{{ $placement }}" class="dropdown-menu dropdown-menu-end {{ if eq $direction " up" }}dropup{{
end }}" aria-labelledby="bd-theme-text-{{ $placement }}" data-bs-popper="static">
<li>
<button type="button" class="dropdown-item d-flex align-items-center active" data-bs-theme-value="light"
aria-pressed="true">
{{ i18n "theme_light" }}
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark"
aria-pressed="false">
{{ i18n "theme_dark" }}
<span class="theme-icon dark d-none" aria-hidden="true">{{ i18n "theme_dark_short" }}</span>
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="auto"
aria-pressed="false">
{{ i18n "theme_auto" }}
<span class="theme-icon light d-none" aria-hidden="true">{{ i18n "theme_light_short" }}</span>
</button>
</li>
</ul>
</div>
@@ -0,0 +1,114 @@
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "showcase" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="rad-showcase rad-showcase--index rad-animation-group rad-fade-down">
<div id="main-content">
{{- $contextType := printf "%T" . -}}
{{- $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") -}}
{{- $inner := (.Scratch.Get "Inner") -}}
{{/* ---------------------------------------------------------------------------
INTRO TITLE / DESCRIPTION / BUTTON
--------------------------------------------------------------------------- */}}
{{- /* Intro title/description */}}
{{- $showcaseTitle := "" -}}
{{- $showcaseSubtitle := "" -}}
{{- $showcaseDescription := "" -}}
{{- $buttonURL := "" -}}
{{- $buttonIcon := "" -}}
{{- $buttonText := "" -}}
{{- $imgSrc := "" -}}
{{- $imgWidth := 0 -}}
{{- $imgHeight := 0 -}}
{{- $imgScale := 0.5 -}}
{{- $socialLinks := "" -}}
{{- if $isShortcode }}
{{/* Shortcode params */}}
{{- $showcaseTitle = .Get "title" | default ( i18n "showcase_title" ) -}}
{{- $showcaseSubtitle = .Get "subtitle" | default ( i18n "showcase_subtitle" ) -}}
{{- $showcaseDescription = .Get "description" | default ( i18n "showcase_description" ) | safeHTML -}}
{{- $buttonURL = .Get "button_url" | default .Site.Data.homepage.showcase.button.URL -}}
{{- $buttonIcon = .Get "button_icon" | default .Site.Data.homepage.showcase.button.icon -}}
{{- $buttonText = .Get "button_text" | default false -}}
{{- $imgSrc = .Get "imgSrc" | default .Site.Data.homepage.showcase.image.src -}}
{{- $imgWidth = .Get "imgWidth" | default .Site.Data.homepage.showcase.image.width -}}
{{- $imgHeight = .Get "imgHeight" | default .Site.Data.homepage.showcase.image.height -}}
{{- $imgScale = .Get "imgScale" | default .Site.Data.homepage.showcase.image.scale -}}
{{- $socialLinks = .Get "social_links" -}}
{{ else }}
{{/* Fallback site or i18n */}}
{{- $showcaseTitle = i18n "showcase_title" -}}
{{- $showcaseSubtitle = i18n "showcase_subtitle" -}}
{{- $showcaseDescription = i18n "showcase_description" | safeHTML -}}
{{- $buttonURL = .Site.Data.homepage.showcase.button.URL -}}
{{- $buttonIcon = .Site.Data.homepage.showcase.button.icon -}}
{{- $buttonText = i18n "showcase_button" -}}
{{- $imgSrc = .Site.Data.homepage.showcase.image.src -}}
{{- $imgWidth = .Site.Data.homepage.showcase.image.width -}}
{{- $imgHeight = .Site.Data.homepage.showcase.image.height -}}
{{- $imgScale = .Site.Data.homepage.showcase.image.scale -}}
{{- $socialLinks = .Site.Data.homepage.showcase.socialLinks -}}
{{ end }}
{{ warnf "showcase.html: Image x: %q" $imgSrc }}
<div class="showcase-section row flex-column-reverse flex-md-row rad-fade-down rad-waiting rad-animate">
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
<h1 class="display-1">
{{ $showcaseTitle }}
</h1>
<h2 class="display-5">
<span>{{ $showcaseSubtitle | safeHTML }}</span>
</h2>
<div class="lead">
{{ $showcaseDescription }}
</div>
{{ if $buttonText }}
<a
href="{{ $buttonURL }}"
class="btn btn-primary"
>
<i class="{{ $buttonIcon }}"></i>
{{ $buttonText }}
</a>
{{ end }}
</div>
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6 profile-image">
{{ partial "lazypicture" (dict "src" $imgSrc "width" $imgWidth "height" $imgHeight "scale" $imgScale "class" "")}}
<!-- future "right text -->
</div>
{{- if $inner }}
<div class="col-12 inner-content">
{{ $inner }}
</div>
{{ end }}
</div>
<div class="row platform-links">
<div class="col-12">
{{- if $socialLinks -}}
{{ range $socialLinks }}
<a href="{{ .URL | absURL }}" target="_blank" rel="noopener noreferrer" aria-label="{{ .icon }}"
><i class="icon-{{ .icon }}"></i
></a>
{{ end }}
{{- end -}}
</div>
</div>
</div>
</section>
@@ -0,0 +1,5 @@
<a href="#main-content"
class="skip-to-content-link"
aria-label='{{ i18n "skipToMainContent" }}'>
{{ i18n "skipToMainContent" }}
</a>
@@ -0,0 +1,61 @@
{{ $shareUrl := .Permalink }}
{{ $shareTitle := .Title }}
{{ $shareDescription := .Description | default .Summary }}
{{ if or .Site.Params.sharing.enabled (not (isset .Site.Params.sharing "enabled")) }}
<aside class="social-sharing light-border-top">
<h3>{{ i18n "share_this_post" | default "Share this post" }}</h3>
<div class="share-buttons">
{{ if or .Site.Params.sharing.twitter (not (isset .Site.Params.sharing "twitter")) }}
<a href="https://twitter.com/intent/tweet?url={{ $shareUrl | urlquery }}&text={{ $shareTitle | urlquery }}"
target="_blank"
rel="noopener noreferrer"
aria-label="{{ i18n "share_on_twitter" | default "Share on Twitter" }}"
class="share-button share-twitter">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
</svg>
<span>{{ i18n "share_twitter_label" | default "Twitter" }}</span>
</a>
{{ end }}
{{ if or .Site.Params.sharing.linkedin (not (isset .Site.Params.sharing "linkedin")) }}
<a href="https://www.linkedin.com/sharing/share-offsite/?url={{ $shareUrl | urlquery }}"
target="_blank"
rel="noopener noreferrer"
aria-label="{{ i18n "share_on_linkedin" | default "Share on LinkedIn" }}"
class="share-button share-linkedin">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
</svg>
<span>{{ i18n "share_linkedin_label" | default "LinkedIn" }}</span>
</a>
{{ end }}
{{ if or .Site.Params.sharing.facebook (not (isset .Site.Params.sharing "facebook")) }}
<a href="https://www.facebook.com/sharer/sharer.php?u={{ $shareUrl }}"
target="_blank"
rel="noopener noreferrer"
aria-label="{{ i18n "share_on_facebook" | default "Share on Facebook" }}"
class="share-button share-facebook">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
</svg>
<span>{{ i18n "share_facebook_label" | default "Facebook" }}</span>
</a>
{{ end }}
{{ if or .Site.Params.sharing.email (not (isset .Site.Params.sharing "email")) }}
<a href="mailto:?subject={{ $shareTitle }}&body={{ $shareDescription }}%0A%0A{{ $shareUrl }}"
aria-label="{{ i18n "share_via_email" | default "Share via Email" }}"
class="share-button share-email">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
<span>{{ i18n "share_email_label" | default "Email" }}</span>
</a>
{{ end }}
</div>
</aside>
{{ end }}
@@ -0,0 +1,55 @@
{{- $contextType := printf "%T" . -}}
{{- $isShortcode := (eq $contextType "*hugolib.ShortcodeWithPage") -}}
{{/* ---------------------------------------------------------------------------
SECTION TITLE
--------------------------------------------------------------------------- */}}
{{- $title := "" -}}
{{- if $isShortcode }}
{{- $title = .Get "title" -}}
{{ else }}
{{- $title = i18n "testimonials_title" -}}
{{ end }}
{{/* ---------------------------------------------------------------------------
TESTIMONIALS COLLECTION
--------------------------------------------------------------------------- */}}
{{- $testimonials := (where .Site.RegularPages.ByDate "Type" "testimonial") -}}
{{- if not $isShortcode }}
{{- $baseLangSite := .Sites.Default -}}
{{- $testimonials = $testimonials | lang.Merge (where $baseLangSite.RegularPages.ByDate "Type" "testimonial") -}}
{{- end -}}
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "testimonial" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section rad-animation-group section--border-bottom">
<div class="container">
{{/*
When passed from a shortcode, the context type is *hugolib.ShortcodeWithPage.
When passed from a partial included in a page via params, the context type is *hugolib.pageState.
*/}}
<h2 class="rad-fade-down">{{ $title }}</h2>
<div class="row row--padded mb-0 rad-fade-down">
{{ range $testimonials }}
<div class="col-12 col-md-4 mb-5 mb-md-0 testimonial container">
<i class="icon-quote-left"></i>
{{ .Content }}
<div class="testimonial__author row gx-0">
{{ partial "lazypicture" (dict "src" .Params.image.src "scale" .Params.image.scale "pictureclass" "picture testimonial col-2" "alt" $title)}}
<div class="testimonial__author-info col-10">
<h3>{{ .Params.name }}</h3>
<span>{{ .Params.position }}</span>
</div>
</div>
</div>
{{ end }}
</div>
</div>
</section>
@@ -0,0 +1,8 @@
{{ if and .Params.toc (gt .WordCount 400) }}
{{ if .TableOfContents }}
<aside class="table-of-contents {{ if .Params.tocSticky }}toc-sticky{{ end }}">
<h3>{{ i18n "table_of_contents" | default "Table of Contents" }}</h3>
{{ .TableOfContents }}
</aside>
{{ end }}
{{ end }}
+7
View File
@@ -0,0 +1,7 @@
User-agent: *
{{- if hugo.IsProduction | or (eq site.Params.env "production") }}
Disallow:
{{- else }}
Disallow: /
{{- end }}
Sitemap: {{ "sitemap.xml" | absURL }}
@@ -0,0 +1 @@
{{ partial "about.html" . }}
@@ -0,0 +1 @@
{{ partial "client-and-work.html" . }}
@@ -0,0 +1 @@
{{ partial "contact.html" . }}
@@ -0,0 +1 @@
{{ partial "education.html" . }}
@@ -0,0 +1,54 @@
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "experience-list-shortcode" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
{{ $padding := .Get "padding" }}
{{ $title := .Get "title" | default "" }}
{{ $containerClass := "" }}
{{ if eq $padding "true" }}
{{ $containerClass = "container" }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section-experience section section--border-bottom rad-animation-group flex-grow-1 {{ $containerClass }}">
<div class="row flex-column-reverse flex-md-row rad-fade-down">
<div class="experience-list col-12 mt-5 mt-sm-0">
{{ if $title }}
<h2 class="section__title mb-4">{{ $title }}</h2>
{{ end }}
{{ $xp := (where .Site.RegularPages.ByDate "Type" "experience") }}
{{ $xpCount := len $xp }}
{{ range $index, $element := first $xpCount (sort $xp "Date" "desc") }}
<div class="experience row">
<div class="experience__header col-12 col-md-3 d-flex align-items-start">
{{ $img := resources.Get .Params.companyLogo }}
{{ with $img }}
{{ $imgWebp := $img.Resize (printf "%dx%d webp q75 Lanczos picture" $img.Width $img.Height) }}
<img src="{{ $imgWebp.RelPermalink }}" alt="{{ .Params.company }} logo"
class="experience__company-logo" loading="lazy">
{{ end }}
<div class="experience__meta">
<div class="experience__date">{{ .Params.duration }}</div>
<div class="experience__title">{{ .Params.jobTitle }}</div>
<div class="experience__company">{{ .Params.company }}. <span class="experience__location">
{{ .Params.location }}</span></div>
</div>
</div>
<div class="experience__description d-print-block col-12 col-md-9 mt-3 mt-md-0">
<h1>{{ .Params.title }}</h1>
{{ .Content | safeHTML }}
</div>
</div>
{{ if ne $index (sub $xpCount 1) }}
<!-- Separator between experiences for mobile -->
<hr class="d-block d-md-none my-4">
{{ end }}
{{ end }}
</div>
</div>
</section>
@@ -0,0 +1 @@
{{ partial "experience.html" . }}
@@ -0,0 +1,9 @@
{{ $url := .Get "url" }}
{{ $icon := .Get "icon" }} <!-- Fixed variable assignment for icon -->
<a
href="{{ $url | absURL }}"
target="_blank"
rel="noopener noreferrer"
{{ if $icon }}aria-label="{{ $icon }}"{{ end }}
>{{ if $icon }}<i class="icon-{{ $icon }}"></i>{{ end }}
</a>
@@ -0,0 +1 @@
{{ partial "newsletter.html" . }}
@@ -0,0 +1,11 @@
{{/* layouts/shortcodes/platform-links.html */}}
{{ $sectionId := "" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
<div class="container"{{ if $sectionId }} id="{{ $sectionId }}"{{ end }}>
<div class="row platform-links shortcode">
<div class="col-12">{{ .Inner }}</div>
</div>
</div>
@@ -0,0 +1,2 @@
{{ .Scratch.Set "Inner" .Inner }}
{{ partial "showcase.html" . }}
@@ -0,0 +1,14 @@
{{ $size := .Get "size" | default "medium" }}
{{ $class := "" }}
{{ if eq $size "small" }}
{{ $class = "pt-3" }}
{{ else if eq $size "medium" }}
{{ $class = "pt-5" }}
{{ else if eq $size "large" }}
{{ $class = "pt-5 mt-4" }}
{{ else if eq $size "xlarge" }}
{{ $class = "pt-5 mt-5" }}
{{ end }}
<div class="spacer {{ $class }}"></div>
@@ -0,0 +1 @@
{{ partial "testimonial.html" . }}
@@ -0,0 +1,42 @@
{{/*
sectionId: Optional argument to override the default HTML id for this section. If not provided, the default id is used. */}}
{{ $sectionId := "" }}
{{ with .Get "sectionId" }}
{{ $sectionId = . }}
{{ end }}
{{ $title := .Get "title" | default "" }}
{{ $subtitle := .Get "subtitle" | default "" }}
{{ $padding := .Get "padding" | default "true" }}
{{ $centered := .Get "centered" | default "false" }}
{{ $containerClass := "" }}
{{ $paddingClass := "" }}
{{ $columnClass := "col-12" }}
{{ if eq $padding "true" }}
{{ $containerClass = "container" }}
{{ $paddingClass = "section--padding" }}
{{ end }}
{{ if eq $centered "true" }}
{{ $containerClass = printf "%s %s" $containerClass "d-flex justify-content-center align-items-center" }}
{{ $columnClass = printf "%s %s" $columnClass "text-center" }}
{{ end }}
<section {{if $sectionId}} id="{{ $sectionId }}"{{end}} class="section section--border-bottom rad-animation-group {{ $paddingClass }}">
<div class="{{ $containerClass }}">
<div class="row rad-fade-down">
<div class="{{ $columnClass }}">
{{ if $title }}
<h2 class="section__title">{{ $title }}</h2>
{{ end }}
{{ if $subtitle }}
<p class="section__subtitle">{{ $subtitle }}</p>
{{ end }}
<div class="text-section__content">
{{ .Inner | markdownify }}
</div>
</div>
</div>
</div>
</section>
@@ -0,0 +1,14 @@
{{ $class := .Get "class" | default "table-of-contents" }}
{{ $heading := .Get "heading" | default "Table of Contents" }}
{{ $showHeading := .Get "showHeading" | default true }}
{{ if .Page.TableOfContents }}
<div class="{{ $class }}">
{{ if $showHeading }}
<h2 class="toc-heading">{{ $heading }}</h2>
{{ end }}
<div class="toc-content">
{{ .Page.TableOfContents }}
</div>
</div>
{{ end }}
+41
View File
@@ -0,0 +1,41 @@
{{ define "main" }}
<section class="site-skills-section">
<div class="container">
<div class="row">
<div class="col-12 text-center">
<h1 class="site-skills-title">{{ .Title }}</h1>
<div class="site-skills-description">
{{ .Content }}
</div>
</div>
</div>
{{ range .Params.skill_categories }}
<div class="row mt-5">
<div class="col-12">
<h2 class="mb-4">{{ .name }}</h2>
<div class="row">
{{ range .skills }}
<div class="col-md-6">
<div class="skill-item">
<div class="skill-header">
<h3 class="skill-name">{{ .name }}</h3>
<span class="skill-level">{{ .level }}%</span>
</div>
<div class="skill-bar">
<div class="skill-bar-fill" style="width: {{ .level }}%;"></div>
</div>
<div class="d-flex justify-content-between align-items-center">
<span class="skill-years">{{ .years }} years</span>
<span class="skill-description">{{ .description }}</span>
</div>
</div>
</div>
{{ end }}
</div>
</div>
</div>
{{ end }}
</div>
</section>
{{ end }}