Skip to content
Binary file added content/blog/dyn-compatibility/social.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/blog/named-arguments-at-home/social.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions content/mentorship/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ aliases = ["pro"]
<header class="pro-hero">
<div class="pro-hero-content">
<h1 class="pro-hero-title">
<span class="highlight">Build, Review,</span><br />
<span class="highlight">Write, Review,</span><br />
<span class="highlight">and Ship Better Rust</span>
</h1>
<p class="pro-hero-subtitle">
For experienced engineers moving from Python, Go, or another language into serious Rust work. Bring your project or codebase and build the judgment to make sound design, architecture, and code-review decisions yourself.
For experienced engineers moving from Python, Go, or another language into serious Rust work. Bring your project or codebase and learn how to make sound design, architecture, and code-review decisions yourself.
</p>

<div class="pro-hero-cta">
Expand Down Expand Up @@ -57,7 +57,7 @@ For experienced engineers moving from Python, Go, or another language into serio
I've worked with Rust since 2015 and have consulted professionally since 2020. I help people get from prototype to production in Rust.
</p>
<p class="pro-section-subtitle pro-subtitle-wide">
I believe the best way to build Rust expertise is by working through real code together. I ask questions and help you understand and own design trade-offs.
I believe the best way to build Rust expertise is by working through real problems with an experienced mentor. I ask the right questions, so you can build the right mental model.
</p>
<p class="pro-section-subtitle pro-subtitle-wide">
I host the <a href="/podcast">Rust in Production Podcast</a>, where I've had more than 50 conversations with engineers and technical leaders about how Rust works in real organizations. You can also watch my <a href="https://www.youtube.com/watch?v=aZ5sfhGmEVU" target="_blank" rel="noopener">CodeCrafters teaching session</a> or read my <a href="/blog">articles on idiomatic and maintainable Rust</a>.
Expand Down Expand Up @@ -103,7 +103,7 @@ I host the <a href="/podcast">Rust in Production Podcast</a>, where I've had mor
<h3>Recognize <span class="highlight">Good Rust</span></h3>
<p>Bring a design you are unsure about, code you need to review, or a project you want to ship. We compare alternatives and make the trade-offs explicit.</p>
<img src="/mentorship/ferris-master.png" alt="Ferris the Crab as a Wizard" class="pro-value-image" />
<p>You leave with clearer mental models and concrete next steps. The goal is for you to handle the implementation.</p>
<p>You leave with a clearer understanding and concrete next steps. The goal is for you to handle the implementation.</p>
</article>

<article class="pro-value-item">
Expand Down Expand Up @@ -229,7 +229,7 @@ I host the <a href="/podcast">Rust in Production Podcast</a>, where I've had mor
</section>

<section class="pro-section">
<div class="pro-container">
<div class="faq-container">
<h2 class="pro-section-title">Frequently Asked Questions</h2>

{% <faq> %}
Expand Down
27 changes: 16 additions & 11 deletions content/services/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,24 @@ I'll help you navigate the Rust crate ecosystem, systems architecture, code revi

## Why LLMs Alone Are Not Enough

LLMs have limitations around the deeper architectural decisions that make or break a Rust codebase:
LLMs have limitations around the deeper architectural decisions that make Rust great:

- Domain modeling: turning business logic into types the compiler enforces.
- Type-driven design: making illegal states unrepresentable to prevent entire categories of bugs.
- API and architecture review: shaping the boundaries between modules, crates, and services so the codebase stays maintainable as it grows.
- Idiomatic Rust: when to use traits and lifetimes, and when to avoid them; how to structure async code to separate I/O-heavy code from simple business logic that can be sync.
- Testing: how to use unit tests for quick feedback loops where other teams might rely on costly end-to-end tests, which are slow.

If you're shipping Rust into production, this is the layer that decides whether the codebase is a joy to work with in two years, or a liability nobody understands or wants to touch.
If you're shipping Rust into production, this is the difference between a codebase that is a joy to work with in two years and a liability nobody understands or wants to touch.

