Compare commits
20 Commits
73f1289e25
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3dee555c5c | |||
| 8fe9bd28dd | |||
| f52263238e | |||
| 0f21bfc3fd | |||
| 2566414e47 | |||
| 0c885d0b32 | |||
| 2aee377e54 | |||
| f486aa58c3 | |||
| 4495eab334 | |||
| 61f615c1d5 | |||
| 4a7161b102 | |||
| 618bfb2e14 | |||
| 147b96fcb0 | |||
| 67e3155518 | |||
| b3a2e00a7b | |||
| b7cc066956 | |||
| 435c5c7847 | |||
| bc04cbfc54 | |||
| 7f2025875b | |||
| 3d689aa9af |
@ -3,27 +3,56 @@ title = 'Home'
|
|||||||
date = 2023-11-14T17:55:14Z
|
date = 2023-11-14T17:55:14Z
|
||||||
+++
|
+++
|
||||||
|
|
||||||
# Hi, I'm John
|
# Hi, I'm John Costa
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
I am a Software Engineer, currently working at Decipad. I'm interested in various subjects including: Compilers, Linux Servers, Web Development, Distributed System and many more.
|
# About Me
|
||||||
|
I'm a Software Engineer currently working at [Requesty](https://requesty.ai). I do full-stack products, host my own services under my desk, solve coding problems and love to read.
|
||||||
|
|
||||||
|
Read my website on your terminal `ssh -p 23234 blog.johncosta.tech`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# My Projects
|
||||||
|
## [Haystack](https://www.youtube.com/watch?v=tPOEJewdj8Y)
|
||||||
|
A tool that uses AI agents to extract information from images, screenshots or pictures. It then creates entities such as locations, events, notes, etc... and gives the user an easy way to search for them. Currently this is in Alpha stage, if you'd like access you can [email me](mailto:me@johncosta.tech).
|
||||||
|
## [Converge](https://converge.sh)
|
||||||
|
A simple website that allows users to list their links, and share them in person using a QR code. Similar to linktree but intended to be used in face-to-face meetings. You can see my profile [here](https://converge.sh/1).
|
||||||
|
|
||||||
|
## [Hybrid Poker](https://github.com/JohnCosta27/Poker)
|
||||||
|
This project has two parts.
|
||||||
|
1. Poker hand evaluator and game loop. I used Zig's [comptime](https://zig.guide/language-basics/comptime/) to generate arrays that allow any poker hand to be evaluated in O(logn), with potential to expand to a O(1) evaluation, the algorithm is based on [Cactus Kev](https://zig.guide/language-basics/comptime/).
|
||||||
|
2. Live playing. The idea behind the project is to allow my friends and I to play poker whilst some of us are together in a room, and some of us are away. I've setup a deck with NFC tags which the dealer uses so the program knows which player has which cards. At the end all the hands are saved and can be replayed.
|
||||||
|
|
||||||
|
## [Arcio](https://github.com/arcio-uk)
|
||||||
|
A management information system (MIS) to help schools and universities mark attendance, manage timetables and organise courses. I worked on this project with 3 other engineers and even trialled it at our university - Royal Holloway. Although the project works, we could not get funding from our university to continue the work. The code is now open source.
|
||||||
|
|
||||||
|
The system was capable of.
|
||||||
|
- Taking attendance of hundreds of students at the same time, and scale to meet demand.
|
||||||
|
- Manage courses, modules, tutors and students involved in each one.
|
||||||
|
|
||||||
|
You can find the rest of my projects on the [projects page](https://johncosta.tech/projects/).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Work
|
# Work
|
||||||
|
|
||||||
Currently working at [Decipad](https://www.decipad.com/) as a full stack engineer.
|
## [Requesty](https://requesty.ai) (2025-Current)
|
||||||
|
I was hired 6 months after the product launched, and joined the team as the 2nd hire. We are building an AI-Gateway to support application development and development teams, providing analytics, cost saving, fallbacks and lots of other interesting things! We are moving very quickly, and so far I've mostly worked on the gateway, building latency based policies, and many other improvements.
|
||||||
|
|
||||||
I worked in various project at my old university [Royal Holloway](https://www.royalholloway.ac.uk/), including a Wellness and Professional Development application, that allowed students to track their wellbeing and various professional skills.
|
## [Decipad](https://decipad.com) (2022-2025)
|
||||||
|
I worked as a full-stack software engineer at Decipad. I was the lead developer for our interactive notebook, that allows users to build models with interactive widgets, rich text, calculations and tables. The editor also supports live-collaboration, multiple tabs and offline editing.
|
||||||
|
|
||||||
Worked on a [InnovateUK](https://www.ukri.org/councils/innovate-uk/) funded project called Tensorcrypt, which allowed for zero-trust data analysis.
|
I've also been responsible for refactoring various parts of the code base. I migrated our old create-react-app frontend to a more modern Vite + Rollup (with SWC), this allowed our developers to have instant updates instead of having to wait 10-15s for their changes to have effect. Furthermore I implemented type generation on our GraphQL server, which reduced backend bugs by 90%.
|
||||||
|
|
||||||
I am also a private GCSE/A-level Maths and Computer Science tutor, and have over 300 hours of tutoring experience.
|
Before leaving, I was working on augmenting our notebooks with a chat, and BigQuery integrations (which we call data lake). This allows users to bring their own data, which we then sync to BigQuery every day, and allow the AI to interact with it.
|
||||||
|
|
||||||
---
|
## [Lead Engineer at Codegroovers](https://www.royalholloway.ac.uk/research-and-education/departments-and-schools/computer-science/news/one-year-of-code-groovers/)
|
||||||
|
I was hired to lead the build a proof of concept system for the universities well-being team. This system allowed students to view all the universities well-being resources in one place, allowed them to keep track of their mental health, and provided charts for measuring progress. It also had a professional development part which allowed users to explore their future careers. You can find the code [here](https://github.com/JohnCosta27/WellbeingApp).
|
||||||
|
|
||||||
# Projects
|
## Private Tutor
|
||||||
|
Since 2019 I've been a private tutor, providing GCSE and A-level lessons in both Maths and Computer Science. I've done over 300 hours of lessons, all my students have achieved an A or above (7 for GCSE grades).
|
||||||
I've developed various projects, which I have listed on the [projects]({{< relref "./projects/_index.md" >}}) page. There you will find blog posts, GitHub Repos and _maybe_ a YouTube video.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -32,11 +61,3 @@ I've developed various projects, which I have listed on the [projects]({{< relre
|
|||||||
I attended [Royal Holloway](https://www.royalholloway.ac.uk/) and achieved a First Class Honours BSc Computer Science.
|
I attended [Royal Holloway](https://www.royalholloway.ac.uk/) and achieved a First Class Honours BSc Computer Science.
|
||||||
|
|
||||||
Previously I attended [Farnborough Sixth Form College](https://farnborough.ac.uk/) and got 5 A-levels.
|
Previously I attended [Farnborough Sixth Form College](https://farnborough.ac.uk/) and got 5 A-levels.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Interests
|
|
||||||
|
|
||||||
Outside of Computer Science, I play guitar (mostly metal), read and do Judo (currently a Red Belt). But I spent most of my time behind a screen, tinkering with software, or [ricing](https://excaliburzero.gitbooks.io/an-introduction-to-linux-ricing/content/ricing.html) my machine (again).
|
|
||||||
|
|
||||||
I like to take part in the [Advent Of Code](https://adventofcode.com/), and have various repo's for each years solutions.
|
|
||||||
|
|||||||
163
content/blog/How I deal with REST APIs.md
Normal file
163
content/blog/How I deal with REST APIs.md
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
+++
|
||||||
|
title = "Keeping it safe and simple. My preferred way to verify API requests in the frontend"
|
||||||
|
date = "2025-08-18"
|
||||||
|
author = "John Costa"
|
||||||
|
toc = true
|
||||||
|
tags = ["Software"]
|
||||||
|
+++
|
||||||
|
|
||||||
|
The challenge of keeping backend APIs and frontend applications in sync has been around for a while, and there are many different solutions from this problem.
|
||||||
|
|
||||||
|
The simplest one is to ignore it completely. Look at what the API returns, and use those values in the frontend without any sort of parsing or validation. This works, for a time. Eventually, the API will change, and if you're lucky it will change in a big way, making it obvious that you are no longer in sync. But if you are unlucky, it will change in a small, miniscule way, that will lead you down hour long debugging sessions for some weird, undefined behaviour. I don't recommend this approach, unless you have complete control over both, and even then, this is one small human error away from being a nightmare.
|
||||||
|
|
||||||
|
An extension to this approach would be have your backend API fit an OpenAPI schema, which makes it easy for tools to generate the types, and potentially validators (which we'll get onto later), for your API. This approach is good, but it involves some level of maintenance for compliance with the OpenAPI schema, and also external tools to generate code for you. However, I would actually recommend this approach under certain scenarios.
|
||||||
|
|
||||||
|
The other approaches I see are more complicated. They involve standardising the API in some way, this is where GraphQL would come in. The frontend asks for the data, and if the data is not returned in the expected way (types and all), then you will get an error. The experience of developing with this approach are good, for the frontend developer (to an extend). But it involves changing your API completely, potentially making it much harder to develop, harder to maintain, less performant, and overly complicated.
|
||||||
|
|
||||||
|
Another similar approach is the use of tools such as tRPC. It's somewhat similar to GraphQL, but it is TypeScript specific. This probably has the best developer experience if you're working with TypeScript only. But again, you're changing the backend again to fix the problems of the frontend, not to mention you are restricted to using TypeScript on the backend. There are other tools or standards, such as gRPC, which would allow you to use this for any language, but again, you will have to make the API compliant.
|
||||||
|
|
||||||
|
## Parse the response
|
||||||
|
|
||||||
|
In my experience, guessing the types, will only get you so far. To have a good, scalable(ish) solution, which will save you countless hours debugging, you need to parse the response you get from the API. This is what GraphQL does, what tRPC does and plenty of other API standards do. But I don't want to use any of those, I want a simple REST API (and note, I'm using REST loosely here, I'm not referring to perfect REST standard APIs, just APIs that return some data when asked).
|
||||||
|
|
||||||
|
Instead of making the burden of maintenance on the backend side (like OpenAPI schemas), I shift it to the frontend, by writing validators which can look at a response, and tell me if anything changed, or if the response is correct.
|
||||||
|
|
||||||
|
The reason I like this approach is because it is simple. All I need is a basic validation library (such as Valibot, Zod, or any other), and write what I'm expecting the response to look like, and then parse it. Even better, now you have TypeScript types, that you know for sure are not lying to you. You also get integration testing, you can run all the requests from the backend and make sure the corresponding validators pass, and if not, then you know something changed in the API.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
We'll start off by writing a helper function `createEndpoint`, which allows me to define an API request, give it a schema, and have it handle the parsing for me.
|
||||||
|
|
||||||
|
I'll show the code section by section, and explain as we go along.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
||||||
|
```
|
||||||
|
|
||||||
|
This is an interesting part of the code. A recent project called `standard-schema`, has made it very easy to swap out what validator you would like to use. This means that my function can take a validator from Zod, Valibot or any of the other libraries which implement this interface. You don't even need this library to be in your dependencies, you could copy it straight from their website. Pretty neat.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type RequestFnWithSchema<T extends StandardSchemaV1, TFn extends (...args: any) => any> = {
|
||||||
|
fn: (...input: Parameters<TFn>) => Promise<StandardSchemaV1.InferOutput<T>>;
|
||||||
|
['~schema']: T
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createEndpoint = <T extends StandardSchemaV1, TFn extends (...args: any) => any>(
|
||||||
|
schema: T,
|
||||||
|
fn: TFn
|
||||||
|
): RequestFnWithSchema<T, TFn> => {
|
||||||
|
return {
|
||||||
|
fn: async (...input) => {
|
||||||
|
const res = await fn(...input);
|
||||||
|
|
||||||
|
const x = schema['~standard'].validate(res);
|
||||||
|
|
||||||
|
if (x instanceof Promise) {
|
||||||
|
throw new Error("unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x.issues != null) {
|
||||||
|
throw new Error(JSON.stringify(x.issues));
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.value;
|
||||||
|
},
|
||||||
|
"~schema": schema,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This method takes two parameters. The first is a schema, this is what your data looks like, the part that you have to write by hand. The second is the request function. This can be anything, but usually it's a simple function that returns a promise.
|
||||||
|
|
||||||
|
We return an object that contains the function to call, and also the schema it uses. This is most so we return a type rather than a function, because I don't want this to get mixed up with other simple functions that request data from the API, I want to make it distinct.
|
||||||
|
|
||||||
|
The callback function is first called with the correct arguments, we then take the schema and validate the response from the callback function, Make sure there's no issues and return the parsed value. This function will throw if there's an error, this is mostly to keep this example simple, but you can choose to return an error value instead, create your own Error class and throw that, whatever you want.
|
||||||
|
|
||||||
|
The return type for this function is `RequestFnWithSchema`, which is just a helper type, that returns a correctly inferred value, so you get nice TypeScript types on the other end.
|
||||||
|
|
||||||
|
Here's an example of how you would use this:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { array, object, string } from "valibot";
|
||||||
|
import { createEndpoint } from "./frontend";
|
||||||
|
|
||||||
|
const userSchema = array(object({
|
||||||
|
id: string(),
|
||||||
|
name: string(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const userEndpoint = createEndpoint(userSchema, async () => {
|
||||||
|
const response = await fetch("http://localhost:1234/users").then(r => r.json());
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
You can see now I am writing the schema using valibot. I then pass it over to the `createEndpoint` function, and a callback which takes no arguments and returns the JSON response (note that I am assuming the API always returns JSON or the fetch throws an error).
|
||||||
|
|
||||||
|
Like this, you now get a lovely typed request function, by doing `userEndpoint.fn`, TypeScript knows it doesn't need any arguments, and will use `userSchema` to infer the return type. And all the complexity of parsing the request is hidden inside `createEndpoint`.
|
||||||
|
|
||||||
|
You can pass in parameters as well, very simply.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const singleUser = object({
|
||||||
|
id: string(),
|
||||||
|
name: string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createUserEndpoint = createEndpoint(singleUser, async (params: { name: string }) => {
|
||||||
|
const response = await fetch("http://localhost:1234/users",
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(params)
|
||||||
|
}).then(r => r.json());
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## A little about validators
|
||||||
|
|
||||||
|
There is a small detail that is easy to overlook by looking at the code above. The `object` part of the schema hides away the fact that it does not perfectly match the object. Take a look at the following:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "id",
|
||||||
|
"name": "name"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is exactly what you expect to pass validation - and it does - but now take a look at this object.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "id",
|
||||||
|
"name": "name"
|
||||||
|
"surname": "surname"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Valibot (experience may differ with other libraries), the standard `object` validator removes extra fields. This is actually key for enabling migrations, which I'll talk about further down. To recap, this object passes validation, but the extra field is stripped away. So TypeScript is still telling the truth.
|
||||||
|
|
||||||
|
The validation fails when a field isn't present, or has an incorrect type. Such as:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": false,
|
||||||
|
"some-field": "not-name"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This fails. And Valibot is very useful at pointing out the errors, `id` is not of type string, and `name` is missing.
|
||||||
|
|
||||||
|
## What happens when the API changes. Development & Production.
|
||||||
|
|
||||||
|
Let's keep the user validator as an example. What happens when the API changes? And there are two scenarios where the schema you have on the frontend, does not match the response that your API does.
|
||||||
|
|
||||||
|
Number one, you're developing the backend API - or someone else has and hasn't changed the frontend schemas - and you validator crashes. But wait you're saying, the example above clearly shows that the extra fields are ignored, and therefore, potentially bugs can pass through. One more thing we can do to make development air tight, is to change the `object` to a `strictObject`. This way, there is no escaping that API change, the moment an extra field is added you will know about it, because your frontend will crash. This is very important to make sure that you get small and fast errors now, instead of bigger bugs which take you a while to figure out.
|
||||||
|
|
||||||
|
One very important thing is: we _only_ want this `strictObject` for development, because shipping it to production will mean that anyone with an out of date frontend (which happens a lot), their application will crash. The most common migration you make is adding fields, which is very easy with `object`, just add a field. If it's present but the validator doesn't see it, it will ignore it.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
This is a practical way to create types that you know are true. You can also be extra strict during development and flexible to allow for users with outdated clients still use the app. It's not perfect, but it is still my favourite way of validating on the frontend.
|
||||||
31
content/blog/Life recently.md
Normal file
31
content/blog/Life recently.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
+++
|
||||||
|
title = "Life, Recently."
|
||||||
|
date = "2025-06-21"
|
||||||
|
author = "John Costa"
|
||||||
|
toc = true
|
||||||
|
tags = ["life"]
|
||||||
|
+++
|
||||||
|
|
||||||
|
I have been going through an unusual period of unbusyness. Normally I tend to be quite busy, working my full-time job, working on side projects after, going to the gym in the morning and talking to friends some evenings, and the weekends tend to be much of the same, only that I work on side projects the majority of the day.
|
||||||
|
|
||||||
|
## So what has happened recently?
|
||||||
|
|
||||||
|
My work has slowed down quite a bit, I have also been on two holidays in one month, with 2 weeks in between, one to Scotland and one to Lisbon. Both were quite nice, and I managed to see a lot of both of these wonderful places. But this has meant that my last 4-6 weeks have been lacking a certain busyness I was used to.
|
||||||
|
|
||||||
|
This sounds great, doesn't it? Well... Yes. I recently watched 9 hours of TV in a single day, I don't remember ever doing that before. It felt _ok_, I'm glad I'm in a position where having such unproductive days doesn't hurt, but it does leave a sense of unnacomplishment (although this particular example I was somewhat proud of, in a weird way), this is something I have fought with for about a year now, and I'm starting to understand this feeling better.
|
||||||
|
|
||||||
|
I've learnt to appreciate this feeling, it pushes me to do _something_, it isn't something to fight, it is something to be grateful for. It pushes me to continue learning, continue working and push myself. It goes away once I've completed a good days work, when I've been to the gym, and when I've made a good, healthy meal.
|
||||||
|
|
||||||
|
## What about (remote) work?
|
||||||
|
|
||||||
|
Firstly, I will try and get back to a good state of bussyness, first and for most.
|
||||||
|
|
||||||
|
Secondly - although I am a big believer in remote work - I understand the need to leave the house. This is not some revolutionaty idea I have discovered, I've known that practically anyone who does remote work for a long time wants to leave the house. Maybe not for an office, but for a coffee shop, a co-working space, the park. Literally anywhere but their house (obviously from time to time).
|
||||||
|
|
||||||
|
So an action I will undertake is to try and leave the house everyday, and during weekdays I will try and work - at least 3 days - outside of my home office. This will mostly come in the form of going to a London office, in general I want to spend more time in London, as I always have fun and meet incredible people when I take the time to go to events, spend time at the pub, or simply working from the office. My mental health improves and so does my work.
|
||||||
|
|
||||||
|
However, the time I spend at home I also want to be better. The home office can be an incredibly productive space, and I want to keep it that way. I will come up with rules around using my phone near my desktop, about starting the day right when I am at home (waking up at the same time), and a few other baselines which I want to achieve. I might also write a blog post about these, more in detail.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
I'm somewhat unhappy with my current productivity. I feel like I am lagging behind, not keeping up with industry trends and much as I should - and most importantly - I am not programming enough.
|
||||||
61
content/blog/Taking Accountability.md
Normal file
61
content/blog/Taking Accountability.md
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
+++
|
||||||
|
title = "Taking Accountability"
|
||||||
|
tags = ["software"]
|
||||||
|
date = "2025-11-17"
|
||||||
|
author = "John Costa"
|
||||||
|
toc = true
|
||||||
|
+++
|
||||||
|
|
||||||
|
There is an interesting shift that happens when you transition from a _junior_ to a more senior level engineer (or any other career for that matter).
|
||||||
|
|
||||||
|
> Note: You've probably met 40 year old _juniors_ and 20 year old _seniors_, age has some correlation, but less than you'd expect.
|
||||||
|
|
||||||
|
I've had a self-driven approach to work for many years. I started my own company when I was just in my first year of uni. I was self employed for quite a few years (tutoring), and I've worked on multiple software projects with other people.
|
||||||
|
|
||||||
|
But work is different.
|
||||||
|
|
||||||
|
Back at [Decipad](https://github.com/decipad/decipad) (my first _real_ job), I was a junior. Sure, I knew how to code but did I know how to be an engineer? I didn't.
|
||||||
|
|
||||||
|
As months past I got very good at being self driven. From figuring out what the product needed, to discussing it with the team, to implementing it, to delivering it, to maintaining it. This is something I am very grateful for having the freedom to do when I was working here.
|
||||||
|
|
||||||
|
Now that I am at [Requesty](https://requesty.ai), I've had to relearn this.
|
||||||
|
|
||||||
|
## Everyone is a junior when they first join.
|
||||||
|
|
||||||
|
OK. Maybe that's not true but stay with me.
|
||||||
|
|
||||||
|
When you first join a software project, you don't really know what's going on. You don't fully understand the customers, you don't fully understand the product, and you certainly do not fully understand the code. So what can you do?
|
||||||
|
|
||||||
|
You can do tasks. And ask (many) questions.
|
||||||
|
|
||||||
|
You shouldn't be responsible for the full delivery of a brand new feature the moment you step foot through the door. Your job should be to learn as much as possible. Contributing will come.
|
||||||
|
|
||||||
|
## Take Accontability
|
||||||
|
|
||||||
|
When you're more established, you understand this new place a little better, then you need to turn your engineering brain fully on. You need to understand that you are not here to be a ticket crunching machine. You are an engineer!
|
||||||
|
|
||||||
|
What do I think an engineer (in a software company) is? Well, it's someone who writes the code, tests it, makes sure it goes into production without breaking other parts, makes sure it actually works, makes sure it was worth building in the first place, goes back to improve existing code and infrastucture, someone who can talk about the business requirements and the more abstract concepts surrounding the code they write (or tell an LLM to write).
|
||||||
|
|
||||||
|
The reason I'm writing this blog post is because this part is hard.
|
||||||
|
|
||||||
|
Writing code is many (maybe all?) engineers confortable place. We like writing our tests, watching the screen go green as we make them pass. We like taking some code and refactoring it to look nice and pretty. (At least I do).
|
||||||
|
|
||||||
|
But then what?
|
||||||
|
|
||||||
|
You must go beyond this. You need to lead the way. You shouldn't be just the tool your manager uses to spit out code. You should be the person your manager delegates to, to fully build something.
|
||||||
|
|
||||||
|
How does this have to do with accountability?
|
||||||
|
|
||||||
|
If no one is telling you what to do, or how to do it, what do you do?
|
||||||
|
|
||||||
|
It's not easy, and often we are not as self monivated as we would like to be (I know I sometimes lack in this regard). But you need to turn your engineering brain on, and figure things out. You need to know what to do next, and how it will impact the business and other people around you.
|
||||||
|
|
||||||
|
It isn't enough to sit back and write code. That code needs to be in the hand of customers, it needs to be tested, it needs to be deployed, maintained, it needs to be designed. It needs love and attention.
|
||||||
|
|
||||||
|
## My conclusion
|
||||||
|
|
||||||
|
Take accountabiliy for your projects at work. You need to be able to lead from start to finish. You cannot wait for someone to tell you what the next step is. You need to figure out that next step.
|
||||||
|
|
||||||
|
Now, I talked a lot about you, but I must stress. If you cannot go to your team to share opinions and ask for help, then you need to leave whatever company you're working for. We're very much shaped and pushed by those around you. And part of this concept is that you need to help others too, in a funny way, you need to know when to help others!
|
||||||
|
|
||||||
|
Writing code isn't enough. Be an engineer!
|
||||||
@ -1,4 +1,3 @@
|
|||||||
+++
|
+++
|
||||||
title = 'Blog'
|
title = 'Blog'
|
||||||
date = 2023-11-14T17:55:14Z
|
|
||||||
+++
|
+++
|
||||||
|
|||||||
42
content/blog/requesty.md
Normal file
42
content/blog/requesty.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
+++
|
||||||
|
title = "Requesty."
|
||||||
|
date = "2025-07-07"
|
||||||
|
tags = ["software"]
|
||||||
|
toc = true
|
||||||
|
+++
|
||||||
|
|
||||||
|
I will be joining [Requesty](https://requesty.ai) in August. My time at Decipad is coming to an end. I want to describe what I'm feeling, what I'm hoping for in the future, my apprehensions, and what I'm looking forward to.
|
||||||
|
|
||||||
|
# 3 Years (What I'm feeling)
|
||||||
|
|
||||||
|
Decipad has been the start of my professional career. Even though I had worked at other places before - and even founded my own company - Decipad was the first time I worked, as part of a sizable engineering team, to build a product.
|
||||||
|
|
||||||
|
I was hired by [Nuno](https://www.linkedin.com/in/nunojob/), who I regard as one of the kindest, most inspiring and decisive people I've ever had the pleasure of meeting. I hope that our paths cross again, and if not I will forever regard him as a friend and role-model.
|
||||||
|
|
||||||
|
I learnt how to work as a team, I learnt how to make product decisions, I learnt how to talk to clients. I came into Decipad as a hot-shot programmer, I could crunch tickets like a machine, but could I steer a very new product the correct direction? No, I could not.
|
||||||
|
|
||||||
|
I leave Decipad feeling that I can make those decisions, I am able to steer a product the correct way. I am not just a coder, I'm a product engineer.
|
||||||
|
|
||||||
|
I met lot's of amazing people - too many to list - and for all of them I am thankful for your kindness and patience as we went on this crazy journey together.
|
||||||
|
|
||||||
|
# My Senior Arc (What I'm hoping for the future)
|
||||||
|
|
||||||
|
I am joining as the 2nd hire, a Founding Engineer. This role caries a lot of weight, I am not just an employee of the company, I will be someone who will shape the product itself. work hand-in-hand with the founders to build the best developer experience, the most reliable and performant way to interact with LLMs from your codebase.
|
||||||
|
|
||||||
|
Like always, I have a lot to learn. I am hoping to learn from [Daniel](https://www.linkedin.com/in/daniel-trugman/), but I'm also hoping he can learn from me, and this I believe is the key difference from when I started Decipad. I am now a more complete engineer, and I am able to lead, much more than when I started at Decipad. I hope to bring my skills as an engineer and as a product person to the team.
|
||||||
|
|
||||||
|
This will likely be the hardest job I've ever worked. The area is hard, the space is crowded by already incredible people and products, and the hours will be long. It took me a while to decide that this is what I wanted to embark on, I deliberated over it for many days (I had other offers, that would potentially be more relaxed, Series A start-up). I want to be the person to take these opportunities and difficulties and face them head on with a smile. And do that I shall.
|
||||||
|
|
||||||
|
# What I'm scared of (Apprehensions)
|
||||||
|
|
||||||
|
I feel nervous, but OK with the difficulty of the technical challenges ahead of me. I enjoy the space, I know a fair bit about it already, and I will learn more everyday. What I am not so confident in, is my physical ability to join an in-person team, with high uncertainty, and a growing customer base. These are very rational fears, and I am working on having control over them, but it will take a while. I am taking the time from now to my start date, to prepare myself for what's about to come.
|
||||||
|
|
||||||
|
# What I'm looking forward to
|
||||||
|
|
||||||
|
Honestly, Golang. I've used this language so many times in so many projects - and yes I know it is [flawed](https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-ride) - I still get much joy from writing it. I am also looking forward to working on a service which is mostly non-user facing. Requesty does provide a very lovely dashboard, but the people actually using our core service (The router), are people who will never see into requesty.
|
||||||
|
|
||||||
|
I am super excited to build these systems, focusing on: high availability, high scalability, and performance. I guess I'm saying I'm looking forward to being a backend engineer.
|
||||||
|
|
||||||
|
# Conclusion
|
||||||
|
|
||||||
|
I'm moving jobs. I am really excited, and hyped to write code. More than I have been in a long time. I will enjoy this month before I start, and make sure that I am up to the challenge.
|
||||||
30
content/blog/self-hosting.md
Normal file
30
content/blog/self-hosting.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
+++
|
||||||
|
title = "Self Hosting"
|
||||||
|
date = "2025-06-08"
|
||||||
|
tags = ["self-hosting", "software"]
|
||||||
|
toc = true
|
||||||
|
+++
|
||||||
|
|
||||||
|
Since I moved into my [flat](https://en.wikipedia.org/wiki/Flat#Architecture), one of the first things I bought was a used computer which I could use as a server. This cost me £50, and it's not a very powerful machine. But this tiny machine has been a great source of fun for me. I want to break down what I'm doing with my own machine, but also the philosophy of self-hosting, and taking back control over your data, and deployment processes.
|
||||||
|
|
||||||
|
# Cloud can be bad
|
||||||
|
For many use-cases, using the cloud to host your projects, can be more trouble than the ol' server under the desk. I run mustly outward facing services on this machine, with some users and the service is very similar to what I would get if I hosted it on a VPS or some managed service. I don't get many [nines](https://en.wikipedia.org/wiki/High_availability#%22Nines%22), I probably only get 1 (or 2 on a good streak!), but does it really matter?
|
||||||
|
- My most important service is the backend of Haystack. A project in a closed beta which allows users to upload pictures. If the service goes down, then my users lose the ability to view, and process their images, which is obviously a bad experience.
|
||||||
|
- I have had one outage (my fault, skill issue), which lasted a day. And I argue that this doesn't matter, realistically Haystack is and will always be a small project with few (but interested) users. One where I believe 1 or 2 nines is enough.
|
||||||
|
|
||||||
|
So I've mentioned the downside, availability. But what are the good things?
|
||||||
|
- Money. I paid very little for the server, but for a similarly speced VPS on most cloud providers I would be paying 72$ a month!! [Source](https://www.linode.com/products/dedicated-cpu/). I do have other costs, namely electricity (I don't have a good number for this, but with the CPU averaging 10% usage, I don't think it's massive), and internet (which I would pay for regardless). There is a good amount of money to be saved by having an old computer under your desk running your stuff.
|
||||||
|
- > I will counter myself though. I will end up upgrading this server, as self-hosting is very much a hobby (and an expensive one when you start playing with fancy hardware!)
|
||||||
|
- Ownership. No one will take away this server from me. The data stored on it, is controlled by me, and not some giant corporation. This becomes important when it comes to personal data. Which I will talk about now.
|
||||||
|
# Own your data
|
||||||
|
Self-hosting isn't just for hosting projects, and outward facing services. Most of my time is spend on inward facing services. I've talked about services I host on the [Gitea post (https://johncosta.tech/blog/hello-gitea/), but to summarise, I have a lot of personal data from myself and my partner, which I would rather control rather than give it up to Google or Apple. A good example is my [Immich](https://immich.app) instance, which has all my photos, and these are terrabytes worth.
|
||||||
|
|
||||||
|
In today's age, it is important we all think about our personal data, who has control over it and who stands to profit from it. I don't want to be training data for an LLM without my consent.
|
||||||
|
|
||||||
|
# Learning and Enjoyment
|
||||||
|
Most importantly, I just love tinkering with the server. I love staying up to date with new open source projects which you has host yourself, I love having little home automations that run on my own hardware (my office lights are controlled by a really single Go script and a WLED controller).
|
||||||
|
|
||||||
|
I've also learnt so much about server administration and DevOps. I've learnt a lot about observability, about hosting your own CI/CD, and how to know when things have gone wrong. I've also continued to learn about Linux, networking, and so many other things I would love have a chance to play with, unless I had my own server. You can argue that this is possible with a VPS, but really, where's the fun in that?
|
||||||
|
|
||||||
|
# Conclusion
|
||||||
|
Self-hosting is really fun, you should try having an old computer under your desk running your stuff. You get a sense of accomplishment, for learning all you need to make it work, and to then manage it such that it continue to work. You will also be able to do things you never thought about doing, like hosting your own Netflix with [Jellyfin](https://jellyfin.org), or having actual production services running right next you, and managing your own database. I've really enjoyed it, and will continue to enjoy it for years to come.
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
+++
|
||||||
|
title = "The 7 Habits of Highly Effective People"
|
||||||
|
author = "Stephen Covey"
|
||||||
|
date = "2025-07-22"
|
||||||
|
+++
|
||||||
4
content/books-and-tv/_index.md
Normal file
4
content/books-and-tv/_index.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
+++
|
||||||
|
title = 'Books & TV'
|
||||||
|
date = 2025-07-22T15:15:00Z
|
||||||
|
+++
|
||||||
6
content/gists/_index.md
Normal file
6
content/gists/_index.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
+++
|
||||||
|
title = 'Gists'
|
||||||
|
toc = true
|
||||||
|
+++
|
||||||
|
|
||||||
|
Small snippets, random thoughts, bits of code. Anything really.
|
||||||
49
content/gists/pointer-vs-value.md
Normal file
49
content/gists/pointer-vs-value.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
+++
|
||||||
|
title = "Pointer vs Value"
|
||||||
|
date = "2025-11-24"
|
||||||
|
author = "John Costa"
|
||||||
|
tags = ["Software", "gist"]
|
||||||
|
+++
|
||||||
|
|
||||||
|
When working with pointers, what do you think the difference is?
|
||||||
|
|
||||||
|
## 1. Assign to pointer
|
||||||
|
```go
|
||||||
|
func (c *MyStruct) SomeFunction(val any) {
|
||||||
|
parsedStruct := someProcessingFunc(val)
|
||||||
|
c = &parsedStruct
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
vs
|
||||||
|
|
||||||
|
## 2. Assign to value
|
||||||
|
```go
|
||||||
|
func (c *MyStruct) SomeFunction(val any) {
|
||||||
|
parsedStruct := someProcessingFunc(val)
|
||||||
|
*c = parsedStruct
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
I came across this at work today and it took me a second to figure out what was wrong.
|
||||||
|
|
||||||
|
|
||||||
|
## Number 2 is correct
|
||||||
|
|
||||||
|
The first example actually assigned the pointer of `parsedStruct` to the local variable `c` which itself is just a pointer.
|
||||||
|
|
||||||
|
```go
|
||||||
|
c = &parsedStruct
|
||||||
|
```
|
||||||
|
|
||||||
|
All we've done, is reassign a local variable.
|
||||||
|
|
||||||
|
Whereas:
|
||||||
|
|
||||||
|
```go
|
||||||
|
*c = parsedStruct
|
||||||
|
```
|
||||||
|
|
||||||
|
Actually changes the underlying value of the pointer `c`, and changes it to the content of `parsedStruct`.
|
||||||
|
|
||||||
|
It's easy to overlook these things, specially now when LLMs write more and more code. But it will be more and more important to understand and spot these differences, they might cost you or your company a lot of business.
|
||||||
19
hugo.toml
19
hugo.toml
@ -9,9 +9,19 @@ theme = 'risotto'
|
|||||||
[[menu.main]]
|
[[menu.main]]
|
||||||
name = 'Blog'
|
name = 'Blog'
|
||||||
pageRef = '/blog'
|
pageRef = '/blog'
|
||||||
|
weight = 1
|
||||||
[[menu.main]]
|
[[menu.main]]
|
||||||
|
weight = 1
|
||||||
name = 'Projects'
|
name = 'Projects'
|
||||||
pageRef = '/projects'
|
pageRef = '/projects'
|
||||||
|
[[menu.main]]
|
||||||
|
weight = 20
|
||||||
|
name = 'Books & TV'
|
||||||
|
pageRef = '/books-and-tv'
|
||||||
|
[[menu.main]]
|
||||||
|
weight = 10
|
||||||
|
name = 'Gists'
|
||||||
|
pageRef = '/gists'
|
||||||
|
|
||||||
[params.about]
|
[params.about]
|
||||||
title = "John Costa"
|
title = "John Costa"
|
||||||
@ -37,17 +47,22 @@ url = "https://github.com/JohnCosta27/JohnTech"
|
|||||||
[[params.socialLinks]]
|
[[params.socialLinks]]
|
||||||
icon = "fa-brands fa-git-alt"
|
icon = "fa-brands fa-git-alt"
|
||||||
title = "Gitea"
|
title = "Gitea"
|
||||||
url = "https://git.johncosta.tech"
|
url = "https://git.johncosta.tech/JohnCosta27"
|
||||||
|
|
||||||
[[params.socialLinks]]
|
[[params.socialLinks]]
|
||||||
icon = "fa-brands fa-linkedin"
|
icon = "fa-brands fa-linkedin"
|
||||||
title = "LinkedIn"
|
title = "LinkedIn"
|
||||||
url = "https://www.linkedin.com/in/john-costa-b883971b5/"
|
url = "https://www.linkedin.com/in/john-costa-b883971b5/"
|
||||||
|
|
||||||
|
[[params.socialLinks]]
|
||||||
|
icon = "fa-brands fa-hashtag"
|
||||||
|
title = "Converge"
|
||||||
|
url = "https://converge.sh/1"
|
||||||
|
|
||||||
[[params.socialLinks]]
|
[[params.socialLinks]]
|
||||||
icon = "fa-solid fa-envelope"
|
icon = "fa-solid fa-envelope"
|
||||||
title = "Email"
|
title = "Email"
|
||||||
url = "mailto:johncosta027@gmail.com"
|
url = "mailto:me@johncosta.tech"
|
||||||
|
|
||||||
[taxonomies]
|
[taxonomies]
|
||||||
tags = "tags"
|
tags = "tags"
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="{{ .Permalink }}">{{ .Title | markdownify }}</a>
|
{{ $format := "02 Jan 2006" }}
|
||||||
|
<a href="{{ .Permalink }}">{{ .Date.Format $format }} | {{ .Title | markdownify }}</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -16,8 +16,8 @@ h3,
|
|||||||
h4,
|
h4,
|
||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
font-size: 1rem;
|
font-size: 1.2rem;
|
||||||
margin: 1.5rem 0 0 0;
|
margin: 2rem 0 0 0;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ h3 + h6,
|
|||||||
h4 + h5,
|
h4 + h5,
|
||||||
h4 + h6,
|
h4 + h6,
|
||||||
h5 + h6 {
|
h5 + h6 {
|
||||||
margin: 0;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1:before {
|
h1:before {
|
||||||
|
|||||||
Reference in New Issue
Block a user