Hey! Before we dive into login screens and token refresh logic, I want to take a step back and shine a light on something that rarely gets the attention it deserves: the supporting packages.
- They don't flash UI.
- They don't talk HTTP. But they are everything that makes the rest of the app possible.
But first, a confession.
I did something bold. Brave. Maybe even a little impulsive.
I subscribed to Cursor Pro
Yes, I paid actual money. And I have zero regrets.
Why? Because coding with Cursor feels less like using a tool and more like pairing with a genius friend who never gets tired, judges my bad naming only silently, and finishes my half-baked ideas without drama X)).
It's not just about giving it prompts. It's about building vibes. You teach Cursor your coding rituals, your quirks, your "I know it's ugly but it works" logic. And wow! it adapts. It's like a teammate that reads your mind, writes tests, and never asks for coffee breaks.
The Foundation: Packages
Before we get fancy with login forms and token flows, let's appreciate the "boring yet essential" stuff: the packages. The heroes of app that quietly hold everything together without complaining.
Redis Adapter
This package wraps Redis operations. I didn't reinvent the wheel, just made it easier to test, swap, and inject (like a good dependency should). The idea is simple: don't scatter redisClient.Set(...)
all over your app.
# Redis Adapter Rule
The `redis` package provides an adapter that wraps the `github.com/go-redis/redis/v8` library, offering a simplified and type-safe API for common Redis operations.
## Purpose
- Abstract away direct usage of the go-redis client
- Provide a reusable, testable, and idiomatic interface for Redis operations
- Enable easy mocking and extension for testing and future enhancements
Token Provider
This one powers the generation, validation, and parsing. Both access and refresh tokens. I use a TokenSubject enum to keep things clean (AccessTokenSubject, RefreshTokenSubject, etc).
I also introduced something fun: LinkedToken. It embeds the refresh token ID inside the access token's claim. This way, revoking both tokens becomes possible even when all you have is the access token, neat, right?
Error
In this app, I separate internal errors (think: Redis down, token parsing failed) from business errors (like "wrong credentials").
How?
- Internal errors are wrapped with my beloved stackerror package. They bubble up with stack traces and observability in mind.
- Business errors are returned as value objects and interpreted at the presentation layer.
This separation lets me write usecases that don't care about HTTP status codes, they just speak in errors, and the HTTP handler translates.
It's like a translator for angry backend logic.
Bonus: Cursor Rule Files Are a Superpower
With Cursor, I rely heavily on .mdc files to establish patterns and expectations.
For example:
# Convention
All packages under /pkg must expose clear interfaces and avoid coupling with HTTP or Echo
# Rule
Business errors are never returned as HTTP errors from usecases
It's not just prompting, it's like training your AI teammate on your architectural beliefs.
That's it for today!
Authentication is coming next, but I hope showing the invisible infrastructure was helpful. If you've ever wondered how to structure pkg in a scalable Go backend, or want to make AI pair programming less chaotic, this is where I started.
Links, if you're curious
Next Up
We're diving into the juicy stuff: the authentication business module.
Think clean usecases, no HTTP nonsense, and logic that could survive a framework apocalypse.
We'll answer questions like:
What actually happens during a login?
How do refresh tokens work with Redis?
Can you TOTP your way into greatness?
Stay tuned, the domain is strong with this one
Top comments (0)