## You Stay In Control With The Right Guardrails

You're probably already using LLMs to write Rust. The question is whether the output is something you'd be proud to ship, or something you'll be paying down for years.
I believe the earlier you involve an expert, the more confident you will feel about the way your Rust project is evolving, and the better automated code generation will work for you because it has reliable guardrails to operate within.
You're probably already using LLMs to write Rust and that is fine.
But I believe the earlier you involve an expert, the more confident you will feel about the way your Rust project is evolving, and the better automated code generation will work for you because it has reliable guardrails to operate within.

Rust is one of the best languages in the world for working with AI-assisted coding because of its strict compiler, but that only works if the surrounding scaffolding is set up well.

I help teams put that scaffolding in place with type-driven design, solid continuous integration, a fast test harness, and review workflows that scale when most of the code is machine-generated. I also coach engineers on how to drive the AI instead of babysitting it, so your team ships faster *and* the code stays yours.

The goal is simple: you stay in control of your codebase and can decide for yourself how much or how little you want to use agents for code generation.
I help teams put that scaffolding in place with type-driven design, solid continuous integration, a fast test harness, and reliable review workflows. I also coach engineers on how to use agents, so your team ships faster *and* stays in control.

{% <info title="Feedback From Happy Customers" icon="heart"> %}

Expand Down Expand Up @@ -164,7 +162,9 @@ From time to time I give talks about Rust and open-source software.
- [View Previous Talks →](https://endler.dev/talks/)


## Happy To Answer Your Questions
<section class="faq-panel skew-top" aria-labelledby="happy-to-answer-your-questions">
<div class="faq-container">
<h2 id="happy-to-answer-your-questions">Happy To Answer Your Questions</h2>

{% <faq> %}
[
Expand Down Expand Up @@ -247,15 +247,20 @@ From time to time I give talks about Rust and open-source software.
]
{% </faq> %}

</div>
</section>

<section class="consultation-cta">

## Accelerate Your Team's Rust Adoption Today

<div style="display: flex; align-items: center; justify-content: left; flex-direction: row; gap: 10px;">
<div class="consultation-cta-actions">
<a class="cta-button" data-cal-link="corrode/chat" data-cal-namespace="chat" data-cal-config='{"layout":"month_view"}'>Schedule A Free Consultation</a>
<p>
or email me at <a href="mailto:hi@corrode.dev">hi@corrode.dev</a>.
</p>
</div>

</div>
</section>

<script type="text/javascript">
(function (C, A, L) { let p = function (a, ar) { a.q.push(ar); }; let d = C.document; C.Cal = C.Cal || function () { let cal = C.Cal; let ar = arguments; if (!cal.loaded) { cal.ns = {}; cal.q = cal.q || []; d.head.appendChild(d.createElement("script")).src = A; cal.loaded = true; } if (ar[0] === L) { const api = function () { p(api, arguments); }; const namespace = ar[1]; api.q = api.q || []; if(typeof namespace === "string"){cal.ns[namespace] = cal.ns[namespace] || api;p(cal.ns[namespace], ar);p(cal, ["initNamespace", namespace]);} else p(cal, ar); return;} p(cal, ar); }; })(window, "https://app.cal.com/embed/embed.js", "init");
Expand Down
125 changes: 27 additions & 98 deletions sass/_article.scss
Original file line number Diff line number Diff line change
Expand Up @@ -332,87 +332,6 @@ article {
font-style: italic;
}

.newsletter-callout {
width: 110%;
margin-left: -5%;
padding: 3em;
margin-top: 4em;
border-radius: 4px;
background-color: $darkBgrd;
color: $darkPrim;
}

#newsletter-subscription p,
#newsletter-subscription p b {
color: white;
}

.newsletter-success {
margin: 0;
font-size: 1.05em;
font-weight: 600;
line-height: 1.5;
color: $brightBgrd;
}

.newsletter-callout ul {
padding: 0;
list-style: none;
display: flex;
}

.newsletter-callout li {
display: flex;
align-items: center;
}

