The Next Craft × Crafter Station · 12h in-person hackathon · Lima · Bogotá · Guatemala · Arequipa · El Salvador

Thoughts

Cómo estoy creando y desplegando proyectos en Crafter Station

Cómo pasé de escribir cada archivo a definir el producto y dejar que los agentes se encarguen del repositorio, el Docker, la base de datos, el dominio y el deployment.

Herramientas del flujo: GrillMe · Claude Code · VPS CLI · Spaceship CLI · Dokploy · UploadX


Últimamente mi forma de crear aplicaciones en Crafter Station ha ido cambiando bastante, sobre todo porque cada vez que hago un proyecto nuevo me doy cuenta de que hay muchas cosas que termino haciendo de la misma manera.

Todo empieza con una idea

Al comienzo, cuando quieres hacer una aplicación, piensas principalmente en el código: qué framework vas a utilizar, cómo vas a hacer el frontend, qué base de datos necesitas, cómo vas a guardar la información y cosas así. Pero después, cuando empiezas a tener varios proyectos, te das cuenta de que alrededor de todo eso también hay bastante trabajo que se repite: crear el repositorio, configurar el proyecto, preparar Docker, crear la base de datos, configurar las variables de entorno, desplegarlo en algún servidor, configurar el dominio, revisar los logs, volver a desplegar cuando algo falla y así sucesivamente.

Entonces, poco a poco, he ido intentando que todas esas partes que se repiten puedan hacerlas los agentes, principalmente Claude Code, utilizando las herramientas que yo mismo he ido creando para Crafter Station. La idea es que, una vez que tengo claro qué quiero hacer, pueda dejarle bastante del trabajo de implementación, configuración y deployment, y yo pueda concentrarme más en definir el producto y probar que realmente funciona como quiero.

Normalmente todo empieza con una idea. A veces es una idea bastante pequeña y otras veces es algo que desde el comienzo sé que va a tener varias partes. Puede ser una aplicación web, una API, algo que necesita autenticación, una aplicación que tiene que trabajar con archivos, algún proyecto que utiliza inteligencia artificial o incluso algo que termina necesitando un CLI, un SDK y varios servicios diferentes. No siempre sé exactamente cómo va a terminar el proyecto cuando empiezo, pero sí intento tener bastante claro qué es lo que quiero construir antes de ponerme a escribir código.

Para esa parte estoy utilizando GrillMe. Lo que me gusta de GrillMe es que no necesito llegar necesariamente con una especificación enorme ya preparada. Puedo tener una idea general y empezar a conversar sobre ella, y a partir de ahí voy agregando los requerimientos que considero importantes. Si el proyecto necesita una base de datos, entonces definimos qué información necesito guardar y cómo debería ser el esquema. Si necesito procesar archivos, vemos qué necesito hacer con esos archivos. Si necesito autenticación, definimos cómo va a funcionar. Si hay una API, vemos qué endpoints voy a necesitar. También puedo ir definiendo cosas como el dominio que quiero utilizar, el repositorio donde va a vivir el proyecto, qué base de datos quiero utilizar o qué tecnologías quiero usar.

No siempre hago este proceso con el mismo nivel de detalle. Si voy a hacer algo muy pequeño, no tiene mucho sentido que pase horas haciendo una especificación enorme para una aplicación que probablemente tenga cinco funcionalidades. Pero cuando el proyecto empieza a tener más requerimientos, sí prefiero dedicarle un poco más de tiempo a esta parte, porque después Claude Code va a utilizar toda esa información para construir la aplicación y mientras más claro tenga desde el principio qué es lo que quiero, menos cosas tengo que corregir después.

Después paso a Claude Code y a la infraestructura

Una vez que ya tengo esa parte más o menos definida, paso a Claude Code. Y aquí es donde está una de las partes que más ha cambiado mi forma de trabajar, porque ya no estoy pensando necesariamente en escribir yo mismo cada archivo del proyecto. Le doy el contexto que hemos definido, le explico lo que quiero y dejo que vaya implementando las diferentes partes. Puede crear el proyecto, crear los archivos, implementar las funcionalidades, preparar la base de datos, crear los endpoints, hacer los componentes de frontend y, dependiendo de lo que necesite el proyecto, también puede trabajar con diferentes servicios.

