
Second deep-dive in a series about maintaining and developing a React Native app in production.
Part 2: Grafting In TDD Into a Legacy React Native Codebase
Questions or improvements? Open an issue on the repo or e-mail me.
Writing about technology, software engineering, the craft, and coding

Second deep-dive in a series about maintaining and developing a React Native app in production.
Questions or improvements? Open an issue on the repo or e-mail me.
Original version was published in October 2025, updated: January 2026
This is a system design document for a Microsoft Teams bot that replaces JIRA’s clunky worklog UI with a single-view Adaptive Card interface.
This is a complete system design for a Teams bot that solves the weekly pain of JIRA time reporting:
Estimated reading time: 20-25 minutes
The document includes the actual Adaptive Card JSON structure, sequence diagrams, data models, and a mathematical load simulation proving that a single Lambda function handles the Friday afternoon spike comfortably.
Questions or improvements? Open an issue on the repo or e-mail me.
This is a technical post-mortem analyzing constraint-driven development with AI coding assistants.
Building a Route Optimization Engine in 4.5 Hours: An LLM-Assisted Hackathon Post-Mortem
This is a detailed analysis of building production-grade code under time constraints:
Estimated reading time: 15-20 minutes
The document includes the actual constraint prompt we used, architectural decisions with reasoning, and specific examples of where the LLM excelled (API integration) and where it failed (domain knowledge, architectural vision).
Questions or improvements? Open an issue on the repo or e-mail me.
This is a comprehensive, step-by-step guide for deploying containerized services to Amazon EKS. You’ll learn how to:
A Complete Guide to Deploying a Service to AWS EKS
This is a comprehensive, production-ready deployment guide covering:
– Infrastructure provisioning with Terraform
– Container builds and ECR push with GitHub Actions
– Kubernetes deployments with Helm
– IAM Roles for Service Accounts (IRSA) configuration
– Complete troubleshooting section
Estimated time: 2-3 hours first time, ~30 minutes after that.
The guide includes complete working examples – not snippets, but full Terraform modules, Helm charts, and GitHub Actions workflows you can adapt.
*Questions or improvements? Open an issue on the repo or message me on LinkedIn.*
While working with Docker builds, you may already be familiar with building images and creating containers:
$ docker build --build-arg FOO=BAR FOUX=BARS -t my-docker-image:latest .
$ docker run -d -p 8088:8080 my-docker-image
This would build and create a container for the following Dockerfile:
FROM node:20-slim AS builder
WORKDIR /app
COPY . .
RUN yarn install --immutable --immutable-cache --check-cache
RUN yarn build:prod
FROM builder AS test
RUN yarn test:integration
FROM node:20-slim AS final
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/yarn.lock ./yarn.lock
RUN yarn install --production --frozen-lockfile
ENTRYPOINT ["node", "./dist/src/server.js"]
Enter the --target flag:
$ docker build --target=test -t my-api:test .
The --target flag will build the Dockerfile from the top to the specified stage, and then stop — skipping any further layers like the final production image. This is ideal when you only want to run tests in a CI/CD pipeline without building the full image.
- name: Build Docker image for testing
run: docker build --target=test -t my-api:test .
- name: Run integration tests in container
run: docker run --rm my-api:test
Context
Was neck-deep in CORS errors logging this week.
This came out of necessity — browser errors were vague, Nomad made it hard to inspect logs, and I needed better observability yesterday. So I wired it all up using winston, express-winston, and a few custom formatters. Added rate limiting and context enrichment. Removed all rogue console.log()s. Now logs feel like a dashboard I can trust.
Still not across the finish line with CORS, but now I know exactly where the requests fail. Which is more than I could say a day ago.
CORS errors in browser environments are notoriously opaque. Hosted behind Nomad, we struggled to get visibility into:
const container = new winston.Container();
container.add('cors', { /* ... */ });
container.add('frontend', { /* ... */ });
container.add('app', { /* ... */ });
container.add('http', { /* ... */ });
export const cors = container.get('cors');
export const frontend = container.get('frontend');
export const app = container.get('app');
export const http = container.get('http');
Each logger uses a scoped prefix ([CORS], [FRONTEND], etc.), with consistent formatting, timestamps, and custom verbosity levels.
POST /log Receives payloads like:
{
level: 'error',
message: 'Error when logging in',
stack: 'AxiosError: ...',
context: { data: ‘some data’, context: 'LoginPage' },
userAgent: navigator.userAgent
}
This hits a backend controller that parses the error and logs it via the [FRONTEND] logger.
No auth required, but it’s behind rate limiting and scoped CORS.
A dedicated CORS logger tracks preflight behavior, incoming origins, and request flow.
app.use((req, res, next) => {
cors.info(`Trust Proxy? ${app.get('trust proxy')}`);
cors.info(`IP: ${req.ip}`);
cors.info(`Origin: ${req.headers.origin}`);
next();
});
After .use(corsMiddleware), we also log:
app.use((req, res, next) => {
cors.debug(`Passed CORS for ${req.method} ${req.originalUrl}`);
next();
});
[RICH-HTTP] logs track all route hits, timings, and status codes, feeding into morganMiddleware and expressWinston.logger.
const morganMiddleware = morgan(
':method :url :status :res[content-length] - :response-time ms',
{ stream: { write: msg => http.http(msg.trim()) } },
);
Critically tuned!
app.set('trust proxy', true);
app.use(express.json());
// Log CORS setup
app.use(corsLoggerMiddleware); // Trust, IP, Origin
app.options(/^\/.*$/, corsMiddleware);
app.use(corsMiddleware);
app.use(corsPassThroughLogger); // Logs which paths passed CORS
// Frontend error logger endpoint
app.post('/log', frontendLoggerController);
// HTTP & diagnostics routes
app.use(appLogger);
app.use(v1Router);
app.use(v2Router);
2025-06-26 21:53:18 [CORS] DEBUG: Passed CORS for POST /log
2025-06-26 21:53:18 [FRONTEND] DEBUG: Error when logging in
Stack: AxiosError: Request failed with status code 404
at settle (...)
UserAgent: Mozilla/5.0 (...)
Context: {
"data": "some data",
"context": "LoginPage"
}
2025-06-26 21:53:18 [RICH-HTTP] INFO: POST /log 204 3ms
With this logging setup in place and after a lot more investigation, we figured out that the load balancer was rejecting client requests because a header wasn’t in the load balancer’s allowed headers list.
A quick refactor of the client request in the FE fixed the CORS problem and we finally saw client requests in Nomad logs. Yeehaw!
The logging infrastructure is finally exactly where I want it:
✅ Server-side logs with clearly scoped loggers ([CORS], [APP], [FRONTEND], [RICH-HTTP])
✅ Timestamps, request info, and stack traces — all structured, readable, and consistent
✅ A dedicated endpoint for piping frontend issues to the backend, with user context + user agent

This is a first in a (possibly!) running series about maintaining and developing a React Native app in production.
Questions or improvements? Open an issue on the repo or e-mail me.