Independent software engineer · Adelaide, South AustraliaDesign / Frontend / Backend

Bespoke software,built to last.

Senior engineering for small businesses, startups and independents — one person who takes the whole problem, from rough idea or ageing system to a shipped product that’s a pleasure to use.

Aidan Forbes · Atavis DevelopmentA considered interface. A complete system.
VueNuxtReactNext.NETTypeScriptNodePostgres

The whole build,
one engineer.

Agencies typically price my kind of work as requiring a designer, a couple of developers and a project manager. I do all of those jobs myself: requirements, architecture, UX/UI, build, deployment.

You don’t need a complete specification or concept. Bring the project as it stands and we’ll work together to determine what needs building and how we’ll approach it.

Nov 2025–now
Senior software engineerLane Communications · Contract
Oct 2025–now
Atavis DevelopmentIndependent software engineering
2023–2025
Software engineerLane Communications · Junior to mid-level

Where I can help.

From a second opinion to the full build, or extra hands alongside your team.

Consulting.

Work out where you’re going, and what it takes to get there.

  • System review and technical direction
  • Project scope and requirements
  • UI/UX concepts and design specifications
  • A second opinion before committing budget

Development.

Design, build, and deploy your dreams. Web or mobile. Long-term maintenance if desired.

Everything in Consulting, plus:
  • Full-stack application development
  • Legacy modernisation and integration
  • Identity, access and live updates
  • Deployment and ongoing support

Reinforcements.

Drop-in mid-to-senior help for a week, a month, or a whole crunch.

Everything in Development, short-term.
  • Short-term contracting
  • Support for an overloaded team
  • Work in an existing codebase
  • A clear handover when we wrap up

A little more
of the thinking.

How I approach interfaces, choose the tools, and build systems that people can keep working on.

All articles
My UI/UX processAn interface starts to make sense when you can explain what someone came there to do.

An interface starts to make sense when you can explain what someone came there to do. They might be checking whether an order is ready, correcting a stock figure or finding the document somebody changed yesterday. The screen needs to help them finish that job.

Doing the design and the engineering together means I can follow a decision all the way through. A reassuring message is only useful if the system can support what it says. A quick interaction still needs somewhere sensible to go when the request fails.

Start with a real task

Take an order list. Before choosing a layout, I want to know who uses it, what they need to spot and what happens next. Someone in production may care about what is ready to make. Someone answering the phone needs to find a particular customer's order quickly. Those are different priorities, even if both people use the same underlying data.

For a first pass, I would write down the journey in ordinary language: find the order, understand its state, make the change, check that it worked. That gives us something concrete to review. If we cannot agree on the journey, moving the buttons around will not settle it.

Make the important things easy to find

Visual hierarchy should follow the task. On that order screen, the reference, status and next action probably deserve more attention than the time the record was created. A useful default sort can save more effort than another filter.

I like restrained interfaces because they make these choices visible. Spacing groups related information. Type size establishes priority. Colour can show the action worth taking, provided the label still makes sense without it. Every separator and container takes up some of the reader's attention, so I want a reason for each one.

Consistency helps too. If one page puts the primary action beside the title, moving it to the bottom of the next page needs a good reason. People should be learning the work, with as little time as possible spent relearning the software.

Work through the awkward states

The first tidy screen is only one state of the interface. What happens with a long customer name, an empty list, a slow connection or a validation error halfway through a form? What if somebody else changes the order while it is open?

A failed save should keep the entered values and explain how to try again. An empty search should retain the query and offer a clear way to reset it. If an action needs permission, the interface should explain the restriction where that explanation is useful. Hiding a button does not enforce the rule; the server must enforce it too.

These decisions connect UX directly to the backend. They affect what the API returns, which changes are safe to retry and how the application handles conflicting edits.

Judge it in the browser

A browser prototype makes the details harder to avoid. You can tab through the controls, resize the page, increase text size and try the longest label. You can feel whether a menu opens where you expect and whether an animation makes the change easier to follow.

The same care applies to a quiet settings form as to a portfolio headline. Focus should remain visible. Labels should stay attached to their fields. Reduced motion should leave a complete, usable page.

