Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<p align="center">
<a href="https://ainsley.dev">
<img src="./res/symbol.png" height="96">
<img src="./resources/symbol.png" height="96">
<h3 align="center">ainsley.dev</h3>
</a>
</p>
Expand All @@ -19,16 +19,17 @@
<div align="center">

[![Vercel](https://therealsujitk-vercel-badge.vercel.app/?app=website&style=plastic)](https://ainsley.dev)
[![Go Report Card](https://goreportcard.com/badge/github.com/ainsleydev/webkit)](https://goreportcard.com/report/github.com/ainsleydev/website)
[![Test](https://github.com/ainsleydev/website/actions/workflows/test.yaml/badge.svg)](https://github.com/ainsleydev/website/actions/workflows/test.yaml)
[![Maintainability](https://api.codeclimate.com/v1/badges/f5912a1dec11b8003850/maintainability)](https://codeclimate.com/github/ainsleydev/website/maintainability)
[![Coverage](https://codecov.io/gh/ainsleydev/website/branch/dev/graph/badge.svg?token=Y8crTxn7Ic)](https://codecov.io/gh/ainsleydev/website)
[![ainsley.dev](https://img.shields.io/badge/-ainsley.dev-black?style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJTUUH5wEYDzUGL1b35AAABA1JREFUWMPtlttvFVUUxn977ZnZu+W0tLalqRovBAUvQag0xNQbpSIosSSIJC198YknJfHJxDf9A/DBJ0x8MbFACjVqvCASq6FYFLFBvJAaAomkFCmhHGpLO+PDzOmZzpn2nKP4pCs5ycmevb7vW99as/fA//FfD1XO5p1nzuA3NWJHx5T8cVkRBPHHQfRjd0tzyZhOOQIy27bAxET9zCuvvhY0r2kC/OiRABeAN4BL/4oDr9+3lGszPs7UVNfUE23v3Nj5koszR/8N4EXg3XJckFIFuCLUuU7GWNNtTg25cu4syJx0F+gGMuU4UJKAt1Yux1UKV6TVat1qs+OYwQESMwDQCjwKsOv4iZsnwGihwbiuEek2WjJGhMrvv0UujYKa08VFkQvuTXNgz6oVeCIo1CqrZYMRwTiaytERKn44kRQAsAFYDbBrsLgLRQU0GI919TXKiHQaUQ1GBCuCCQKqjg/MqInrM4lZrgc6A1CljHhRAZ4Ip65m77FaOmbJdehC5vzZr1RAf/T6x6NDwb3/uAVfP74GnwCjZasRuXuWXASj9XQme+3t6erqPcB0IvUuYCsUH8YFBRhRNBqvyYpsn0MeOnG6wvc/9x33MPBjSvp24Na/7cDP7Y/gKIURecZoeTBObkSwWg7UNjaOeFfGLgK9KRAPAM8Wc2FeAUaEWtddbEV2WBFtREXkCqvlghE5yOQkvucBHAR+T0BooAtYXLYDI5sewxWFJ/Kk1bI2UTlW5DMFp03+JPwJ+DQFai2wbiEXUgVUas0trmuslm4jUmGi/tuwDVmrpafBuNPVrs7N/wzQA2QTUJbwYLIlOxB0tOGJ4IhqsSJts+T54Rv0lBz1RFh9ZJA385fOAHAshaMNaAF4OcWFQgeUwhMlrlJdnqjaOLkR8Y2WvbWec9VIQeo4sJf8FZ2LmmgWJO1cmm8I7wc2a6XwosGL+v+rFfnYUYplh47Obo5dvZ8Av6TgbSZ8KxYWEGxZn/u7Dbg9t8HNnwF9S2qqzqVUn4vzQF/K+m3AC1A4jGlId0QC8l0BXKVGrahe//okNR99WZAUc6EXuJiC+zxw57wOxKp/DliRAvCFKDUkxS+YIeBwyvryCHuOC0kH6oBOCj/V/gTeA6aK0oefZj3ARGJdRdh1BQ7Eqm8HHk4B/Q7oB1B9acWFEWtDf5STjGbgqbgLcQcqCQ8NL5EUAPuBsRKqz8UVYB+F97QXcSyatSXoWJ8zvB04AFQlkoaBp4HhhaqPR1TdUsLjeVni8TjhVX0odCAkd4AdKeQAHxIwXEb1Odt+Az5IeVQVcTmhgDBWAhtTNl8G9qGAwKfU2N3SnJvi/RFGMjYCD8UFdACNKRsHgZMA6v0j5ZpAlPtNyvqSiJO/AKik60y0ALlUAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIzLTAxLTI0VDE1OjUzOjA2KzAwOjAwm5vntAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMy0wMS0yNFQxNTo1MzowNiswMDowMOrGXwgAAABXelRYdFJhdyBwcm9maWxlIHR5cGUgaXB0YwAAeJzj8gwIcVYoKMpPy8xJ5VIAAyMLLmMLEyMTS5MUAxMgRIA0w2QDI7NUIMvY1MjEzMQcxAfLgEigSi4A6hcRdPJCNZUAAAAASUVORK5CYII=)](https://ainsley.dev)
[![Twitter Handle](https://img.shields.io/twitter/follow/ainsleydev)](https://twitter.com/ainsleydev)

</div>

## ainsley.dev

Website and theme source code for [ainsley.dev](https://ainsley.dev).
Website and theme source code for [ainsley.dev](https://ainsley.dev) and [ainsleyclark.com](https://ainsleyclark.com)

Coupling state-of-the-art technology with stunning designs, we create memorable digital transformations and well-crafted
software for everyone from startups to established brands.
Expand Down Expand Up @@ -69,7 +70,7 @@ Kingdom and/or other countries. All other trademarks are the property of their r
## Copyright

You may not, except with our express written permission, distribute or commercially exploit the content found within
the `/content` folder or any written text within this repository. Nor may you transmit it or store it in any other
the `content` folder or any written text within this repository. Nor may you transmit it or store it in any other
website or other form of electronic retrieval system.

Any redistribution or reproduction of part or all of the contents in any form is prohibited other than the following:
Expand All @@ -82,5 +83,3 @@ Any redistribution or reproduction of part or all of the contents in any form is

Code Copyright 2023 ainsley.dev. Code released under the [BSD-3 Clause](LICENSE).

[//]: # ([![Maintainability]&#40;https://api.codeclimate.com/v1/badges/f5912a1dec11b8003850/maintainability&#41;]&#40;https://codeclimate.com/github/ainsleydev/website/maintainability&#41;)

18 changes: 14 additions & 4 deletions api/_pkg/middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ const (
// AuthHeader is the header used for authentication via an
// API Key
AuthHeader = "X-API-Key"
// OriginURL is the URL of the site to compare against
// in production.
OriginURL = "https://ainsley.dev"
)

// OriginURLs is the list of allowed origins to compare against in production.
var OriginURLs = []string{
"https://ainsley.dev",
"https://ainsleyclark.com",
}

// Auth validates API request and determines if the AuthHeader value is of equal
// to the header send in the request.
// Returns errors.INVALID if there is a mismatch.
Expand All @@ -40,7 +43,14 @@ func Auth(cfg *environment.Config) echo.MiddlewareFunc {
// Vercel comes back with a different URL in production for some reason.
// So a static variable needs to be used.
// TODO: See if there is a more graceful way of doing this.
if !strings.Contains(origin, OriginURL) || origin == "" {
allowed := false
for _, u := range OriginURLs {
if strings.Contains(origin, u) {
allowed = true
break
}
}
if !allowed || origin == "" {
return false, fmt.Errorf("bad origin: %s, with comparison: %s", origin, cfg.URL)
}
return auth == cfg.APIKey, nil
Expand Down
16 changes: 14 additions & 2 deletions api/_pkg/middleware/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,23 @@ func TestAuth(t *testing.T) {
},
want: http.StatusOK,
},
"OK Production": {
"OK Production ainsley.dev": {
input: func(r *http.Request) {
t.Setenv(AuthHeader, "key")
r.Header.Set(AuthHeader, "key")
r.Header.Set("Origin", OriginURL)
r.Header.Set("Origin", OriginURLs[0])
},
config: environment.Config{
Env: "production",
APIKey: "key",
},
want: http.StatusOK,
},
"OK Production ainsleyclark.com": {
input: func(r *http.Request) {
t.Setenv(AuthHeader, "key")
r.Header.Set(AuthHeader, "key")
r.Header.Set("Origin", OriginURLs[1])
},
config: environment.Config{
Env: "production",
Expand Down
96 changes: 0 additions & 96 deletions sites/ainsley-clark/BRIEF.md

This file was deleted.

10 changes: 0 additions & 10 deletions sites/ainsley-clark/config/_default/params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,5 @@ codepen:
footer:
title: 'Shipping Go at scale.<br class="d-none d-desk-inline"/>Growing engineers.<br class="d-none d-desk-inline"/>Building communities that last.'
subText: 'All original content, code, and written works published on this site are the intellectual property of ainsley.dev LTD unless otherwise stated.'
bio:
image: images/bio.jpg
title: "Hi, I'm Ainsley."
content: |
<p>Most of my time is spent writing Go at Just Eat Takeaway.com, where I work as a Senior/Lead Software Engineer across platform services, architecture, and tooling. The rest goes into the thing I care about just as much — growing engineers and the Go community.</p>
<p>At JET, that meant founding and chairing the Go Guild, a cross-organisation community focused on Go adoption, engineering standards, and knowledge sharing. We've published over 10 episodes on YouTube, hosted speakers like Eleanor McHugh, and built a space where Gophers across the company come together to learn and set the bar higher.</p>
<p>In 2025, I spoke at GopherCon UK on how Just Eat uses tooling to deploy Go micro-services in minutes. Before that, I presented at JET TechFest and started creating content around Go best practices — from writing well-crafted packages to effective error handling.</p>
<p>Before JET, I spent four years at Reddico as a Senior Full Stack Engineer, designing and shipping an intelligent link-building tool that processed 100k+ tasks daily across ten bespoke micro-services. I also founded ainsley.dev, a registered software company that won Website of the Year in its first year — end-to-end experience from branding and design through to architecture and deployment.</p>
<p>Open source is a big part of how I contribute back. go-mail (190+ stars) is a cross-platform mail driver for Go. Verbis is a CMS built entirely in Go. WebKit turns a single app.json manifest into production-ready infrastructure and CI/CD pipelines.</p>
<p>The thread through all of it — whether it's code review, pair programming, one-on-ones, or running a guild — is making the engineers around me better and building communities where people actually grow.</p>
wording:
pronoun: me
17 changes: 15 additions & 2 deletions sites/ainsley-clark/content/_index.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
---
title: Full Stack Software Engineer (GoLang | PHP | TypeScript) at @justeat Gopher, developer, author & tech enthusiast.
title: Full Stack Engineer, Author, Speaker & Mentor
description: Ainsley Clark, a full stack software engineer working at Just Eat Takeaway.com & founder of ainsley.dev with a passion for all things tech.
heading: Shipping Go at <span class="type-serif">scale*</span><br/>Growing engineers<br class="d-none d-tab-inline"/>Building communities that <u>last</u>
lead: Senior/Lead Software Engineer at Just Eat Takeaway.com. GopherCon UK speaker. Chair of the Go Guild at JET and open-source contributor. Passionate about writing well-crafted Go, mentoring engineers, and building communities where Gophers thrive.
lead: Senior software engineer at Just Eat Takeaway.com, owner of ainsley.dev (web design & dev), conference speaker & leader. & open-source contributor. Passionate about writing well-crafted Go, mentoring the next generation, and building communities where engineers thrive.
styles:
- scss/pages/home.scss
bio:
image: images/bio.jpg
title: "Hi, I'm Ainsley."
content: |
<h3>Hi, I'm Ainsley</h3>
<p>I've always been a bit of a geek at heart. Starting with off with a pair off decks as a kid which led me into a Music Technology degree, and somewhere along the way turned into a career building software. I can say I love what I do & always excited about all things tech.</p>
<h4>Engineering</h4>
<p>Most of my time is spent writing Go at Just Eat Takeaway.com, leading platform work across architecture, services and tooling at scale.</p>
<h4>Advocating</h4>
<p>Giving back matters to me, whether that's speaking at conferences, contributing to open source, or contributing to the Just Eat Go Guild to raise engineering standards across teams.</p>
<h4>Mentoring</h4>
<p>I've always loved investing in people, and watching people grow through one to ones, code reviews and pair programming.</p>
skills:
- title: Languages & Frameworks
list:
Expand Down
2 changes: 1 addition & 1 deletion sites/ainsley-clark/layouts/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ <h1>
<!-- =====================
Bio
===================== -->
{{ with .Site.Params.bio }}
{{ with .Params.bio }}
<section id="bio" class="bio section section-padding section-padding-bottom" data-scroll-section style="overflow-x: clip;">
<div class="container">
<div class="row">
Expand Down
57 changes: 56 additions & 1 deletion themes/shared/assets/js/animations/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export class Animations {
this.playables.push(...up());
this.playables.push(...fade());
this.playables.push(carousel());
this.playables.push(logoCarousel());
}

/**
Expand Down Expand Up @@ -144,6 +145,7 @@ const hero = (): Playable => {
anime.set(heading.querySelectorAll('.word'), { opacity: 1 });
anime.set(heading.querySelectorAll('.char'), { opacity: 0 });
anime.set(heading.querySelectorAll('.hero .arrow-hover'), { opacity: 0 });

const timeline = anime
.timeline({
autoplay: false,
Expand Down Expand Up @@ -204,7 +206,7 @@ const hero = (): Playable => {
duration: 1000,
},
900,
);
)

const arrow = document.querySelector('.hero .arrow-hover');
if (arrow) {
Expand Down Expand Up @@ -417,3 +419,56 @@ const carousel = (): Playable => {

return timeline.play;
};

/**
* Logo Carousel animation (a-clark homepage).
*/
const logoCarousel = (): Playable => {
const items = document.querySelectorAll('.logo-carousel-slide');
if (!items.length) {
return <() => void>{};
}

anime.set(items, { opacity: 0 });

const timeline = anime.timeline({
autoplay: false,
});

// Mobile (simple fade, no bounce)
if (window.innerWidth < 1024) {
timeline.add({
targets: items,
opacity: [0, 1],
easing: 'easeInQuad',
duration: 1000,
delay: anime.stagger(100),
});
return timeline.play;
}

// Desktop — separate translateY and opacity, matches carousel() pattern
timeline
.add(
{
targets: items,
translateY: [250, 0],
easing: 'easeOutElastic',
duration: 2500,
delay: anime.stagger(120),
},
0,
)
.add(
{
targets: items,
opacity: [0, 1],
easing: 'easeInQuad',
duration: 1000,
delay: anime.stagger(100),
},
100,
);

return timeline.play;
};
2 changes: 1 addition & 1 deletion themes/shared/assets/js/pages/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const homeAnimation = (): void => {
duration: 2000,
},
'-=4000',
);
)

Scroll.onScroll((y: number) => {
const percent = (y / (height + offset - Elements.HTML.clientHeight)) * 100;
Expand Down
8 changes: 7 additions & 1 deletion themes/shared/assets/scss/components/_logo-carousel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
position: relative;
width: 100%;
overflow-x: clip;
isolation: isolate;
margin-top: clamp(60px, 10vw, 100px);

// Gradients
Expand All @@ -21,6 +22,11 @@
width: clamp(80px, 16vw, 160px);
z-index: 1;
pointer-events: none;

@include media-desk {
top: -100px;
bottom: -100px;
}
}

&::before {
Expand All @@ -37,7 +43,7 @@
// =========================================================================

&-embla {
overflow: hidden;
overflow-x: clip;
}

&-container {
Expand Down
2 changes: 1 addition & 1 deletion themes/shared/layouts/_default/sitemap.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
{{ range .Data.Pages }}
{{- if and (.Permalink) (not .Params.private) -}}
{{- if and (.Permalink) (not .Params.private) (ne .Params.build.render "never") -}}
<url>
<loc>{{ .Permalink }}</loc>{{ if or (eq .Sitemap.Priority 1.0) (not .Lastmod.IsZero) }}
<lastmod>{{ if eq .Sitemap.Priority 1.0 }}{{ now.Format "2006-01-02T15:04:05-07:00" | safeHTML }}{{ else }}{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}{{ end }}</lastmod>{{ end }} {{ with .Sitemap.ChangeFreq }}
Expand Down
Loading