Four Hard Truths No One Told Me About Launching My First Book

Last month, I launched Street-Smart Coding, my first “official” book. It felt exciting and terrifying.

I had already written books, but I didn’t call them that. I thought only traditionally published works counted. And I didn’t know about writing mini-books. I had to change my mind about the concept of a book.

Here are 4 realizations I’ve had after launching it:

#1. The real work starts when you write the last words of your first draft. Editing, designing, launching, and promoting, that’s 80% of the work after the draft.

#2. Once your book is out, the game is in your mind. Waking up to see sales notifications is so satisfying. But silence is draining. I kept refreshing the sales dashboard, asking: “Why isn’t it selling? Is it me, the sales page, or the price?” The inner voice speaks louder than your wins.

The other day, Ryan Holiday, a New York Times best-selling author, shared that as soon as he finishes a book, he focuses on what he can control: working on the next. Now I see why.

#3. It’s easy to fall into the comparison trap online. These days, Gregory Orosz, the guy behind The Pragmatic Engineer, shared an update on his book The Software Engineer’s Guidebook after one year of launch. He shared sales figures. My first thought: I’m far from those numbers. But he admitted that his book is an outlier. Comparison is the thief of joy.

#4. If someone outside your circle buys your book, it’s already a win. That’s a line I found the other day scrolling on r/writing. It’s an anchor to put our feet back on the ground. By that definition, my book is already a success. And I already passed the $1 test.

Friday Links: Single-letter names, Windows 11, and optimization

Hey there.

Here are 4 links I thought were worth sharing this week:

#1. This week, another major Internet outage. This time at Cloudflare. It raises the question: do we really need Cloudflare? (2min).

#2. Maybe it’s time to migrate to GNU/Linux. Because Windows 11 is adding an AI agent (8min) with access to personal folders.

#3. Imagine all the trouble you’ll face online if you had a single-letter name (6min). Airlines won’t sell you a ticket, and another name won’t match your passport. Keep this in mind next time you’re working on validating web forms.

#4. Faster code isn’t always better. Working at a startup makes you optimize your code for different things (2min).


And in case you missed it, I wrote on my blog about some hard truths about coding they don’t teach you (2min) and the skill that took my career further than anything else (2min).


(Bzzz…Radio voice) This email was brought to you by… Street-Smart Coding: 30 lessons to help you code like a pro, from Googling to clear communication. It’s the roadmap I wish I had moving from junior to senior and the one I hope helps you too.

See you next time,

Cesar

Want to receive an email with curated links like these? Get 4 more delivered straight to your inbox every Friday. Don’t miss out on next week’s links. Subscribe to my Friday Links here.

Hard Truths About Coding They Don't Teach You (Part 2)

I was about to start a new list from scratch. But I remembered I already wrote about some hard truths about coding.

Here are five more truths:

#1. Most of your day will be in meetings, not coding.

#2. You won’t be building systems from scratch. Most of the time, you’ll be maintaining and rewriting legacy systems.

#3. Communication skills, not more languages, will take you further. Just asking the right questions will make you stand out.

#4. You will have to learn a lot of subjects. Don’t try to learn them all at once. Get your feet wet in many areas, then stick to a few. The learning phase never ends.

#5. At some point, you’ll realize end users and business owners don’t care about code. It’s a tough lesson. You won’t like it, but it changes how you see coding.

Junior me focused on mastering syntax and forgot about problem-solving, communication, and collaboration. That’s why I wrote the book I wish I had on day one, Street-Smart Coding: 30 Ways to Get Better at Coding. Because coding is more than syntax and typing symbols fast.

Get your copy of Street-Smart Coding here

The Skill That Took My Career Further Than Anything Else

As a junior coder, I made the mistake of only focusing on mastering syntax.

I thought we were artists writing code to frame in a museum. But we write code to solve problems. Even the code you write for fun solves a problem: boredom and curiosity.

If you don’t experience your code firsthand, put yourself into your end user’s shoes. Think about their problem, why they’d pay, and how your code solves it.

A sense of curiosity, desire to learn, and inspiring mentors helped me grow. But nothing compares to product thinking: imagining being a product owner who codes. That’s the most valuable skill.

I wish someone had told me that earlier. As a junior coder, I ignored product thinking, teamwork, and clear communication. Those skills make us stand out as coders. And that’s why I wrote Street-Smart Coding: 30 Ways to Get Better at Coding, the guide to the lessons I wish I’d known from day one.

If you want to grow faster, grab your copy of Street-Smart Coding here

BugOfTheDay: Blazor Input Control Won't Turn Red

In another episode of Adventures with Blazor, I ran into a sneaky bug with custom input validation.

This time I had an input control to enter sizes and lengths in either inches or millimeters based on a flag per client. When the bound value was missing, the border didn’t turn red.

Here’s a form using a custom MeasurementInput,

@* MyCoolForm.razor *@
<EditForm Model="MyCoolRequest" OnValidSubmit="OnValidSubmit">
	<DataAnnotationsValidator />
	<ValidationSummary />

	<div class="row">
		<div class="col-sm-3">
			<label for="length" class="form-label">Length</label>
			<MeasurementInput id="length" @bind-Value="MyCoolRequest.Length" class="form-control" />
			@* ^^^^^ *@
			@* A custom input. Notice the class attribute *@
			<ValidationMessage For="() => MyCoolRequest.Length" class="invalid-feedback" />
		</div>
	</div>

	<button type="submit" class="btn btn-primary">@SubmitButtonText</button>
</EditForm>

And here’s the actual MeasurementInput,

@* MeasurementInput.razor *@
@inherits InputBase<Measurement>

<input class="@CssClass" @attributes="AdditionalAttributes" @bind="CurrentValueAsString" type="text" />
@*     ^^^^^ *@
@* Notice the class attribute here *@

@code
{
    [Parameter]
    public bool? ShouldUseInches { get; set; } = true;

    protected override string? FormatValueAsString(Measurement? value)
    {
        // Format as inches or millimeters
    }

    protected override bool TryParseValueFromString(string? value, out Measurement? result, [NotNullWhen(false)] out string? validationErrorMessage)
    {
        // Validate and parse from inches or millimeters
    }
}

After hours of debugging, I found the input style never applied the is-invalid class.

The fix? Two lines of code changed,

-<input class="@CssClass" @attributes="AdditionalAttributes" @bind="CurrentValueAsString" type="text" />
+<input class="form-control @CssClass" @attributes="AdditionalAttributes" @bind="CurrentValueAsString" type="text" />
-<MeasurementInput id="length" @bind-Value="MyCoolRequest.Length" class="form-control" />
+<MeasurementInput id="length" @bind-Value="MyCoolRequest.Length" />

Two class attributes: one in the input, one in the form. Arrggg! A full day lost to two lines of code. Source.

This tiny bug reminded me that coding isn’t just about syntax. It’s about searching, finding answers, and asking for help.

Even with AI, those skills remain essential for new coders. That’s why I start my book, Street-Smart Coding: 30 Ways to Get Better at Coding, with them. It’s the practical guide I wish I had on my journey from junior to senior.

Get your copy of Street-Smart Coding here