The useful question at the end is specific: can someone complete the task and tell that it succeeded? Once that works, there is still room to refine the typography, timing and spacing. That last pass is where a functional interface starts to feel considered.

Open article page
Building scalable and maintainable systemsA useful system has to fit the business running it, including the people who will maintain it.

A useful system has to fit the business running it, including the people who will maintain it. An architecture can look impressive in a diagram and still be a poor fit for a small team trying to keep orders moving.

I want the structure to make everyday changes understandable. A new approval step, another customer type or a replacement integration should have a reasonably clear home. That is a more useful starting point than guessing how many services the business might need years from now.

Size the system to the business

Before choosing an architecture, I would ask about the work: how much data moves through it, when people use it, which systems it depends on and what a failure would interrupt. A reporting screen and an order submission have different consequences when they are unavailable.

For a small team, a single application with clear internal boundaries can be a sensible starting point. It keeps deployment and diagnosis relatively straightforward. Separate services can be worthwhile when parts of the system need independent operation or deployment, but those benefits have to justify the extra coordination.

Growth also has several meanings. More customers, a larger catalogue and more developers changing the code create different pressures. Naming the likely pressure makes the next decision less speculative.

Give business rules a clear home

Consider the rule for when an order may move into production. It should be possible to find that rule without tracing a button click through half the application. The server needs to enforce it wherever the request comes from. The interface can then explain why an order is ready or what still needs attention.

I would keep that rule separate from details such as the colour of a status label or the delivery service used to send an email. Those things change for different reasons. Keeping their responsibilities distinct makes the business behaviour easier to review and test.

Boundaries are useful when they reduce the amount you need to understand at once. Adding a layer that only forwards a call can have the opposite effect. I want each abstraction to earn the extra jump through the code.

Change legacy systems in manageable steps

Existing software often contains decisions that nobody has written down. A strange-looking field may support a monthly report. A manual workaround may be protecting an integration that fails under a particular condition.

Before replacing a part of the system, I want to understand who depends on it and what behaviour must survive. A narrow replacement with an explicit connection to the old application can make progress possible without requiring everything to change together.

Data deserves particular care. A deployment plan should explain how existing records move forward, what happens to work already in progress and how to recover if the change fails. Rolling back application code does not automatically reverse a data migration.

Make faults understandable

A useful error report gives enough context to locate the failed operation without exposing private information. For an integration, that might include a request identifier and the stage that failed. It should be possible to distinguish a rejected request from an unavailable dependency.

Retries need an equally deliberate design. If a caller repeats a submission after a timeout, the system needs to know whether that operation has already happened. Otherwise a recovery mechanism can create duplicate work.

Tests should protect the behaviours that matter: permissions, state changes, calculations and interactions with systems outside our control. Before shipping, I would also want a clear deployment procedure, a recovery path and documentation for whoever takes responsibility next. Those are practical parts of maintainability, even though they rarely appear in an architecture diagram.

Open article page
Why these are excellent frameworksA framework choice should make the next few years of work easier for the people who own the software.

A framework choice should make the next few years of work easier for the people who own the software. I care about how clearly it expresses the interface, what the team already understands and how comfortably it fits the existing system.

Vue, Nuxt, React and Next are among the tools I work with. They offer different ways to organise frontend work, and the choice between them depends on the project. Being quick in a framework is useful; recognising when it is the wrong fit is useful too.

What makes a framework worth choosing

I want to be able to open a component and understand where its data comes from, what it displays and what happens when somebody interacts with it. That sounds modest, but it matters when the original developer is away and an ordinary business change needs to ship.

Vue's templates keep much of that relationship visible. Its official introduction describes an incrementally adoptable framework, which is helpful when considering both a new application and an addition to an existing page. The conventions around templates, reactive state and components give me a clear vocabulary for building interfaces. Vue's introduction explains that model.

React's component model is another useful way to break an interface into responsibilities. I particularly like the exercise of deciding which values genuinely need to be stored and which can be calculated from existing data. Keeping those decisions clear helps avoid two parts of a screen disagreeing. The official Thinking in React guide walks through that process.

The application around the components

A component library alone does not settle routing, data loading or how a page reaches the browser. Nuxt and Next provide application-level conventions around Vue and React respectively.