.newsletter-callout img {
display: block;
margin-right: 5px;
}

.newsletter-callout ul a {
display: flex;
align-items: center;
text-decoration: none;
color: inherit;
}

.newsletter-callout li:hover {
color: $brightScnd;
}

.newsletter-callout .postscript {
font-size: 0.9em;
margin-top: 1em;
}

.newsletter-callout form {
display: flex;
flex-direction: column;
gap: 1em;
}

.newsletter-callout input[type="email"] {
font-size: 1em;
padding: 0.8em;
border: none;
border-radius: 4px;
width: 100%;
color: $brightPrim;
}

.newsletter-callout input[type="submit"],
.newsletter-callout button[type="submit"] {
font-size: 1em;
padding: 0.8em;
border: none;
border-radius: 4px;
background-color: $brightScnd;
color: white;
cursor: pointer;
}

.social {
padding-top: 1em;
}
Expand Down Expand Up @@ -461,20 +380,6 @@ article {
max-width: 100%;
}

.newsletter-callout {
width: 100%;
margin-left: 0;
}

.newsletter-callout form {
flex-direction: column;
}

.newsletter-callout input[type="submit"],
.newsletter-callout button[type="submit"] {
width: 100%;
}

.social {
margin-top: 3em;
padding-top: 1em;
Expand All @@ -486,17 +391,41 @@ article {
background-color: $brightScndLight;
}

.article-content-with-resources {
padding-bottom: 5em;
}

.article-footer {
max-width: 800px;
margin: 0px auto;
padding: 1em;
padding: 1em 1em 7em;
background-color: $brightBgrd;

&.skew-top {
padding-top: 6em;
}

&.skew-top-reverse::before {
transform: skewY(1deg);
}
}

.article-footer-inner {
max-width: 768px;
margin: 0 auto;
}

.article-resources > h2 {
margin-top: 0;
}

.editor-credits {
font-size: 0.8em;
}

@media (prefers-color-scheme: dark) {
.article-footer {
background-color: $heroDark;
}

.article-content-wrapper {
background-color: $darkBgrd;
}
Expand Down
11 changes: 1 addition & 10 deletions sass/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ h2 {
}

// Section headings share one treatment; navigation and embedded UI keep theirs.
h2:where(:not(.list-row-title, .subheading, .footer h2, .footer-newsletter-copy h2, .quiz-container h2)) {
h2:where(:not(.list-row-title, .subheading, .footer h2, .quiz-container h2)) {
margin-top: 48px;
margin-bottom: 22px;
padding: 0;
Expand Down Expand Up @@ -233,11 +233,6 @@ img.hero-img {
}
}

.hero-headline {
font-size: 2.8em;
margin-bottom: 0px;
}

a {
color: $brightPrim;
text-decoration: underline;
Expand Down Expand Up @@ -648,10 +643,6 @@ hr {
}

@media (max-width: 900px) {
.hero-headline {
font-size: 2.5em;
}

img.hero {
width: 100%;
}
Expand Down
4 changes: 4 additions & 0 deletions sass/_blog.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.blog-overview .article-content-wrapper {
padding-bottom: 7em;
}

.blog-filters {
margin-bottom: 2.5rem;
display: flex;
Expand Down
31 changes: 30 additions & 1 deletion sass/_faq.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
.faq-container,
.faq-section {
width: 100%;
max-width: 800px;
margin: 2rem auto;
margin-inline: auto;
}

.faq-section {
margin-block: 2rem;
}

.faq-panel.skew-top {
width: 100vw;
margin-top: 5em;
margin-bottom: 0;
margin-inline: calc(50% - 50vw);
padding: 5em 1rem 4em;
background-color: $darkBgrdDeep;

&::before {
transform: skewY(-1deg);
}

h2 {
margin-top: 0;
color: white;
}
}

.article-content-wrapper:has(.faq-panel) {
padding-bottom: 0;
}


.faq-item {
border-radius: 8px;
margin-bottom: 1rem;
Expand Down
Loading
Loading