Pero además de escribir código, Claude Code tiene acceso a las herramientas que utilizo alrededor del proyecto. Esto es bastante importante porque el desarrollo no termina cuando tienes los archivos en tu computadora. Después tienes que hacer algo con esos archivos: tienes que subirlos a GitHub, construir la aplicación, desplegarla, configurar el dominio, revisar si funciona y todo lo demás que normalmente ocurre alrededor del código.

Por eso una de las cosas que hice para Crafter fue crear un VPS CLI para administrar mi infraestructura. Yo normalmente parto de un VPS de Contabo donde tengo Dokploy, y Dokploy es el lugar donde estoy manejando mis aplicaciones, deployments, bases de datos, dominios, variables de entorno y demás. Dokploy tiene una API REST y una API key, así que en lugar de tener que entrar constantemente al dashboard para hacer estas operaciones, hice un CLI que puede comunicarse con esa API.

El VPS CLI básicamente me permite hacer desde la terminal muchas de las cosas que haría desde Dokploy. Puedo crear proyectos, aplicaciones, bases de datos, dominios, hacer deployments, volver a desplegar una aplicación, iniciar o detener servicios, revisar logs, configurar variables de entorno y trabajar también con diferentes tipos de recursos como PostgreSQL, MySQL, MariaDB, Redis, MongoDB o LibSQL. Además, como puedo tener diferentes perfiles, puedo trabajar con más de un VPS sin tener que cambiar manualmente toda la configuración cada vez.

Entonces, por ejemplo, si Claude Code está construyendo una aplicación que necesita PostgreSQL, no necesariamente tengo que detenerme, abrir Dokploy, entrar al servidor, crear la base de datos y luego copiar manualmente la información de conexión al proyecto. El agente puede utilizar el VPS CLI para crear ese recurso y obtener la información que necesita para continuar. Lo mismo ocurre cuando llega el momento de desplegar la aplicación, porque el deployment también puede formar parte del flujo que está ejecutando Claude Code.

HerramientaPara qué la uso
VPS CLITrabajar con la infraestructura de Dokploy desde la terminal y desde los agentes
DokployGestionar aplicaciones, bases de datos, dominios, variables y deployments en el VPS
Spaceship CLICrear los registros DNS de los dominios sin entrar al dashboard
UploadXArchivos y uploads sin montar una instancia nueva por proyecto

Los dominios funcionan de una manera bastante parecida

Para los proyectos de Crafter normalmente utilizo crafter.run, y cuando creo una aplicación nueva intento utilizar un subdominio relativamente corto, porque crafter.run ya tiene cierta longitud y no quiero terminar con dominios demasiado grandes. Por ejemplo, uno de los proyectos puede terminar en algo como wapi.crafter.run.

Para que eso funcione hay dos cosas que tengo que hacer. Primero tengo que crear el registro DNS, normalmente un registro A que apunta al IP del VPS, y después tengo que registrar ese dominio dentro de Dokploy para que la aplicación pueda recibir el tráfico. Para la parte de DNS utilizo Spaceship y también tengo un CLI para Spaceship, así que Claude Code puede crear ese registro automáticamente. Después puede registrar el dominio dentro de Dokploy y configurar el HTTPS, que normalmente termina utilizando Let’s Encrypt.

flowchart TD
    CC[Claude Code] --> V[VPS CLI]
    CC --> S[Spaceship CLI]
    V --> D[Dokploy]
    S --> DNS["DNS · registro A al IP del VPS"]
    D --> APP["https://app.crafter.run"]
    DNS --> APP

La aplicación no siempre es solamente una aplicación

Después está la parte de la arquitectura, que también intento mantener bastante relacionada con el proyecto que estoy haciendo. No tengo una arquitectura única que utilice para absolutamente todo. Si estoy haciendo una aplicación pequeña, probablemente tenga Next.js, PostgreSQL y Drizzle, y si necesito autenticación puedo agregar Clerk. Si necesito archivos, puedo utilizar UploadX. Y con eso probablemente sea suficiente.

No intento crear una arquitectura enorme solamente porque algún día el proyecto podría crecer. Si tengo una aplicación pequeña, prefiero mantenerla pequeña. Por ejemplo, si tengo una aplicación con unos cuantos productos, algunas páginas, autenticación y una base de datos, no necesito convertirla desde el primer día en diez servicios diferentes solamente porque existe la posibilidad de que algún día tenga más funcionalidades.

