ChatGPT, GitHub Copilot, Cursor, and their cousins can now spit out a React component before you finish typing the prompt. Hook up a Next.js route to Supabase? Done in seconds. Refactor that tangled TypeScript utility? Here are three options, complete with type guards. For anyone working in modern web stacks, the experience can feel borderline magical.

I use these tools daily. My stack is Next.js, TypeScript, and Supabase, and AI sits right there in my editor, ready to scaffold custom hooks, generate database queries, or clean up messy conditional logic. In the small, it performs like a very fast junior developer. It knows syntax cold. It remembers API surface areas I have to Google. It does not get tired of writing boilerplate.

But software keeps breaking. Apps feel slower. Customer dashboards lag. Edge cases crash forms. If AI has made coding so much easier, why does using software feel worse than it did a few years ago?

The answer is that generating syntax and building software are not the same job.

Syntax Is Not Architecture

AI handles tokens remarkably well. Ask it to write a useEffect hook that listens to a Supabase real-time channel, and you will get something that compiles. It can convert an untyped JavaScript file into strict TypeScript, or spin up a form component with Zod validation before you have had your coffee.

What it cannot do is understand the contours of your specific application. Good software requires deliberate state management, careful handling of race conditions, and a clear map of where data lives versus where it is merely displayed. AI sees the immediate file, not the system. It treats your codebase like a flat text corridor rather than a living structure with load-bearing walls.

Think of it like an architect who has never actually lived in a house. They can draw beautiful floor plans. They know how many windows a bedroom should have. But they do not know where the pipes tend to leak in February, or which hallway gets unusable in the summer heat. That lived knowledge is what keeps a building standing. Code works the same way.

The Two Friction Points

When I let AI write larger chunks of code without strict guardrails, I notice the same two problems cropping up again and again.

First, it ignores the design patterns you have already established. Maybe your team extracts all data fetching into a dedicated layer of custom hooks. Maybe you have a strict convention for how Supabase RLS policies map to frontend helpers. AI does not care. It will drop a raw supabase.from().select() right into a button’s onClick if that solves the immediate prompt. The code runs. It even looks clean. But it is an outlier in your codebase, and every outlier is a future refactoring tax. Six months later, someone has to find that needle, understand why it exists, and gently pull it back into line.

Second, it reaches for complexity when simplicity would do. The tool has been trained on repositories large enough to need abstract factories, intricate reducer patterns, and multi-layered higher-order components. When you ask it to build a simple contact form, it may well hand you a state machine, a context provider, and a custom hook abstraction that spans three files. The solution is not technically wrong. It is just heavy. Each unnecessary layer adds cognitive debt. You did not skip the work; you deferred it, with interest.

The Velocity Trap

There is a dangerous feedback loop here. AI lets you build features twice as fast, but human attention does not scale the same way. If you are shipping in half the time, are you spending twice as long on code review? Are you writing more tests, or fewer?

In practice, it is remarkably easy to trust generated code because it looks authoritative. It uses modern syntax. Comments are sprinkled in exactly the right places. Variable names sound professional. Subtle bugs hide in that polish. A dependency array in a hook that omits a setter. A TypeScript type that is technically correct but allows a null state you forgot to handle. A Supabase query that forgets to account for soft-deleted rows in your specific schema. You skim instead of reading every line, because the pace of delivery demands it. The speed feels great on Monday. The debugging session on Friday lasts until midnight.

The Real Cost

The people who pay for this are not the developers. They are the end users.

Perangkat lunak terasa lebih berat karena kompleksitas tumbuh lebih cepat daripada kemampuan tim untuk mengelolanya. Kita membangun aplikasi yang lebih besar dengan tim yang lebih kecil, dibekali dengan alat yang membuat kita merasa tak terkalahkan. Ketika satu pengembang dapat membuat kerangka (scaffold) seluruh dasbor dalam satu sore, organisasi mengharapkan tiga dasbor pada hari Rabu. Skalabilitas tanpa kehati-hatian menghasilkan sistem yang rapuh. State membengkak. Ukuran bundle merayap naik. Race condition berlipat ganda. Antarmukanya mungkin terlihat modern, tetapi ia mereset dirinya sendiri saat pengguna menekan tombol kembali, atau butuh waktu empat detik untuk melakukan hydrate karena tidak ada yang sempat melakukan profil terhadap waterfall pengambilan data yang dihasilkan AI.

Bekerjalah Bersama Mesin, Bukan Untuknya

Semua ini bukan berarti Anda harus membuang AI dari editor Anda. Ini berarti Anda membutuhkan batasan.

Gunakanlah untuk hal-hal yang memang dikuasainya. Biarkan ia menulis hal-hal yang membosankan: antarmuka TypeScript yang repetitif, kueri boilerplate Supabase, pengaturan Jest.