diff --git a/README.md b/README.md
index 7c41cfe2..ef4e42d1 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
+
ainsley.dev
@@ -19,16 +19,17 @@
[](https://ainsley.dev)
+[](https://goreportcard.com/report/github.com/ainsleydev/website)
[](https://github.com/ainsleydev/website/actions/workflows/test.yaml)
-[](https://codeclimate.com/github/ainsleydev/website/maintainability)
[](https://codecov.io/gh/ainsleydev/website)
+[](https://ainsley.dev)
[](https://twitter.com/ainsleydev)
## 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.
@@ -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:
@@ -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).
-[//]: # ([](https://codeclimate.com/github/ainsleydev/website/maintainability))
-
diff --git a/api/_pkg/middleware/auth.go b/api/_pkg/middleware/auth.go
index 8b28a73d..d65658dd 100644
--- a/api/_pkg/middleware/auth.go
+++ b/api/_pkg/middleware/auth.go
@@ -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.
@@ -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
diff --git a/api/_pkg/middleware/auth_test.go b/api/_pkg/middleware/auth_test.go
index 3d4d20e9..48565f30 100644
--- a/api/_pkg/middleware/auth_test.go
+++ b/api/_pkg/middleware/auth_test.go
@@ -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",
diff --git a/sites/ainsley-clark/BRIEF.md b/sites/ainsley-clark/BRIEF.md
deleted file mode 100644
index 7ba5e25c..00000000
--- a/sites/ainsley-clark/BRIEF.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# ainsleyclark.com — Content Brief
-
----
-
-## Hero
-
-**Headline:**
-Shipping Go at scale. Growing engineers. Building communities that last.
-
-**Lead paragraph:**
-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.
-
----
-
-## Logos
-
-**Label:** "Companies I've worked with"
-
-- Just Eat Takeaway.com
-- Reddico
-- ainsley.dev
-- Dec's Pets
-- Oak Tuition
-- S.Clark
-- Thinkopedia
-- Royal Beauty
-- Scott's Guttering
-- EDR Dental
-- Elite Roofing
-
----
-
-## Bio
-
-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.
-
-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.
-
-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.
-
-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.
-
-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.
-
-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.
-
----
-
-## Media
-
-### Conference Talks
-
-- **GopherCon UK 2025** — How Just Eat uses tooling to deploy Go micro-services in minutes
-
-### Just Eat Go Guild (YouTube)
-
-- Feb 2026 — Diving into Go's 1.26, survey results and a round up
-- Nov 2025 — Community insights & network resilience
-- April 2025 — Diving into the new Go tool directive
-- Feb 2025 — Exploring Go 1.24, plus a deep dive into Go's internals
-- Dec 2024 — Go 1.24 Unveiled: Discover the Latest Features
-- Oct 2024 — How passing tests can still cause issues in production
-- Sept 2024 — Building Open Source Go Projects in Public with MelkeyDev
-
-### Written
-
-- How to write well-crafted GoLang packages
-- Effective error handling in GoLang: how to Error()
-- Responsibilities as a developer for optimised SEO
-
----
-
-## Contact
-
-**Heading:** Let's talk
-
-**Subtext:** Whether it's about Go, open source, engineering leadership, or opportunities — I'd love to hear from you.
-
-**Form fields:**
-- Name
-- Email
-- Message
-- Send button
-
----
-
-## Footer
-
-**Links:**
-- ainsley.dev
-- GitHub (github.com/ainsleyclark)
-- LinkedIn (linkedin.com/in/ainsleyclark)
-- X / Twitter (@ainsleydev)
-
-**Optional tagline:**
-Built with Go, obviously.
diff --git a/sites/ainsley-clark/config/_default/params.yaml b/sites/ainsley-clark/config/_default/params.yaml
index 6f00894e..6c22f848 100644
--- a/sites/ainsley-clark/config/_default/params.yaml
+++ b/sites/ainsley-clark/config/_default/params.yaml
@@ -50,15 +50,5 @@ codepen:
footer:
title: 'Shipping Go at scale.
Growing engineers.
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: |
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
wording:
pronoun: me
diff --git a/sites/ainsley-clark/content/_index.md b/sites/ainsley-clark/content/_index.md
index a4830106..5c17593b 100644
--- a/sites/ainsley-clark/content/_index.md
+++ b/sites/ainsley-clark/content/_index.md
@@ -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 scale*
Growing engineers
Building communities that last
-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: |
+ Hi, I'm Ainsley
+ 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.
+ Engineering
+ Most of my time is spent writing Go at Just Eat Takeaway.com, leading platform work across architecture, services and tooling at scale.
+ Advocating
+ 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.
+ Mentoring
+ I've always loved investing in people, and watching people grow through one to ones, code reviews and pair programming.
skills:
- title: Languages & Frameworks
list:
diff --git a/sites/ainsley-clark/layouts/index.html b/sites/ainsley-clark/layouts/index.html
index e7d7904d..71f2e1ec 100644
--- a/sites/ainsley-clark/layouts/index.html
+++ b/sites/ainsley-clark/layouts/index.html
@@ -64,7 +64,7 @@
- {{ with .Site.Params.bio }}
+ {{ with .Params.bio }}
diff --git a/themes/shared/assets/js/animations/text.ts b/themes/shared/assets/js/animations/text.ts
index 3ed7575a..fd798467 100644
--- a/themes/shared/assets/js/animations/text.ts
+++ b/themes/shared/assets/js/animations/text.ts
@@ -42,6 +42,7 @@ export class Animations {
this.playables.push(...up());
this.playables.push(...fade());
this.playables.push(carousel());
+ this.playables.push(logoCarousel());
}
/**
@@ -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,
@@ -204,7 +206,7 @@ const hero = (): Playable => {
duration: 1000,
},
900,
- );
+ )
const arrow = document.querySelector('.hero .arrow-hover');
if (arrow) {
@@ -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;
+};
diff --git a/themes/shared/assets/js/pages/home.ts b/themes/shared/assets/js/pages/home.ts
index 0c1fee1b..c8327aeb 100644
--- a/themes/shared/assets/js/pages/home.ts
+++ b/themes/shared/assets/js/pages/home.ts
@@ -94,7 +94,7 @@ export const homeAnimation = (): void => {
duration: 2000,
},
'-=4000',
- );
+ )
Scroll.onScroll((y: number) => {
const percent = (y / (height + offset - Elements.HTML.clientHeight)) * 100;
diff --git a/themes/shared/assets/scss/components/_logo-carousel.scss b/themes/shared/assets/scss/components/_logo-carousel.scss
index dd5bedef..03bf0498 100644
--- a/themes/shared/assets/scss/components/_logo-carousel.scss
+++ b/themes/shared/assets/scss/components/_logo-carousel.scss
@@ -7,6 +7,7 @@
position: relative;
width: 100%;
overflow-x: clip;
+ isolation: isolate;
margin-top: clamp(60px, 10vw, 100px);
// Gradients
@@ -21,6 +22,11 @@
width: clamp(80px, 16vw, 160px);
z-index: 1;
pointer-events: none;
+
+ @include media-desk {
+ top: -100px;
+ bottom: -100px;
+ }
}
&::before {
@@ -37,7 +43,7 @@
// =========================================================================
&-embla {
- overflow: hidden;
+ overflow-x: clip;
}
&-container {
diff --git a/themes/shared/layouts/_default/sitemap.xml b/themes/shared/layouts/_default/sitemap.xml
index e4732e4c..481867f9 100644
--- a/themes/shared/layouts/_default/sitemap.xml
+++ b/themes/shared/layouts/_default/sitemap.xml
@@ -1,7 +1,7 @@
{{ printf "" | safeHTML }}
{{ range .Data.Pages }}
- {{- if and (.Permalink) (not .Params.private) -}}
+ {{- if and (.Permalink) (not .Params.private) (ne .Params.build.render "never") -}}
{{ .Permalink }}{{ if or (eq .Sitemap.Priority 1.0) (not .Lastmod.IsZero) }}
{{ 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 }}{{ end }} {{ with .Sitemap.ChangeFreq }}