admin – Juan Camilo Niño
The first weeks with an AI coding assistant feel like magic. The next weeks feel like cleaning up after magic. What changed my results was not a better model, it was a better loop.
Write the problem down before you prompt
Before I open the assistant I write three lines: what should be true when this is done, what must not change, and how I will check it. Those lines become the prompt. If I cannot write them, I do not understand the task yet, and no tool will fix that.
Give context, not just instructions
A model that sees only the file you pasted will invent the rest. I give it the surrounding structure: how the project is organized, the naming rules, the component I want it to imitate. The closer the example, the less rewriting I do later.
Keep the steps small
Ask for one change at a time. A small diff is easy to read, easy to test and easy to revert. When I ask for a whole feature in one go, I get a result I can only accept or reject, never review.
Read every line you keep
This is the rule that matters most. If I would not be able to explain a line in a code review, it does not go in. AI makes typing cheap, which makes judgment the expensive part. That is where a developer earns their place.
Use it for the boring parts first
- Boilerplate, types and repetitive component variants.
- Explaining unfamiliar code before you change it.
- Drafting tests and documentation you then correct.
- Second opinions on naming and structure.
Keep learning on purpose
The risk of working with AI is not that you get replaced, it is that your own skills quietly fade. I still read documentation, I still write the hard parts myself, and I still debug without the assistant now and then. Treat the tool like a fast junior colleague: useful, tireless, and in need of review.
The developers who benefit most are not the ones who prompt the most. They are the ones who know what good looks like and can tell when the output is not it.
Las primeras semanas con un asistente de código con IA parecen magia. Las siguientes parecen limpiar el desorden de la magia. Lo que cambió mis resultados no fue un mejor modelo, fue un mejor flujo.
Escribe el problema antes de escribir el prompt
Antes de abrir el asistente escribo tres líneas: qué debe ser verdad cuando termine, qué no puede cambiar y cómo lo voy a verificar. Esas líneas se vuelven el prompt. Si no puedo escribirlas, todavía no entiendo la tarea, y ninguna herramienta arregla eso.
Da contexto, no solo instrucciones
Un modelo que solo ve el archivo que pegaste inventa el resto. Yo le muestro la estructura alrededor: cómo está organizado el proyecto, las reglas de nombres, el componente que quiero que imite. Mientras más cercano el ejemplo, menos reescribo después.
Mantén los pasos pequeños
Pide un cambio a la vez. Un diff pequeño es fácil de leer, de probar y de revertir. Cuando pido una funcionalidad completa de una sola vez, recibo un resultado que solo puedo aceptar o rechazar, nunca revisar.
Lee cada línea que te quedas
Esta es la regla más importante. Si no podría explicar una línea en una revisión de código, no entra. La IA vuelve barato el teclear, así que el criterio es lo caro. Ahí es donde un desarrollador se gana su lugar.
Úsala primero para lo aburrido
- Código repetitivo, tipos y variantes de componentes.
- Explicar código desconocido antes de tocarlo.
- Borradores de tests y documentación que luego corriges.
- Segundas opiniones sobre nombres y estructura.
Sigue aprendiendo a propósito
El riesgo de trabajar con IA no es que te reemplacen, es que tus propias habilidades se apaguen sin que lo notes. Yo sigo leyendo documentación, sigo escribiendo yo mismo las partes difíciles y de vez en cuando depuro sin el asistente. Trata la herramienta como a un colega junior rápido: útil, incansable y necesitado de revisión.
Los desarrolladores que más se benefician no son los que más prompts escriben. Son los que saben cómo se ve lo bueno y notan cuándo el resultado no lo es.
Code written by an AI looks confident. It compiles, it has tidy names, it even has comments. None of that tells you it does what the client asked. The only thing that does is a test that fails when the behavior is wrong.
Test the behavior, not the implementation
I care about what a visitor can do: add a product to the cart, submit a form, pay. End-to-end tests describe exactly that, and they do not care how the code underneath was written, by me or by a model. That makes them the ideal referee for AI-assisted work.
test("visitor can request a website audit", async ({ page }) => {
await page.goto("/website-audit/");
await page.fill("[name=site]", "example.com");
await page.fill("[name=name]", "Test User");
await page.fill("[name=email]", "test@example.com");
await page.click("button[type=submit]");
await expect(page.locator(".form__status")).toContainText("review");
});
Write the test first when the stakes are high
For checkout flows, forms and payments, I write the test before I ask for the code. The test is the specification. If the generated code passes, I read it and keep it. If it fails, the failure message tells me exactly what to say in the next prompt.
Do not let the model grade its own homework
A model asked to write both the code and the tests will happily write tests that pass. I review the assertions themselves: do they check the real outcome, or just that a function was called? A test that cannot fail is decoration.
Cover the ugly paths
- Empty and invalid input.
- Slow networks and failed requests.
- Mobile widths and keyboard-only navigation.
- The thing that broke last time.
Document what the tests protect
Short technical documentation next to the tests pays for itself. It tells the next developer, or the next model, which behaviors are promises and which are accidents.
AI made writing code faster. It did not make being wrong cheaper. Tests are how you keep the speed without paying for the mistakes.
El código escrito por una IA se ve seguro. Compila, tiene nombres ordenados, incluso trae comentarios. Nada de eso te dice que haga lo que pidió el cliente. Lo único que lo dice es una prueba que falla cuando el comportamiento es incorrecto.
Prueba el comportamiento, no la implementación
Me importa lo que puede hacer un visitante: agregar un producto al carrito, enviar un formulario, pagar. Las pruebas de punta a punta (e2e) describen justo eso y no les importa cómo se escribió el código por debajo, si lo hice yo o un modelo. Eso las convierte en el árbitro ideal del trabajo asistido por IA.
test("visitor can request a website audit", async ({ page }) => {
await page.goto("/website-audit/");
await page.fill("[name=site]", "example.com");
await page.fill("[name=name]", "Test User");
await page.fill("[name=email]", "test@example.com");
await page.click("button[type=submit]");
await expect(page.locator(".form__status")).toContainText("review");
});
Escribe la prueba primero cuando hay mucho en juego
Para flujos de compra, formularios y pagos, escribo la prueba antes de pedir el código. La prueba es la especificación. Si el código generado pasa, lo leo y me lo quedo. Si falla, el mensaje de error me dice exactamente qué decir en el siguiente prompt.
No dejes que el modelo califique su propia tarea
Un modelo al que le pides el código y los tests escribirá felizmente tests que pasan. Reviso las aserciones: ¿verifican el resultado real o solo que se llamó una función? Una prueba que no puede fallar es decoración.
Cubre los caminos feos
- Datos vacíos e inválidos.
- Redes lentas y peticiones fallidas.
- Anchos móviles y navegación solo con teclado.
- Lo que se rompió la vez anterior.
Documenta lo que protegen los tests
Una documentación técnica corta junto a las pruebas se paga sola. Le dice al siguiente desarrollador, o al siguiente modelo, qué comportamientos son promesas y cuáles son accidentes.
La IA hizo más rápido escribir código. No hizo más barato equivocarse. Los tests son la forma de conservar la velocidad sin pagar los errores.
On Shopify projects, the real test comes after launch: the client wants a new landing page on Friday and you are not there. The way you build the theme decides whether that is a five-minute task or an emergency.
Build sections, not pages
Every block of a design should be a section with a schema: settings the client can change and blocks they can reorder. A page then becomes a list of sections, and the client composes it in the theme editor without touching code.
{% schema %}
{
"name": "Feature row",
"settings": [
{ "type": "text", "id": "heading", "label": "Heading" },
{ "type": "richtext", "id": "body", "label": "Text" }
],
"blocks": [{ "type": "item", "name": "Item" }],
"presets": [{ "name": "Feature row" }]
}
{% endschema %}
Put structured data in metafields
Ingredients, specifications, certifications: anything that repeats across products belongs in a metafield with a clear definition, not in a wall of text in the description. The template reads the field, and the client fills it in from the product page.
Use metaobjects for things that are not a product
Team members, FAQs, store locations, lab results. Metaobjects give that content its own structure and its own admin screen. I have used them on stores in the biotech space, where the data is detailed and needs to stay consistent across many pages.
Keep the theme boring
- One naming convention for sections and settings.
- Small snippets for repeated markup.
- No hard-coded text or IDs in templates.
- Shopify CLI and Git for every change, never editing live.
Measure, then change
A/B tests settle arguments about design with data. Change one thing, wait for enough traffic, keep the winner. It is slower than trusting your gut, and much cheaper than being wrong.
The goal is a store that keeps working, and keeps improving, when the developer is not in the room.
En los proyectos Shopify, la prueba real llega después del lanzamiento: el cliente quiere una landing nueva el viernes y tú no estás. La forma en que construyes el tema decide si eso es una tarea de cinco minutos o una emergencia.
Construye secciones, no páginas
Cada bloque de un diseño debe ser una sección con su schema: ajustes que el cliente puede cambiar y bloques que puede reordenar. Una página pasa a ser una lista de secciones, y el cliente la compone en el editor del tema sin tocar código.
{% schema %}
{
"name": "Feature row",
"settings": [
{ "type": "text", "id": "heading", "label": "Heading" },
{ "type": "richtext", "id": "body", "label": "Text" }
],
"blocks": [{ "type": "item", "name": "Item" }],
"presets": [{ "name": "Feature row" }]
}
{% endschema %}
Pon los datos estructurados en metafields
Ingredientes, especificaciones, certificaciones: todo lo que se repite entre productos va en un metafield con una definición clara, no en un muro de texto en la descripción. La plantilla lee el campo y el cliente lo llena desde la página del producto.
Usa metaobjects para lo que no es un producto
Miembros del equipo, preguntas frecuentes, sedes, resultados de laboratorio. Los metaobjects le dan a ese contenido su propia estructura y su propia pantalla de administración. Los he usado en tiendas del sector biotecnología, donde los datos son detallados y deben ser consistentes en muchas páginas.
Mantén el tema aburrido
- Una sola convención de nombres para secciones y ajustes.
- Snippets pequeños para el marcado repetido.
- Nada de textos ni IDs escritos a mano en las plantillas.
- Shopify CLI y Git para cada cambio, nunca editar en vivo.
Mide, luego cambia
Las pruebas A/B resuelven discusiones de diseño con datos. Cambia una cosa, espera suficiente tráfico y quédate con la ganadora. Es más lento que confiar en el instinto y mucho más barato que equivocarse.
La meta es una tienda que siga funcionando, y mejorando, cuando el desarrollador no está en la sala.
When I built a payment collection platform from scratch, the hardest part was not React or Material-UI. It was working out what the system actually had to do. Code you write against the wrong requirements is just a well-organized mistake.
Ask about the money and the mess first
In anything that handles payments, start with the uncomfortable questions. What happens when a payment fails halfway? Who can see what? What must be recorded, and for how long? These answers shape the architecture far more than the choice of framework.
Write the user journeys in plain language
Before any diagram, I write each journey as a short story: who is the user, what do they want, what do they see at each step, what can go wrong. A client can read and correct a story. They cannot correct a database schema.
Turn stories into a small, honest scope
- What must exist on day one.
- What can wait for version two.
- What is explicitly out of scope, written down.
That last list saves more arguments than any other.
Let AI interrogate the brief
This is where an assistant is genuinely useful. I paste the requirements and ask it to find contradictions, missing edge cases and questions I should ask the client. It does not decide anything, but it finds holes faster than I do at the end of a long day.
Choose the architecture last, and keep it boring
Once the journeys and the scope are clear, the architecture is mostly obvious: a component structure that mirrors the journeys, a clear boundary between the interface and the data, and as few moving parts as the problem allows.
Good requirements analysis feels slow at the start and saves weeks at the end. It is also the part of the job AI is least able to do for you, because it depends on talking to people.
Cuando construí una plataforma de recaudo de pagos desde cero, lo más difícil no fue React ni Material-UI. Fue descubrir qué tenía que hacer realmente el sistema. El código escrito sobre requisitos equivocados es solo un error bien organizado.
Pregunta primero por el dinero y por el desorden
En todo lo que maneja pagos, empieza por las preguntas incómodas. ¿Qué pasa si un pago falla a la mitad? ¿Quién puede ver qué? ¿Qué debe registrarse y por cuánto tiempo? Esas respuestas moldean la arquitectura mucho más que la elección del framework.
Escribe los recorridos del usuario en lenguaje simple
Antes de cualquier diagrama, escribo cada recorrido como una historia corta: quién es el usuario, qué quiere, qué ve en cada paso, qué puede salir mal. Un cliente puede leer y corregir una historia. No puede corregir un esquema de base de datos.
Convierte las historias en un alcance pequeño y honesto
- Lo que debe existir el primer día.
- Lo que puede esperar a la versión dos.
- Lo que queda explícitamente fuera del alcance, por escrito.
Esa última lista ahorra más discusiones que cualquier otra.
Deja que la IA interrogue el brief
Aquí un asistente es realmente útil. Pego los requisitos y le pido que encuentre contradicciones, casos límite olvidados y preguntas que debería hacerle al cliente. No decide nada, pero encuentra huecos más rápido que yo al final de un día largo.
Elige la arquitectura al final y mantenla aburrida
Cuando los recorridos y el alcance están claros, la arquitectura casi se explica sola: una estructura de componentes que refleja los recorridos, una frontera clara entre la interfaz y los datos, y tan pocas piezas móviles como el problema permita.
Un buen análisis de requisitos se siente lento al principio y ahorra semanas al final. También es la parte del trabajo que la IA menos puede hacer por ti, porque depende de hablar con personas.
Most of my career has been spent working with agencies and their clients, often several at the same time: WordPress here, Shopify there, a React app in between. Context switching is the real job. These habits made it sustainable.
Every project gets a one-page brief
Goal, stack, who to ask, how to deploy, what not to touch. When I return to a project after two weeks, that page gets me productive in minutes instead of hours. I keep it in the repository, next to the code.
Documentation is a deliverable
I write the handoff notes as I go, not at the end. Setup steps, decisions and their reasons, known problems. It is the difference between a client who depends on you and a client who trusts you.
Automate the repeated work
- Scripts for local setup and deployment.
- Checklists for launch: metadata, redirects, indexing, analytics.
- A standard QA pass on every project before it goes out.
Process automation is not glamorous, but it is what lets one developer serve many projects without dropping details.
Communicate early, in writing
Bad news travels best early. A short message that says what is late, why, and what the new plan is keeps a client calm. Written updates also protect both sides when memory gets fuzzy.
Where AI helps, and where it does not
AI is excellent at the switching cost: summarizing an unfamiliar codebase, reminding me how a plugin works, drafting the boring parts of documentation. It is poor at knowing what a particular client values, or which shortcut will hurt them later. That judgment stays with you.
Protect your learning time
When you are busy, learning is the first thing to go, and the tools change every few months. I keep a small, fixed slot each week for reading and experimenting. It is the cheapest insurance a developer can buy.
Gran parte de mi carrera ha sido trabajar con agencias y sus clientes, muchas veces varios a la vez: WordPress aquí, Shopify allá, una app en React en medio. Cambiar de contexto es el trabajo real. Estos hábitos lo hicieron sostenible.
Cada proyecto tiene un brief de una página
Objetivo, stack, a quién preguntar, cómo desplegar, qué no tocar. Cuando vuelvo a un proyecto después de dos semanas, esa página me hace productivo en minutos y no en horas. La guardo en el repositorio, junto al código.
La documentación es un entregable
Escribo las notas de entrega mientras avanzo, no al final. Pasos de instalación, decisiones y sus razones, problemas conocidos. Es la diferencia entre un cliente que depende de ti y un cliente que confía en ti.
Automatiza el trabajo repetido
- Scripts para el entorno local y el despliegue.
- Listas de verificación para el lanzamiento: metadatos, redirecciones, indexación, analítica.
- Una revisión de QA estándar en cada proyecto antes de salir.
Automatizar procesos no es glamoroso, pero es lo que permite que un desarrollador atienda muchos proyectos sin perder detalles.
Comunica temprano y por escrito
Las malas noticias viajan mejor temprano. Un mensaje corto que diga qué se atrasa, por qué y cuál es el nuevo plan mantiene tranquilo al cliente. Las actualizaciones escritas también protegen a ambos lados cuando la memoria se vuelve borrosa.
Dónde ayuda la IA y dónde no
La IA es excelente para el costo del cambio de contexto: resumir un código desconocido, recordarme cómo funciona un plugin, redactar las partes aburridas de la documentación. Es mala para saber qué valora un cliente en particular o qué atajo lo va a perjudicar después. Ese criterio es tuyo.
Protege tu tiempo de aprendizaje
Cuando estás ocupado, lo primero que se pierde es aprender, y las herramientas cambian cada pocos meses. Yo reservo un espacio pequeño y fijo cada semana para leer y experimentar. Es el seguro más barato que puede comprar un desarrollador.