Cuando el proyecto realmente empieza a tener más cosas, ahí sí cambia la forma en que lo organizo. Si tengo diferentes dominios dentro de la aplicación, muchos requerimientos, procesos que tienen que ejecutarse por separado, workers, colas, una API grande, diferentes SDKs o un CLI, entonces ya tiene más sentido separar las cosas. En esos proyectos puedo terminar utilizando diferentes módulos, servicios, handlers, repositorios y modelos dependiendo de lo que necesite cada parte.

Un ejemplo de esto sería un proyecto que no solamente tiene una aplicación web, sino que además tiene una API, un worker para procesar tareas, un servicio que mantiene algún estado y otros componentes que necesitan comunicarse entre sí. En ese caso normalmente utilizo Docker Compose para poder desplegar todo como una unidad dentro de Dokploy. Cada servicio puede tener su propio container y pueden comunicarse internamente a través de la red de Docker, sin que necesariamente tenga que exponer cada servicio públicamente.

Por ejemplo, puedo tener una aplicación web que sí tiene un dominio público, mientras que PostgreSQL y Redis permanecen dentro de la red interna. Una API puede estar disponible solamente para otros servicios y un worker puede estar ejecutándose en segundo plano. Todo eso termina siendo parte del mismo deployment, dependiendo de lo que necesite el proyecto.

Y una cosa que intento mantener desde el comienzo es que la aplicación esté preparada para funcionar dentro de Docker. En proyectos de Next.js, por ejemplo, hay algunos detalles que tengo que cuidar para que el tráfico pueda llegar correctamente desde Traefik hasta el container, como hacer que la aplicación escuche en 0.0.0.0 y configurar correctamente el puerto. Son detalles que si ya los conoces no son complicados, pero si no los tienes en cuenta puedes terminar con una aplicación que aparentemente está desplegada pero que desde el dominio no responde como esperas.

Trabajar por fases

Una vez que la estructura está definida, normalmente no intento construir todo el proyecto de una sola vez. Prefiero trabajar por fases. Esto también me ayuda bastante con Claude Code porque puedo darle una parte concreta del proyecto, hacer que la implemente, probarla y recién después pasar a la siguiente.

Entonces puede existir una primera fase en la que simplemente hago la aplicación principal y la base de datos. Después puedo agregar autenticación, luego alguna funcionalidad más específica, después integración con archivos, después una API o lo que necesite el proyecto. No necesariamente todas las aplicaciones tienen las mismas fases, pero la idea es ir construyendo sobre algo que ya funciona.

Y dentro de cada fase el proceso termina siendo bastante parecido. Claude Code implementa lo que definimos, hace las verificaciones que pueda hacer por su cuenta, después el código se guarda en GitHub y se hace el deployment en el VPS. Una vez que la aplicación está desplegada, yo entro y la pruebo.

flowchart TD
    P[Planificar] --> I[Implementar]
    I --> T[Probar]
    T --> G[GitHub]
    G --> DEP[Deploy en el VPS]
    DEP --> M[Probar como usuario]
    M -->|OK| N[Siguiente fase]
    M -->|Error| CTX["Contexto: error, logs, trace ID"]
    CTX --> CC[Claude Code]
    CC --> FIX[Corregir y verificar]
    FIX --> DEP

Para GitHub también dejo bastante trabajo al agente. Normalmente utilizo el GitHub CLI, gh, y Claude Code puede crear el repositorio, hacer commits, hacer push y manejar las diferentes operaciones que necesite el proyecto. En general suelo trabajar directamente sobre main y trato de que los commits sean lo más atómicos posible, aunque dependiendo del proyecto también puedo trabajar con pull requests y después hacer el merge a main. Si el proyecto lo necesita, también puedo configurar GitHub Actions para que ejecute los tests y el linting.

Lo más importante viene después del deployment

Para mí una de las partes más importantes de todo este proceso viene después del deployment, porque ahí es donde yo entro nuevamente de una manera bastante directa. Cuando termino una fase, abro la aplicación y la utilizo como si fuera un usuario. Navego por las diferentes partes, sigo el flujo que tendría que seguir una persona, creo información, pruebo las funcionalidades y también miro si el diseño realmente quedó como esperaba.