Nuxt documents universal, client-side and hybrid rendering. That flexibility makes it possible to choose rendering behaviour around the needs of a route rather than assume every page has the same job. A public article and a signed-in operational screen deserve separate consideration. See the Nuxt rendering guide.

Next's App Router uses Server and Client Components. Its documentation is worth reading closely because that boundary affects where code runs and how interactive parts are composed. I would want those choices understood by the team maintaining the application, rather than hidden behind copied examples. The Server and Client Components guide explains the distinction.

Check the surrounding decisions

For an actual project, I would look beyond a basic demo. Does the approach fit the authentication system? Are the required controls accessible? Where will it run, and who will support the deployment? Can the team diagnose a failed request without learning several unfamiliar abstractions first?

The existing codebase also counts. If a team already maintains a healthy React application, the case for adding Vue needs to be stronger than my preference for its templates. Consistency can reduce the amount of knowledge needed to keep the whole system working.

Where I would choose something else

A small content site may need very little JavaScript. A conventional server-rendered application may already handle a business workflow perfectly well. An established platform may cover most of the requirement without a custom application at all.

When bespoke software is justified, I want the framework to support clear code and a good interface without becoming the centre of the project. The client is buying a working system. My job is to choose tools that make it practical to build, change and look after.

Open article page
Going independentI opened Atavis Development in October 2025, after starting my professional software career at Lane Communications.

I opened Atavis Development in October 2025, after starting my professional software career at Lane Communications. The work brought together requirements, interface design, backend development and the existing systems a business relies on. That combination is still the centre of what I offer.

Getting started

I finished my Bachelor of Software Development in September 2023, graduating in the top five per cent of computer science students with merit awards each year. In December I joined Lane Communications, where I progressed from a junior to a mid-level software engineering role.

During that employment I shipped two full-stack web projects: an online ordering platform with its internal tooling, and an online document version control manager. That work meant taking responsibility for more than the visible screen. Data, access, workflow and the surrounding business processes all had to fit together.

The degree gave me a foundation. Working on systems used inside a business gave those decisions a different context: there were people who needed the software to help them get their work done.

Forming Atavis Development

Atavis began in October 2025. The following month I started contracting with Lane Communications as a senior software engineer, working directly with executive management on the modernisation of their digital ecosystem.

The name has a personal connection: it is an amalgamation of my own name. It also connects with atavus, the Latin word for an ancestor. I like the idea behind that connection. Tools change quickly, while questions about clear interfaces, sensible boundaries and understandable code keep coming back.

That is the thinking behind “built to last”. Software will need changes. I want the work to leave room for them, and for the person making those changes to be able to understand what is already there.

The kind of work I am interested in

Small businesses, startups and independent business people often need someone who can take a rough problem and work out what building a useful solution involves. That can mean defining the workflow, making technology choices, designing the interface and carrying the build through to deployment.

I enjoy the connection between those responsibilities. A design decision can reveal that a business rule is unclear. An awkward integration can change the most sensible way to present a workflow. Being involved across the build means I can follow those issues through rather than leave them at a handover.

Modernisation is a particular part of that work. Existing systems have useful behaviour as well as limitations. I want to understand what needs to stay, what is getting in the way and which improvements can be made without disrupting everything around them.

Working together

You do not need to arrive with a complete specification. A description of the problem, the current process and the people involved is a useful place to begin. From there we can establish what needs building and whether I am the right person to do it.

Some engagements need a complete build. Others need a technical second opinion, a design specification or another engineer alongside an existing team. I offer consulting, development and short-term support to suit those different situations.

I am based in Adelaide and work remotely, with hybrid arrangements where they help the project. The work I am looking for has room for both engineering judgement and care for the people using the result.

Open article page

Bring the problem.
We’ll work it out.

Tell me what you’re building, or what’s in the way. I’ll usually reply within 1–3 business days, and everything you share stays confidential.

First a reply, then a call to work out what you actually need. Nothing is committed until there is a written scope, and asking costs nothing.

Contracts starting at $120 AUD/hr. Adelaide · Remote worldwide.

All fields required

Aidan Forbes · Adelaide, South Australia