No hago necesariamente una revisión de código línea por línea. En este momento mi revisión es más de alto nivel: quiero que el código sea entendible, que esté bien organizado, que no tenga cosas innecesarias y que tenga los patrones que realmente necesita el proyecto. Pero sobre todo quiero comprobar que la aplicación funciona.

Porque puede pasar perfectamente que Claude Code termine una funcionalidad, los tests pasen y la aplicación compile, pero cuando yo entro a utilizarla me doy cuenta de que el flujo no es exactamente como lo imaginaba. Puede ser que una pantalla necesite otro comportamiento, que un formulario debería funcionar de otra manera o que alguna parte del diseño no tenga sentido. En esos casos simplemente vuelvo al agente y le explico qué encontré.

Y aquí intento darle toda la información posible. Si tengo un error, le paso el error. Si hay logs, le paso los logs. Si existe un trace ID, también se lo paso. Si puedo obtener información del container o algún otro detalle de lo que ocurrió, también se lo doy. Me parece que mientras más contexto tenga el agente sobre el problema, menos tiene que intentar adivinar qué está pasando.

Entonces Claude Code puede investigar el problema, revisar los archivos involucrados, hacer los cambios necesarios y volver a intentar las pruebas. Si puede hacer pruebas integradas o alguna verificación automatizada, también puede hacerlo. Después vuelve a desplegar y yo vuelvo a probar la aplicación.

Una fase no termina cuando Claude Code dice que terminó de implementar algo. Termina cuando yo la probé y estoy conforme tanto con el funcionamiento como con el diseño.

Si encuentro algo que no me gusta, todavía no está terminada, aunque técnicamente el código ya esté funcionando.

Y cuando ya tengo una funcionalidad funcionando, intento que las siguientes cosas sean compatibles con lo que ya existe. Esto se vuelve cada vez más importante a medida que el proyecto crece, porque no quiero implementar una nueva funcionalidad y terminar rompiendo algo que ya estaba funcionando. Entonces, cuando Claude Code trabaja en una fase nueva, también tiene que considerar lo que ya existe en el proyecto y mantener ese comportamiento siempre que sea posible.

También hay proyectos donde entra la inteligencia artificial

Otra parte que aparece bastante en los proyectos que hago es la inteligencia artificial. Dependiendo de lo que estoy construyendo, puedo integrar modelos de IA dentro de la aplicación, y normalmente utilizo OpenAI junto con AI SDK. Me gusta AI SDK porque es bastante sencillo de utilizar, especialmente cuando estoy trabajando con Next.js, y además me permite mantener la aplicación un poco más independiente del proveedor que estoy utilizando.

Por ejemplo, si hoy estoy utilizando un modelo de OpenAI pero mañana quiero probar otro proveedor, prefiero no tener toda mi aplicación directamente acoplada al SDK de ese proveedor. AI SDK me permite tener una capa que hace que ese cambio sea más sencillo. Y cuando necesito algo que AI SDK no me da, puedo utilizar directamente el SDK de OpenAI, pero incluso en ese caso puedo poner una abstracción propia, por ejemplo una interfaz y diferentes implementaciones, para que el resto de la aplicación no tenga que conocer todos los detalles del proveedor.

Por ahora OpenAI es lo que utilizo principalmente porque es lo que me funciona y es donde actualmente tengo créditos. También podría probar otros modelos o proveedores más adelante, incluyendo opciones como DeepSeek, Kimi u otros modelos open source, pero hasta ahora no he tenido una razón suficientemente fuerte para cambiar ese flujo. Si más adelante encuentro un caso donde el precio, rendimiento o alguna capacidad específica haga sentido, puedo agregarlo.

Muchas de estas herramientas fueron apareciendo mientras construía

Y algo parecido ha pasado con las herramientas que utilizo alrededor de los proyectos. Muchas de ellas las fui creando porque me encontré varias veces con el mismo problema. El VPS CLI salió de querer administrar el VPS sin tener que hacer todo manualmente desde el dashboard. El CLI de Spaceship salió de querer automatizar los dominios. UploadX salió de que no quería tener que configurar una instancia nueva de MinIO para cada proyecto que necesitara archivos, así que terminé creando una especie de servicio centralizado que puedo reutilizar.

Eso también hace que cada proyecto nuevo sea un poco diferente al anterior, pero al mismo tiempo aproveche cosas que ya existen. Si necesito autenticación, puedo utilizar Clerk, porque es una herramienta que conozco bastante y que además puedo manejar con las herramientas que ya tengo. Si necesito archivos, puedo utilizar UploadX. Si necesito PostgreSQL, puedo crearlo dentro de mi infraestructura. Si necesito Redis, puedo hacer lo mismo. Si necesito un dominio, tengo el CLI de Spaceship. Y si necesito desplegar, tengo Dokploy y el VPS CLI.

Entonces, con el tiempo, el proceso empieza a tener menos cosas que tengo que repetir manualmente.

Y creo que esa es una de las partes que más me interesa de todo este workflow. No estoy intentando hacer una metodología completamente diferente para cada proyecto, sino que cada vez que encuentro una parte que estoy repitiendo demasiado, intento ver si puedo convertirla en una herramienta o automatizarla de alguna manera. Si algo se repite en todos los proyectos, probablemente tiene sentido que exista una herramienta para eso. Si algo solamente ocurre en un proyecto, probablemente no necesito crear una abstracción solamente por crearla.

Al final, el flujo termina siendo bastante parecido

Al final, mi forma de trabajar termina siendo algo bastante parecido a una conversación larga con el proyecto. Primero tengo la idea y voy definiendo qué quiero construir. Después utilizo GrillMe para aterrizar los requerimientos cuando hace falta y paso esa información a Claude Code. Claude Code empieza a implementar, utiliza las herramientas que tiene disponibles, crea el código y prepara el proyecto. Después ese proyecto termina en GitHub, se construye con Docker y se despliega en mi VPS utilizando Dokploy. Cuando necesita un dominio, puede utilizar Spaceship para crear el DNS y después registrar ese dominio en Dokploy.

flowchart TD
    YO["Yo · idea, requisitos, decisiones"] --> GM[GrillMe]
    GM --> CC[Claude Code]
    CC --> GH[GitHub]
    CC --> VC[VPS CLI]
    CC --> SC[Spaceship CLI]
    SC --> DK[Dokploy]
    VC --> DK
    GH --> PR[Producción]
    DK --> PR
    PR --> TM[Prueba manual]
    TM -->|OK| SF[Siguiente fase]
    TM -->|Error| CX["Contexto: error, logs, trace ID"]
    CX --> CC

Una vez que está desplegado, yo entro a la aplicación y la pruebo. Si encuentro algo que no funciona o que no quedó como esperaba, le paso el contexto al agente y volvemos a esa parte del proceso. Claude Code investiga, hace los cambios, vuelve a probar y despliega otra vez. Cuando finalmente yo pruebo la funcionalidad y estoy conforme con cómo funciona y cómo se ve, considero que esa fase ya está terminada y podemos continuar con la siguiente.

Y después simplemente vuelvo a repetir el proceso.

Eso es más o menos cómo estoy construyendo proyectos actualmente en Crafter Station. Hay una parte importante que sigue dependiendo de mí, que es decidir qué quiero construir, definir los requerimientos, tomar las decisiones que considero necesarias y probar el resultado. Pero alrededor de eso tengo cada vez más herramientas que hacen que Claude Code pueda encargarse de una parte bastante grande del trabajo que antes tenía que hacer manualmente.

Y creo que lo interesante es que este sistema no apareció completo desde el principio. El VPS CLI, el CLI de Spaceship, UploadX, las skills y el resto de herramientas fueron apareciendo porque las necesitaba mientras iba construyendo proyectos. Entonces, en lugar de tener que resolver nuevamente el mismo problema cada vez que empiezo algo nuevo, voy dejando preparada esa parte para el siguiente proyecto.

Al final, eso me permite que cuando tengo una nueva idea no tenga que volver a empezar desde cero con toda la infraestructura que existe alrededor de una aplicación. Puedo concentrarme en definir lo que quiero hacer, construirlo por fases, probarlo y, si encuentro algo que se repite, intentar automatizarlo para que la próxima vez también forme parte del proceso.

← all thoughts