<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ayoze Barrera</title>
    <description>The latest articles on DEV Community by Ayoze Barrera (@ayozebarrera).</description>
    <link>https://dev.to/ayozebarrera</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F232522%2Fc70ed0c6-13fb-4c77-8055-70c8d8386c7b.png</url>
      <title>DEV Community: Ayoze Barrera</title>
      <link>https://dev.to/ayozebarrera</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayozebarrera"/>
    <language>en</language>
    <item>
      <title>Spren: mi workspace de escritorio para programar con agentes</title>
      <dc:creator>Ayoze Barrera</dc:creator>
      <pubDate>Thu, 07 May 2026 15:19:39 +0000</pubDate>
      <link>https://dev.to/ayozebarrera/spren-mi-workspace-de-escritorio-para-programar-con-agentes-2hm</link>
      <guid>https://dev.to/ayozebarrera/spren-mi-workspace-de-escritorio-para-programar-con-agentes-2hm</guid>
      <description>&lt;p&gt;Hace poco escribí sobre cómo &lt;a href="https://dev.to/ayozebarrera/de-ticket-a-deploy-sin-tocar-nada-como-claude-code-orquesta-mi-flujo-entero-2kpm"&gt;Claude Code y un CLI propio (&lt;code&gt;tv&lt;/code&gt;) me ahorran 15 minutos de secretariado por ticket&lt;/a&gt;. Funcionó tan bien que me destapó el siguiente cuello de botella: aunque ya no copiaba títulos a mano ni creaba ramas manualmente, mi pantalla seguía teniendo abiertas siete ventanas distintas. Timeview en una pestaña del navegador para ver tareas, GitLab en otra para ver el pipeline,  terminal con Claude Code corriendo, VSCode al lado, notas sueltas en otra app y Gemini cuando quería mejorar algún texto.&lt;/p&gt;

&lt;p&gt;El secretariado por ticket lo había resuelto. &lt;strong&gt;El context-switching seguía intacto.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spren es lo que construí para resolverlo: una app de escritorio que junta en una sola pantalla todo lo que mi día a día necesita. Terminal con tabs, estado de git en tiempo real, el panel de tareas de Timeview, las notificaciones, el estado del pipeline en GitLab, mi cuota de Claude, un widget de Gemini para preguntas rápidas, y un par de cosas más (TODO, pomodoro, recordatorio para beber agua). En este artículo te cuento cómo está montada y, sobre todo, por qué cada decisión de diseño es la que es, por si te da ideas para hacer tu propio workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zn53zlh8m41a3mmj3iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zn53zlh8m41a3mmj3iw.png" alt=" " width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  El problema: la app perfecta no existía
&lt;/h2&gt;

&lt;p&gt;Cada uno tiene su forma de trabajar.&lt;/p&gt;

&lt;p&gt;Warp es una buena terminal. Raycast es un buen launcher. Notion es buena para notas. Pero ninguna de estas resolvía mi problema: yo no necesitaba &lt;strong&gt;otra app más&lt;/strong&gt;, necesitaba &lt;strong&gt;una app menos&lt;/strong&gt;. Una que sustituyera a varias.&lt;/p&gt;

&lt;p&gt;El problema con las soluciones existentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Demasiado generales&lt;/strong&gt;: dashboards corporativos que muestran 200 cosas que no me importan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demasiado específicas&lt;/strong&gt;: cada app hace bien una cosa, y cuando combinas cinco apps tienes el mismo problema de partida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sin integración con mi stack real&lt;/strong&gt;: ninguna se conecta a Timeview ni a mi GitLab self-hosted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quería algo hecho a medida de mi flujo. Y la única forma de conseguirlo, era creando a Spren.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En el Cosmere, los spren son entidades que se manifiestan cuando las necesitas y se vinculan a quien las invoca&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Las decisiones de stack que importan
&lt;/h2&gt;

&lt;p&gt;Spren es una app de escritorio para macOS hecha con &lt;strong&gt;Electron + React + JavaScript&lt;/strong&gt;. No TypeScript, no Tauri, no nada exótico. Te explico por qué cada elección.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Electron sobre Tauri&lt;/strong&gt;: Tauri es más ligero pero su ecosistema de Node es menor. Yo necesitaba &lt;code&gt;node-pty&lt;/code&gt; para terminales reales, &lt;code&gt;simple-git&lt;/code&gt; para integración nativa con git, &lt;code&gt;chokidar&lt;/code&gt; para watching del filesystem, y la API de &lt;code&gt;safeStorage&lt;/code&gt; de Electron para cifrar tokens. Todo eso son problemas resueltos en Electron y problemas a resolver en Tauri. Para una app personal, era el camino claro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript sobre TypeScript&lt;/strong&gt;: decisión consciente. Iteración rápida, pocos colaboradores, y una codebase que no espero que crezca a 50.000 líneas. El coste de tipar todo no compensa el beneficio. (Si esto fuera una app pública con equipo, sería TypeScript sin pensarlo).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;electron-vite como starter&lt;/strong&gt;: HMR funcional, configuración mínima, no me peleo con webpack ni con builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TanStack Query para todo lo que viene de red&lt;/strong&gt;: cache, retry, refetch, polling adaptativo. Si tu UI hace peticiones HTTP, TanStack Query te ahorra el 80% del código de estado... y me encanta!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;xterm.js + node-pty para las terminales&lt;/strong&gt;: las terminales son &lt;strong&gt;reales&lt;/strong&gt;, con shell, history, ANSI colors, todo. Cada tab tiene su propio proceso pty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;safeStorage para tokens&lt;/strong&gt; (no &lt;code&gt;keytar&lt;/code&gt;): la primera versión usaba &lt;code&gt;keytar&lt;/code&gt; y dio problemas con el code-signing. &lt;code&gt;safeStorage&lt;/code&gt; de Electron es nativo, sin dependencias compiladas, y suficiente para uso personal. Los tokens viven cifrados en &lt;code&gt;~/Library/Application Support/spren/secrets.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sin SQLite&lt;/strong&gt;: lo consideré pero no lo necesité. Para los datos que persisto (TODO items, settings, code projects, mappings) un JSON plano vía un módulo &lt;code&gt;settingsManager&lt;/code&gt; es más que suficiente. Si en el futuro quiero historial de pomodoros con gráficas, ahí sí entrará SQLite.&lt;/p&gt;




&lt;h2&gt;
  
  
  La arquitectura, en una imagen mental
&lt;/h2&gt;

&lt;p&gt;Spren tiene tres procesos, como cualquier app de Electron:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Main process&lt;/strong&gt;: todo lo sensible vive aquí — credenciales, llamadas HTTP a APIs externas, ejecución de procesos pty, watchers del filesystem, lectura del Keychain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preload&lt;/strong&gt;: un puente tipado vía &lt;code&gt;contextBridge&lt;/code&gt; que expone al renderer solo lo que tiene que poder llamar (&lt;code&gt;window.api.timeview.getMyTasks(...)&lt;/code&gt; y similares).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Renderer&lt;/strong&gt;: solo React, solo UI. &lt;strong&gt;El renderer nunca toca tokens, nunca lee archivos del usuario directamente, nunca llama a APIs externas.&lt;/strong&gt; Todo va por IPC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esta separación es &lt;strong&gt;innegociable&lt;/strong&gt; y vale la pena explicarla porque es lo que permite que una app así sea segura. Si el renderer pudiera acceder a tokens, cualquier vulnerabilidad de XSS comprometería tus credenciales de Timeview, GitLab y Gemini de golpe. Como no puede, el peor caso es que un script malicioso pida llamadas a tu API, pero nunca verá los tokens.&lt;/p&gt;




&lt;h2&gt;
  
  
  El layout: cuatro columnas que cuentan una historia
&lt;/h2&gt;

&lt;p&gt;La pantalla principal (HOME) son cuatro columnas verticales:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TERMINAL (flex)  |  GIT (320px)  |  TIMEVIEW (400px)  |  WIDGETS (400px)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El orden no es casual. &lt;strong&gt;Cuenta una historia de izquierda a derecha&lt;/strong&gt;: dónde estoy escribiendo código, qué estado tiene mi código localmente, qué tengo pendiente y qué está pasando en mi sistema de tareas, y herramientas auxiliares.&lt;/p&gt;

&lt;h3&gt;
  
  
  Columna 1: TERMINAL
&lt;/h3&gt;

&lt;p&gt;Multi-tab con &lt;code&gt;Cmd+T&lt;/code&gt;, &lt;code&gt;Cmd+W&lt;/code&gt;, &lt;code&gt;Cmd+1..9&lt;/code&gt;. Cada tab es un pty real con su propio shell, su propio cwd, su propio history. Cuando hago &lt;code&gt;cd&lt;/code&gt; en una tab, el resto sigue donde estaba.&lt;/p&gt;

&lt;p&gt;Lo más importante: el cwd activo de la tab actual &lt;strong&gt;alimenta a las demás columnas&lt;/strong&gt;. La columna GIT mira al repo donde estoy. La columna TIMEVIEW resalta el proyecto correspondiente. Si cambio de tab, todo se actualiza.&lt;/p&gt;

&lt;h3&gt;
  
  
  Columna 2: GIT
&lt;/h3&gt;

&lt;p&gt;Lee el repo del cwd actual con &lt;code&gt;simple-git&lt;/code&gt; y vigila cambios con &lt;code&gt;chokidar&lt;/code&gt;. Muestra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Branch actual&lt;/strong&gt;, ahead/behind, tracking de upstream.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archivos modificados / staged / untracked&lt;/strong&gt;, con counters.&lt;/li&gt;
&lt;li&gt;**Diff: puedo ver que ha cambiado en cada fichero sin abrir el IDE.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bloque GITLAB&lt;/strong&gt;: estado del MR de la rama actual (draft / opened / merged), último pipeline del proyecto (running / passed / failed), con botón "open in browser" que dispara &lt;code&gt;shell.openExternal&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Detalle de UX: &lt;strong&gt;el bloque GITLAB solo aparece si hay datos relevantes&lt;/strong&gt;. Si estoy en main sin MR, no aparece. Cero ruido.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl404t1g7bogy6588l2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl404t1g7bogy6588l2u.png" alt="GIT panel" width="364" height="975"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Columna 3: TIMEVIEW
&lt;/h3&gt;

&lt;p&gt;Tres bloques verticales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MY TASKS&lt;/strong&gt;: lista paginada de mis tareas, con toggle entre "asignadas a mí" y "sin asignar". Cada item muestra estado, id, título, tags y a quién está asignado. Paginación con scroll infinito vía TanStack Query.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UNREADS COUNTERS&lt;/strong&gt;: cuatro contadores horizontales (rooms / tasks / notifs / docs) que vienen de de Timeview. Sirven como panorama general.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTIFICATIONS&lt;/strong&gt;: lista de notificaciones, con borde izquierdo rojo destacado para las no leídas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click en una tarea me lleva al detalle. Y desde el detalle puedo escribir comentarios para "preparar el terreno" antes de delegar la tarea a Claude. Eso enlaza con el punto siguiente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Columna 4: WIDGETS
&lt;/h3&gt;

&lt;p&gt;Una pila vertical: TODO, Gemini, Claude Usage, Pomodoro, Water. Cada uno hace una cosa y la hace bien. Aquí los más interesantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TODO&lt;/strong&gt;: items locales con &lt;code&gt;done: false/true&lt;/code&gt;, ordenados pendientes-arriba completados-abajo, con botón "clear done" para limpiar de golpe. Persistencia en &lt;code&gt;settingsManager&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini&lt;/strong&gt;: input + send + área de respuesta con streaming. Para "cambia esta frase a algo más profesional" o "tradúceme esto rápido". Modelo hardcoded a &lt;code&gt;gemini-2.5-flash&lt;/code&gt; con tier gratuito. Evita salir a otra pestaña.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Usage&lt;/strong&gt;: muestra mi cuota actual (5h / 7d / opus) leída del endpoint OAuth interno de Claude Code. Barras ASCII, color verde / ámbar / rojo según umbral. Toggleable porque es un endpoint &lt;strong&gt;undocumented&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwew9uy4u20m1x0b7uyuq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwew9uy4u20m1x0b7uyuq.png" alt="Widgets panel" width="410" height="976"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  La pieza que cierra el bucle: "Trabaja en esta tarea"
&lt;/h2&gt;

&lt;p&gt;El flujo completo entre Spren y mi CLI &lt;code&gt;tv&lt;/code&gt; es esto:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Llega una notificación de Timeview a la columna correspondiente.&lt;/li&gt;
&lt;li&gt;Click en la tarea, se abre el detalle.&lt;/li&gt;
&lt;li&gt;Si necesito añadir contexto antes de delegar, escribo un comentario directamente desde Spren (pasa por la API de Timeview).&lt;/li&gt;
&lt;li&gt;Cuando estoy listo, click en &lt;strong&gt;"trabaja en esta tarea"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Spren abre una tab nueva con el cwd en el code project que elija (los tengo configurados en Settings, uno por repo local), ejecuta &lt;code&gt;claude&lt;/code&gt; con un prompt que invoca &lt;code&gt;tv tasks work &amp;lt;id&amp;gt;&lt;/code&gt;, y a partir de ahí Claude se encarga del resto del flujo descrito en el artículo anterior.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8rqfegxdtk8jbpndb88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8rqfegxdtk8jbpndb88.png" alt="Task" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un detalle interesante es el &lt;strong&gt;selector de code project&lt;/strong&gt;. Una tarea de Timeview no tiene relación 1:1 con un repo. La tarea es "implementar X feature"; el repo donde se resuelve depende de qué área toques (frontend, backend, desktop, mobile). En mi equipo, una misma tarea puede resolverse en &lt;code&gt;timeview/desktop&lt;/code&gt;, &lt;code&gt;timeview/app&lt;/code&gt; o &lt;code&gt;timeview/api&lt;/code&gt; según corresponda. Y cada developer tiene su propia ruta local para cada repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fap9uojai92uy8pbgrboh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fap9uojai92uy8pbgrboh.png" alt="Code projects" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por eso Spren guarda una lista de "code projects" — pares &lt;code&gt;nombre + ruta local&lt;/code&gt; que tú das de alta. Cuando le doy a "trabaja en esta tarea", el botón muestra "trabaja en esta tarea en &lt;code&gt;&amp;lt;nombre&amp;gt;&lt;/code&gt;" y, si tengo más de uno, aparece un dropdown para cambiar antes de pulsar. Recuerda mi última elección entre sesiones.&lt;/p&gt;




&lt;h2&gt;
  
  
  Decisiones de diseño que cambiaron el resultado
&lt;/h2&gt;

&lt;p&gt;Tres elecciones que parecen menores pero hicieron mucho:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Cero polling agresivo, refresh inteligente.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mi primera versión hacía polling cada 30 segundos a Timeview, GitLab y Gemini. Resultado: la app consumía mucho innecesariamente y Anthropic / GitLab / Timeview veían tráfico constante mío.&lt;/p&gt;

&lt;p&gt;La versión actual usa &lt;code&gt;refetchInterval&lt;/code&gt; adaptativo de TanStack Query. Por ejemplo: el pipeline de GitLab se refresca cada 10 segundos &lt;strong&gt;si está running&lt;/strong&gt;, cada 60 segundos si está en estado terminal. Las notificaciones de Timeview, refresh manual con botón. La cuota de Claude, cada 5 minutos.&lt;/p&gt;

&lt;p&gt;Misma sensación de "estoy al día", una décima parte del tráfico.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Keep-alive vs unmount.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spren tiene tres secciones (HOME, TIMEVIEW, SETTINGS). Cuando cambias de sección, la anterior &lt;strong&gt;no se desmonta&lt;/strong&gt;. Sigue viva pero invisible (&lt;code&gt;visibility: hidden + position: absolute&lt;/code&gt;). Las terminales siguen corriendo, las queries mantienen su estado, no se pierde nada.&lt;/p&gt;

&lt;p&gt;Esto resolvió un bug famoso de xterm: si la columna terminal se desmontaba con &lt;code&gt;display: none&lt;/code&gt;, al volver el contenedor tenía dimensiones 0×0, &lt;code&gt;fitAddon.fit()&lt;/code&gt; calculaba 5 filas, y el pty perdía scrollback. Visualmente parecía que la terminal se había encogido. La solución de &lt;code&gt;visibility: hidden + position: absolute&lt;/code&gt; mantiene dimensiones reales todo el tiempo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Errores tipados en cada cliente HTTP.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cada integración (Timeview, GitLab, Gemini) tiene sus propios errores tipados con un campo &lt;code&gt;.code&lt;/code&gt;: &lt;code&gt;TIMEVIEW_AUTH_FAILED&lt;/code&gt;, &lt;code&gt;GITLAB_NETWORK&lt;/code&gt;, &lt;code&gt;GEMINI_RATE_LIMIT&lt;/code&gt;, etc. Los IPC handlers nunca lanzan a través del bridge — siempre devuelven &lt;code&gt;{ ok: true, data }&lt;/code&gt; o &lt;code&gt;{ ok: false, error: { code, message } }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cuando veo un error en Spren, se exactamente qué pasa: "TOKEN no es válido" en lugar de "Network error". Y el código de UI puede mapear cada &lt;code&gt;code&lt;/code&gt; a un mensaje específico y a una acción ("ir a Settings", "reintentar", "abrir Claude Code").&lt;/p&gt;




&lt;h2&gt;
  
  
  Lecciones inespereadas
&lt;/h2&gt;

&lt;p&gt;Tres cosas que no esperaba al construir Spren:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. El context-switching no se mide en clicks, se mide en pestañas abiertas.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No es solo el coste de cambiar de Timeview a GitLab. Es el coste &lt;strong&gt;acumulado&lt;/strong&gt; de tener N pestañas abiertas todo el día, cada una pidiéndote atención visual aunque estés en otra. Ir cambiando cada cierto tiempo por si no has visto alguna notificación. Reducir mi número total de pestañas de 7 a 2 (Spren + el navegador) tiene un impacto en concentración que no esperaba.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Construir tu propia app te obliga a definir tu propio flujo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Igual que escribir el &lt;code&gt;CLAUDE.md&lt;/code&gt; me obligó a documentar reglas implícitas, construir Spren me obligó a definir qué información necesito ver constantemente y cuál no. Resultado: descubrí que no necesitaba ver "todas las tareas" — necesitaba ver "las mías". No necesitaba ver "todos los pipelines" — necesitaba ver "el último del proyecto en el que trabajo". El proceso de decidir qué meter en cada columna fue el ejercicio de productividad más útil que he hecho en mucho tiempo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Una app personal no necesita ser perfecta; necesita ser tuya.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spren no es accesible. No tiene tests automáticos. No tiene auto-update. No está firmada para distribución. No funciona en Windows ni Linux. Es deliberadamente cruda: tema oscuro hardcoded, fuente monoespaciada para todo, casi sin animaciones, una densidad de información que asustaría a un diseñador.&lt;/p&gt;

&lt;p&gt;Precisamente por eso me funciona. Cada decisión está optimizada para mi caso y solo el mío. No hay tradeoffs con casos de uso que no son los míos. Esa es la diferencia entre una app personal y un producto.&lt;/p&gt;

&lt;p&gt;Y me encanta abrirla, me encanta saber que todo lo que tengo delante es útil y cada vez que salto al navegador con frecuencia, pienso si puedo incluirlo en Spren, porque yo decido.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lo que viene
&lt;/h2&gt;

&lt;p&gt;Lo siguiente que he pensado incluir es &lt;strong&gt;agent harness&lt;/strong&gt;: un panel "AGENTS" en Spren donde pueda lanzar varias instancias de Claude Code en modo no interactivo (&lt;code&gt;claude -p&lt;/code&gt;) sobre distintas tareas, y monitorizar su progreso desde Spren — qué archivos están tocando, cuánto llevan, si terminaron OK o con error, con notificación nativa cuando completan.&lt;/p&gt;

&lt;p&gt;La idea es pasar de "lanzo Claude en una tab y miro su output, tomando decisiones" a "delego cinco tareas en paralelo y vuelvo cuando estén listas". Si funciona, escribo el siguiente artículo, pero para conseguir eso, es necesario darle a los agentes skills, tools y tareas muy claras.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cierre
&lt;/h2&gt;

&lt;p&gt;No te voy a decir que tienes que construir tu propia app de escritorio. Lo que sí te digo es: si te encuentras con siete pestañas abiertas y notas que pierdes foco saltando entre ellas, el problema no es disciplina personal. Es que tu herramienta de trabajo está fragmentada en N apps diseñadas por personas distintas con prioridades distintas.&lt;/p&gt;

&lt;p&gt;A veces la solución no es encontrar la app perfecta. Es construirla.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Si quieres ver el código de Spren, escribeme. Es deliberadamente personal — no busco contribuciones ni mantenimiento — pero las ideas son "robables". Si construyes algo similar, cuéntame!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
      <category>devops</category>
    </item>
    <item>
      <title>De ticket a deploy sin tocar nada: cómo Claude Code orquesta mi flujo entero</title>
      <dc:creator>Ayoze Barrera</dc:creator>
      <pubDate>Thu, 23 Apr 2026 11:45:08 +0000</pubDate>
      <link>https://dev.to/ayozebarrera/de-ticket-a-deploy-sin-tocar-nada-como-claude-code-orquesta-mi-flujo-entero-2kpm</link>
      <guid>https://dev.to/ayozebarrera/de-ticket-a-deploy-sin-tocar-nada-como-claude-code-orquesta-mi-flujo-entero-2kpm</guid>
      <description>&lt;p&gt;Lunes por la mañana. Abro Timeview — mi gestor de tareas — y hay un ticket nuevo: migrar un listado de scroll virtual a paginación tradicional. Hace unos meses, este momento significaba 10 o 15 minutos de fricción antes de poder siquiera pensar en el cambio. Copiar el título, crear la issue en GitLab, etiquetarla, asignarla, crear la rama, abrir el MR en draft, hacer checkout, abrir VSCode. Secretariado.&lt;/p&gt;

&lt;p&gt;Ahora escribo tres palabras:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Trabaja en la tarea 6283"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Me voy a por un café. Cuando vuelvo, la issue está creada en GitLab con las mismas etiquetas que tenía en Timeview, hay un MR en draft enlazándola, la rama está activa en VSCode, y Claude Code me espera con un análisis del componente actual y un plan de cambios. Yo reviso lo que propone, ajusto un detalle, y lo implementa.&lt;/p&gt;

&lt;p&gt;No es magia. Es &lt;code&gt;@timeview/cli&lt;/code&gt; — un CLI que escribí con Ink y React, el mismo stack que usa Claude Code — y un &lt;code&gt;CLAUDE.md&lt;/code&gt; que le enseña a usarlo. En este artículo te cuento cómo funciona y, sobre todo, cuánto tiempo me ahorra de verdad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffic8as19i125555408td.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffic8as19i125555408td.png" alt=" " width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  El problema: 15 minutos de secretariado por ticket
&lt;/h2&gt;

&lt;p&gt;Mi flujo manual, paso a paso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Leer el ticket en Timeview&lt;/li&gt;
&lt;li&gt;Copiar título y descripción&lt;/li&gt;
&lt;li&gt;Ir a GitLab self-hosted, crear la issue, etiquetas, milestone, asignación&lt;/li&gt;
&lt;li&gt;Crear la rama desde &lt;code&gt;develop&lt;/code&gt; con naming consistente&lt;/li&gt;
&lt;li&gt;Abrir MR en draft enlazando la issue&lt;/li&gt;
&lt;li&gt;Hacer checkout en el terminal&lt;/li&gt;
&lt;li&gt;Abrir VSCode en esa rama&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Por fin: empezar a pensar en el problema&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Desarrollar&lt;/li&gt;
&lt;li&gt;Mergear, checkout a &lt;code&gt;develop&lt;/code&gt;, pull, borrar rama local&lt;/li&gt;
&lt;li&gt;Volver a Timeview, estado a completado, registrar tiempo, comentario resumen con link al MR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Los pasos 1–7 son 10 o 15 minutos. Los pasos 10–11, otros 5. Son 15 o 20 minutos de overhead por ticket, multiplicado por 3 a 5 tickets al día.&lt;/p&gt;

&lt;p&gt;Pero el coste real no se mide en minutos. Cada salto entre Timeview, el navegador, el terminal y el editor rompe el foco. Cuando llegas al paso 8, ya no estás al 100% — estás llegando cansado antes de empezar.&lt;/p&gt;




&lt;h2&gt;
  
  
  La idea: darle manos al agente fuera del editor
&lt;/h2&gt;

&lt;p&gt;Claude Code ya es un buen pair programmer dentro del editor. La pregunta que me hice fue: &lt;strong&gt;¿y si le doy manos fuera del editor también?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No un plugin, no una integración oficial. Un CLI propio — &lt;code&gt;tv&lt;/code&gt; — que habla con Timeview, con GitLab y con git local. Claude Code tiene permiso para invocarlo. Le explico el flujo en un &lt;code&gt;CLAUDE.md&lt;/code&gt; y el agente decide cuándo leer la tarea, cuándo abrir el MR, cuándo mergear, cuándo actualizar Timeview.&lt;/p&gt;

&lt;p&gt;Yo solo apruebo.&lt;/p&gt;




&lt;h2&gt;
  
  
  El flujo, seis fases
&lt;/h2&gt;

&lt;p&gt;Todo empieza con una frase: &lt;em&gt;"Trabaja en la tarea 6283"&lt;/em&gt;. A partir de ahí, el agente ejecuta esto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuicc7laqz4wlecrmd8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuicc7laqz4wlecrmd8d.png" alt=" " width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fase 1 — Leer la tarea
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tv tasks work 6283 &lt;span class="nt"&gt;--status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Devuelve un JSON con título, notas, estado, etiquetas y MR vinculado si existe. Claude lo digiere.&lt;/p&gt;

&lt;p&gt;Hay una regla de esta fase que tardé un par de iteraciones en dejar bien: &lt;strong&gt;las notas tienen prioridad sobre el título&lt;/strong&gt;. Un ticket se abre con un título rápido y luego la conversación lo refina en los comentarios. Esa regla vive en el &lt;code&gt;CLAUDE.md&lt;/code&gt; y evita que el agente trabaje sobre un enunciado obsoleto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj73fgxgwzki3eoccfgyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj73fgxgwzki3eoccfgyg.png" alt=" " width="540" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fase 2 — Iniciar el trabajo
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tv tasks start 6283
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un único comando que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crea la issue en GitLab self-hosted &lt;strong&gt;copiando las etiquetas desde Timeview&lt;/strong&gt; (&lt;code&gt;bugfix&lt;/code&gt;, &lt;code&gt;feature&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt;…)&lt;/li&gt;
&lt;li&gt;Abre el MR en draft y lo enlaza a la issue&lt;/li&gt;
&lt;li&gt;Crea la rama con naming consistente&lt;/li&gt;
&lt;li&gt;Hace checkout automático&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El detalle de las etiquetas parece cosmético pero no lo es. Cuando preparo una release, el changelog se genera agrupando por etiqueta. Mantenerla sincronizada entre Timeview y GitLab significa que &lt;strong&gt;clasifico el ticket una sola vez, al crearlo, y la clasificación viaja sola hasta las release notes&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tv tasks work &amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;--status&lt;/span&gt;   &lt;span class="c"&gt;# Ver estado actual de tarea + MR&lt;/span&gt;
tv tasks comment &amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &amp;lt;texto&amp;gt; &lt;span class="c"&gt;# Añadir nota por ID (desde cualquier rama)&lt;/span&gt;
tv tasks state &amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &amp;lt;stateId&amp;gt; &lt;span class="c"&gt;# Cambiar estado por ID (desde cualquier rama)&lt;/span&gt;
tv tasks new &lt;span class="nt"&gt;--title&lt;/span&gt; &amp;lt;título&amp;gt; &lt;span class="c"&gt;# Crear nueva tarea en Timeview + GitLab&lt;/span&gt;
tv notes &amp;lt;texto&amp;gt;              &lt;span class="c"&gt;# Nota en la tarea de la rama actual&lt;/span&gt;
tv spend &amp;lt;minutos&amp;gt;            &lt;span class="c"&gt;# Registrar tiempo en la tarea actual&lt;/span&gt;
tv status                     &lt;span class="c"&gt;# Ver contexto: proyecto, rama, tarea, MR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fase 3 — Analizar con el código delante
&lt;/h3&gt;

&lt;p&gt;Aquí pasa algo que no diseñé consciente, pero que resultó clave: Claude propone los cambios &lt;strong&gt;después&lt;/strong&gt; del checkout, no antes. Con la rama activa, puede leer los archivos reales del repo y solo entonces me presenta:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qué archivos va a tocar&lt;/li&gt;
&lt;li&gt;Qué cambios propone y por qué&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si le pidiera el plan antes del checkout, sería un plan a ciegas sobre suposiciones. Con el código delante, es un plan sobre hechos. Yo apruebo o corrijo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fase 4 — Implementar
&lt;/h3&gt;

&lt;p&gt;Claude Code haciendo su trabajo habitual: edita el código según lo acordado. Nada nuevo aquí; lo relevante es que llega con &lt;strong&gt;todo el contexto del ticket ya cargado&lt;/strong&gt;, no con un prompt genérico que yo haya tenido que improvisar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fase 5 — Commit, push, merge
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &amp;lt;archivos&amp;gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"refactor: migrar listado a paginación"&lt;/span&gt;
git push origin &amp;lt;rama&amp;gt;

tv tasks work 6283 &lt;span class="nt"&gt;--merge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El &lt;code&gt;--merge&lt;/code&gt; es mi favorito. Mergea el MR, cierra la issue de GitLab, hace checkout a &lt;code&gt;develop&lt;/code&gt;, pull, borra la rama local y limpia la referencia del config. Cinco pasos aburridos en uno.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fase 6 — Cerrar la tarea
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tv tasks comment 6283 &lt;span class="s2"&gt;"Añadida paginación a la página de noticias. Cambiado de listado virtual con filtrado client-side a query paginada server-side. Destacados se obtienen en query separada. Búsqueda y filtro por tags resetean a página 1. Componente Pagination integrado. MR: &amp;lt;url&amp;gt;"&lt;/span&gt;
tv tasks state 6283 completed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comentario con el resumen, URL del MR, estado a completado. Fin del ciclo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5bu64w59s0nfcw4wdcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5bu64w59s0nfcw4wdcc.png" alt=" " width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  La arquitectura, en una imagen mental
&lt;/h2&gt;

&lt;p&gt;Tres piezas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@timeview/cli&lt;/code&gt;&lt;/strong&gt; (invocado como &lt;code&gt;tv&lt;/code&gt;): el CLI propio. Hecho con &lt;strong&gt;Ink + React&lt;/strong&gt; — el mismo stack que usa Claude Code. Wrappea la API de Timeview, la API de GitLab y los comandos de git locales. Una sola responsabilidad: traducir intenciones de alto nivel ("trabaja en la tarea 6197") en las llamadas concretas que hay debajo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code&lt;/strong&gt;: con permisos para ejecutar &lt;code&gt;tv&lt;/code&gt; y git.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; del proyecto&lt;/strong&gt;: el runbook del agente. Describe el flujo, los comandos, el orden y las reglas que no puede romper (como la de "las notas tienen prioridad").&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Autenticación local: nada que desplegar
&lt;/h3&gt;

&lt;p&gt;Un detalle importante si otro dev del equipo quiere usarlo: &lt;strong&gt;la autenticación es local&lt;/strong&gt;. Para Timeview, el usuario introduce sus credenciales una vez y el CLI guarda el token. Para GitLab, un access token personal. Todo en &lt;code&gt;~/.timeview/config.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No hay servidor intermedio, no hay credenciales compartidas, no hay infraestructura que montar. Un compañero instala el paquete, se autentica con lo suyo y tiene exactamente el mismo flujo en su máquina. Esa es la diferencia entre una herramienta personal y una que puede adoptar el resto del equipo sin pedir permisos ni levantar nada.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctmgkth3pd2ilnycb8gh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctmgkth3pd2ilnycb8gh.png" alt=" " width="715" height="383"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Los números
&lt;/h2&gt;

&lt;p&gt;Separo por tipo de tarea porque el ahorro es muy distinto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Antes&lt;/strong&gt;: ~10 min de setup antes de empezar + 20–60 min de resolución = &lt;strong&gt;30–70 min totales&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ahora&lt;/strong&gt;: 1–5 min leyendo el ticket en Timeview + 1–2 min revisando el plan + ~1 min de ejecución = &lt;strong&gt;3–8 min totales&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahorro por bug: entre 25 minutos y una hora larga.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature nueva
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Antes&lt;/strong&gt;: 4–16 horas según tamaño&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ahora&lt;/strong&gt;: hasta 1 hora siendo precavido con las pruebas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahorro por feature: varias horas. En las más grandes, casi un día entero.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caso real: la tarea 6283 de este artículo
&lt;/h3&gt;

&lt;p&gt;Las capturas que ves en este post son de una tarea real — el ticket #6283, migrar un listado de scroll virtual a paginación tradicional. La completé en &lt;strong&gt;5 minutos&lt;/strong&gt; de trabajo efectivo.&lt;/p&gt;

&lt;p&gt;Los otros 10 minutos que me llevó la sesión los gasté recolocando datos de prueba y esperando el momento adecuado para pulsar "captura". El cronómetro no miente: el trabajo en sí fueron 5 minutos de punta a punta.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dónde paro de prometer
&lt;/h3&gt;

&lt;p&gt;Estas cifras son &lt;strong&gt;estimaciones basadas en mi experiencia&lt;/strong&gt;, no medidas cronometradas. Comparan cómo trabajaba antes y cómo trabajo ahora sobre tickets parecidos. El ahorro real será algo menor en los casos buenos y algo mayor en los malos, pero el orden de magnitud es sólido.&lt;/p&gt;

&lt;p&gt;Tampoco incluyen el tiempo de &lt;strong&gt;pensar, revisar y decidir&lt;/strong&gt;. Y eso es lo que quería: el agente se come el secretariado, no el diseño.&lt;/p&gt;

&lt;p&gt;Lo que no aparece en los números pero se siente todos los días es el fin del context-switching. Antes saltaba varias veces por ticket entre cuatro ventanas. Ahora el único salto es leer el plan y aprobarlo. No sale en el cronómetro, pero al final del día queda más energía.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lecciones no obvias
&lt;/h2&gt;

&lt;p&gt;Tres cosas que no esperaba al construir esto:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. El cuello de botella no eran los minutos, era el foco.&lt;/strong&gt; Lo pensaba como un problema de tiempo; resultó ser un problema de atención. Eliminar los saltos entre herramientas tiene más impacto que los minutos que ahorra.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Dar manos al agente te obliga a documentar tu propio flujo.&lt;/strong&gt; Para que Claude supiera qué hacer, tuve que escribir el &lt;code&gt;CLAUDE.md&lt;/code&gt;. Para escribirlo, tuve que explicitar cosas que hacía por intuición y nunca había puesto por escrito. Reglas como "las notas tienen prioridad sobre el título" no existían en ningún sitio hasta que tuve que enseñárselas a una máquina. El proceso de documentar, por sí solo, ya mejoró el flujo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Las etiquetas compartidas cierran el ciclo hasta el changelog.&lt;/strong&gt; Que la etiqueta viaje de Timeview a GitLab y de ahí a las release notes parece un detalle. No lo es: clasificar el ticket una sola vez y ver esa clasificación llegar intacta al documento que lee el cliente es uno de los beneficios más infravalorados del sistema.&lt;/p&gt;

&lt;p&gt;Una nota antes de seguir: &lt;strong&gt;este patrón no es exclusivo de Claude Code&lt;/strong&gt;. Cualquier agente con permisos de shell podría invocar un CLI así — Cursor, Aider, Codex CLI, lo que uses. Lo interesante no es qué agente eliges, sino que dejes de usarlo solo dentro del editor.&lt;/p&gt;




&lt;h2&gt;
  
  
  Qué viene después
&lt;/h2&gt;

&lt;p&gt;Browser-agent. Quiero que Claude pruebe él mismo los cambios de UI antes de pedirme review: que abra el navegador, cargue la pantalla, haga clic entre páginas, verifique que la paginación responde como debe. Hoy esa parte todavía la hago yo. Cuando esté, el bucle entero — desde el ticket hasta el "funciona de verdad" — estará cerrado sin que yo tenga que abrir una sola pestaña.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cierre
&lt;/h2&gt;

&lt;p&gt;No voy a decirte que esto es el futuro del desarrollo. No lo sé, cada día que pasa, algo cambia. Lo que sí sé es que &lt;strong&gt;el desarrollo tiene un porcentaje sorprendentemente alto de trabajo de secretario&lt;/strong&gt;: mover tickets, crear ramas, rellenar formularios de estado, escribir comentarios resumen. Ese trabajo nunca me hizo mejor ingeniero.&lt;/p&gt;

&lt;p&gt;Darle ese trabajo a un agente no me convierte en un dev mejor. Me convierte en un dev que pasa más minutos del día pensando en código y menos rellenando casillas.&lt;/p&gt;

&lt;p&gt;Con eso me vale.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Como crear una guía de estilo con Figma</title>
      <dc:creator>Ayoze Barrera</dc:creator>
      <pubDate>Sun, 01 Mar 2020 14:54:29 +0000</pubDate>
      <link>https://dev.to/capua/como-crear-una-guia-de-estilo-con-figma-269o</link>
      <guid>https://dev.to/capua/como-crear-una-guia-de-estilo-con-figma-269o</guid>
      <description>&lt;p&gt;La imagen de un proyecto es súper importante, y va a influenciar al usuario directamente para que siga utilizando la aplicación y la identifique rápidamente o para que salga huyendo confuso y asustado.&lt;/p&gt;

&lt;p&gt;Cuando trabajan varios diseñadores o programadores en un proyecto muy grande, lo mejor es crear una guía de estilo para que nadie se salga del &lt;em&gt;guión&lt;/em&gt; y acabe diseñando algún componente fuera de tono en comparación al resto.&lt;/p&gt;

&lt;p&gt;Para evitar esto, existen las guías de estilos.&lt;/p&gt;

&lt;p&gt;Así que cuando llega alguien nuevo al proyecto, le podemos dar la bienvenida con una bonita guía de estilos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq2vcfp81awipkl2v4qff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq2vcfp81awipkl2v4qff.png" alt="Alt Text" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Que es una guía de estilo
&lt;/h1&gt;

&lt;p&gt;Una guía de estilos, como bien dice su nombre, es una guía para saber que &lt;strong&gt;materiales&lt;/strong&gt; se deben de usar para seguir construyendo, como por ejemplo, que tipografía usar en los títulos, cuáles son los colores principales de la aplicación, que sombras utilizar, y cualquier aspecto que queramos definir.&lt;/p&gt;

&lt;p&gt;En nuestra &lt;a href="https://citec-sl.com" rel="noopener noreferrer"&gt;empresa&lt;/a&gt;, hemos creado una guía de estilos muy simple para una aplicación que llevamos desarrollando cuatro años: &lt;a href="https://fleetview.io" rel="noopener noreferrer"&gt;Fleetview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nuestra guía de estilo ha servido a otros compañeros para poder crear manuales y vídeos sobre la aplicación.&lt;/p&gt;

&lt;p&gt;Hemos decidido hacerla en Figma ya que es una aplicación increible y nos permite exportar cualquier elemento en vectorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Que elementos añadir
&lt;/h2&gt;

&lt;p&gt;Podemos añadir los elementos que consideremos más importantes, y en nuestro caso fueros los siguientes:&lt;/p&gt;

&lt;h3&gt;
  
  
  Branding
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F800thl6sd50j162ze09f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F800thl6sd50j162ze09f.png" alt="Alt Text" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los logos de la aplicación y sus variantes. Cualquier otra variante que no esté aquí definida no estará permitida.&lt;/p&gt;

&lt;h3&gt;
  
  
  Paleta de colores
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyfrhej25hhegw4g691u7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyfrhej25hhegw4g691u7.png" alt="Alt Text" width="800" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Colores principales y secundarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tipografía
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwgrd68xuur8kj7qqlefn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwgrd68xuur8kj7qqlefn.png" alt="Alt Text" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La tipografía que usamos en el logo, en los títulos y en los párrafos. De cada uno de ellos definimos la familia, peso, tamaño, altura de línea, espaciado entre letras, color y un ejemplo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Iconos
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcmu6pcm35sbiu4t0zsrl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcmu6pcm35sbiu4t0zsrl.png" alt="Alt Text" width="376" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El sistema de iconos que usa la aplicación. Si hay que diseñar un icono nuevo, debe tener el mismo tamaño y mismo el grosor en las líneas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Componentes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqsxjtfui0pnqjzibogpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqsxjtfui0pnqjzibogpp.png" alt="Alt Text" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los componentes más importantes que utilicen algunos de los aspectos anteriores.&lt;/p&gt;

&lt;p&gt;Y todo junto pues se vería así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxuamwgqvkoxbllhb99cu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxuamwgqvkoxbllhb99cu.png" alt="Alt Text" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hasta la próxima batalla!&lt;/p&gt;

&lt;p&gt;🖖&lt;/p&gt;

</description>
      <category>design</category>
      <category>figma</category>
      <category>style</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mapeando tus movimientos con React y Leaflet</title>
      <dc:creator>Ayoze Barrera</dc:creator>
      <pubDate>Mon, 24 Feb 2020 12:12:45 +0000</pubDate>
      <link>https://dev.to/capua/mapeando-tus-movimientos-con-react-y-leaflet-3bce</link>
      <guid>https://dev.to/capua/mapeando-tus-movimientos-con-react-y-leaflet-3bce</guid>
      <description>&lt;p&gt;Hoy en día usamos mapas para todo… para buscar direcciones, consultar cuál es el mejor camino a tomar para llegar a un punto en concreto, para promocionar un local, o simplemente viajar desde casa (&lt;em&gt;asi es, he visto a youtubers que se pasan horas dando vueltas por paises gracias a los mapas… y hacen visitas!&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;Pues por ese motivo vamos a ver cómo podemos hacer un mapa con nuestros movimientos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3qhcajjuwqmr6k6y6g1q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3qhcajjuwqmr6k6y6g1q.png" alt="Moves" width="410" height="306"&gt;&lt;/a&gt;&lt;/p&gt;
Moves app



&lt;h1&gt;
  
  
  Moves
&lt;/h1&gt;

&lt;p&gt;Para registrar los movimientos, aunque hay otras, he usado la aplicación &lt;a href="https://moves-app.com/" rel="noopener noreferrer"&gt;moves&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Moves se ejecuta en segundo plano y nos permite importar tus movimientos en diferentes formatos, y uno de ellos es geojson.&lt;/p&gt;

&lt;p&gt;Para empezar nos vamos a la página web de moves. Allí nos permitirá importar lo registrado desde nuestro dispositivo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuración
&lt;/h1&gt;

&lt;p&gt;Lo primero será instalar los paquetes de &lt;strong&gt;leaflet&lt;/strong&gt; y &lt;strong&gt;react-leaflet&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nt"&gt;-i&lt;/span&gt; S leaflet react-leaflet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://react-leaflet.js.org/" rel="noopener noreferrer"&gt;React-leaflet&lt;/a&gt; lo que hace es cargar componentes pero sin renderizar nada, simplemente usa los métodos de &lt;em&gt;leaflet&lt;/em&gt; en el &lt;em&gt;lifecycle&lt;/em&gt; del componente.&lt;/p&gt;

&lt;p&gt;Podríamos conseguir nuestro mapa sin react-leaflet pero lo he usado anteriormente y ayuda mucho.&lt;/p&gt;
&lt;h1&gt;
  
  
  El mapa
&lt;/h1&gt;

&lt;p&gt;Ya estamos listos para empezar así que lo primero será importar los paquetes que vamos a necesitar.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TileLayer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-leaflet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;leaflet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;De momento solo he importado dos componentes de react-leaflet: Map y TileLayer. Esto es lo básico que necesitarás para mostrar un mapa.&lt;/p&gt;

&lt;p&gt;También he importado leaflet porque vamos a usar el método circleMarker para poder tratar los puntos de los geojsons de nuestros datos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Map
&lt;/h2&gt;

&lt;p&gt;Capa principal del mapa que controla el zoom, bordes y el centro. Lo que vayamos a representar en el mapa, lo pasaremos como hijos.&lt;/p&gt;
&lt;h2&gt;
  
  
  TileLayer
&lt;/h2&gt;

&lt;p&gt;Componente que se encargará de mostrar los tiles correspondientes en base al zoom y al centro.&lt;/p&gt;

&lt;p&gt;Este componente necesita la propiedad url que será al montarse.&lt;/p&gt;

&lt;p&gt;Para este ejemplo, voy a usar un mapa en blanco y negro, pero puedes encontrar mas urls &lt;a href="https://leaflet-extras.github.io/leaflet-providers/preview/" rel="noopener noreferrer"&gt;aquí&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}{r}.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ah! Antes de poder usar nuestro mapa, necesitaremos importar el css de leaflet, que puedes encontrar en su apartado de &lt;a href="https://leafletjs.com/download.html" rel="noopener noreferrer"&gt;descargas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Configurados estos dos componentes, deberíamos de tener algo muy parecido a esto:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foc1lg5bknvrnjualxo41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foc1lg5bknvrnjualxo41.png" alt="Map" width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tanto rollo para tener un mapa vacío?&lt;/p&gt;

&lt;p&gt;Calma… ahora viene lo bueno 😁&lt;/p&gt;

&lt;h1&gt;
  
  
  Nuestros movimientos
&lt;/h1&gt;

&lt;p&gt;Moves, aparte de ofrecerte muchos formatos, también te separa los datos en movimientos diarios, semanales, mensuales, anuales y por último, todos en un mismo fichero. Yo voy a utilizar mis lugares visitados separados por años. En concreto los de 2016, 2017 y 2018.&lt;/p&gt;

&lt;p&gt;Para ello voy a usar una capa de GeoJSON de leaflet, que como no, también lo tenemos como componente en react-leaflet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TileLayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GeoJSON&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-leaflet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El siguiente paso sería importar los datos de nuestros movimientos:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;places2016&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/places_2016.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;places2017&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/places_2017.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;places2018&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/places_2018.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Después, tenemos que usar el componente GeoJSON como un &lt;strong&gt;children&lt;/strong&gt; más en nuestro component Map:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Map&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;{styles.map}&lt;/span&gt; &lt;span class="na"&gt;center=&lt;/span&gt;&lt;span class="s"&gt;{props.center}&lt;/span&gt; &lt;span class="na"&gt;zoom=&lt;/span&gt;&lt;span class="s"&gt;{props.zoom}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;TileLayer&lt;/span&gt; &lt;span class="na"&gt;url=&lt;/span&gt;&lt;span class="s"&gt;{props.url}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;GeoJSON&lt;/span&gt;
    &lt;span class="na"&gt;data=&lt;/span&gt;&lt;span class="s"&gt;{places2016}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Map&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Además de pasarle los datos a la capa GeoJSON, el componente necesita la propiedad style, que es una función que usará internamente para aplicar el style que queramos a cada elemento de nuestro geojson:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Cuidado!&lt;/strong&gt; La función anterior solo te servirá para elementos que NO sean de tipo Point.&lt;/p&gt;

&lt;p&gt;Dentro de mis geojsons, solo tengo elementos de tipo Point, asi necesitaré utilizar una propiedad extra: &lt;strong&gt;pointToLayer&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;geojsonMarkerOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fillColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#EE4266&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fillOpacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pointToLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;latlng&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;circleMarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;latlng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;geojsonMarkerOptions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;En mi caso, el componente GeoJSON se queda de la siguiente manera:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;GeoJSON&lt;/span&gt;
  &lt;span class="na"&gt;data=&lt;/span&gt;&lt;span class="s"&gt;{places2016}&lt;/span&gt;
  &lt;span class="na"&gt;pointToLayer=&lt;/span&gt;&lt;span class="s"&gt;{pointToLayer}&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ya casi terminamos!&lt;/p&gt;

&lt;p&gt;Como voy a representar tres geojsons diferentes, y quiero representarlos con diferentes colores, tengo que crear tres funciones diferentes de pointToLayer&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Map&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;{styles.map}&lt;/span&gt; &lt;span class="na"&gt;center=&lt;/span&gt;&lt;span class="s"&gt;{props.center}&lt;/span&gt; &lt;span class="na"&gt;zoom=&lt;/span&gt;&lt;span class="s"&gt;{props.zoom}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;TileLayer&lt;/span&gt; &lt;span class="na"&gt;url=&lt;/span&gt;&lt;span class="s"&gt;{props.url}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;GeoJSON&lt;/span&gt;
    &lt;span class="na"&gt;data=&lt;/span&gt;&lt;span class="s"&gt;{places2016}&lt;/span&gt;
    &lt;span class="na"&gt;pointToLayer=&lt;/span&gt;&lt;span class="s"&gt;{pointToLayer2016}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;GeoJSON&lt;/span&gt;
    &lt;span class="na"&gt;data=&lt;/span&gt;&lt;span class="s"&gt;{places2017}&lt;/span&gt;
    &lt;span class="na"&gt;pointToLayer=&lt;/span&gt;&lt;span class="s"&gt;{pointToLayer2017}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;GeoJSON&lt;/span&gt;
    &lt;span class="na"&gt;data=&lt;/span&gt;&lt;span class="s"&gt;{places2018}&lt;/span&gt;
    &lt;span class="na"&gt;pointToLayer=&lt;/span&gt;&lt;span class="s"&gt;{pointToLayer2018}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Map&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Este es el resultado final del componente:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Voilá&lt;/em&gt;, nuestro mapa estaría listo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1ru87n8qkj0rsnf6si4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1ru87n8qkj0rsnf6si4l.png" alt="Finished map" width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nos vemos en la próxima batalla!&lt;/p&gt;

&lt;p&gt;🖖🏼&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>mapping</category>
      <category>leaflet</category>
    </item>
    <item>
      <title>Cómo crear un paquete de Node</title>
      <dc:creator>Ayoze Barrera</dc:creator>
      <pubDate>Fri, 14 Feb 2020 10:02:24 +0000</pubDate>
      <link>https://dev.to/capua/como-crear-un-paquete-de-node-3hp3</link>
      <guid>https://dev.to/capua/como-crear-un-paquete-de-node-3hp3</guid>
      <description>&lt;p&gt;Cuando vamos a crear un proyecto nuevo, nos pasamos una gran parte del tiempo copiando y pegando código de antiguos proyectos… ¿para que vamos a reinventar la rueda?&lt;/p&gt;

&lt;h1&gt;
  
  
  El nacimiento de nuestra librería personal
&lt;/h1&gt;

&lt;p&gt;Para empezar, creamos una carpeta con el nombre del paquete, yo lo llamaré &lt;em&gt;capua-package-sample&lt;/em&gt;, y dentro ejecutamos el siguiente comando de npm para generar nuestro package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm init &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este comando te creará un package.json básico extrayendo información de la carpeta donde se ejecuta.&lt;/p&gt;

&lt;p&gt;Deberíamos de tener algo parecido a esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"capua-package-sample"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ayoze Barrera"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fichero principal
&lt;/h2&gt;

&lt;p&gt;Ahora que tenemos el package.json, necesitamos crear el fichero que se usará cuando se importe nuestro paquete. Este fichero se especifica en la propiedad main, y por defecto es &lt;strong&gt;index.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;En este fichero, para nuestro ejemplo, exportaremos cualquier cosa, como por ejemplo una función sencilla:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myAwesomeFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta función debería de devolver &lt;strong&gt;«baNaNa»&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ahora solo faltaría subirlo a nuestro repositorio o &lt;em&gt;publicarlo&lt;/em&gt; en npm!&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando nuestro paquete
&lt;/h2&gt;

&lt;p&gt;Si has publicado el paquete sabrás como instalarlo, pero si no lo has hecho, quizás no sepas… pues es muy fácil, solo tienes que ejecutar el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;git-service&amp;gt;:&amp;lt;git-user&amp;gt;/&amp;lt;repo-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si no rellenamos el servicio, buscará en github por defecto, pero soporta muchos otros… para saber más mira la &lt;a href="https://docs.npmjs.com/cli/install" rel="noopener noreferrer"&gt;documentación&lt;/a&gt; de npm install.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt; github:capua/capua-package-sample
└── capua-package-sample@1.0.0  &lt;span class="o"&gt;(&lt;/span&gt;git://github.com/capua/capua-package-sample.git#e5903fa2a1e4ee1e751a53fb0aa420cba07e949a&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ya solo tendríamos que importarlo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;myAwesomeFunction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;capua-package-sample&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;myAwesomeFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; "baNaNa"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nos vemos en la próxima batalla!&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>npm</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mapeando con Javascript</title>
      <dc:creator>Ayoze Barrera</dc:creator>
      <pubDate>Mon, 10 Feb 2020 16:56:11 +0000</pubDate>
      <link>https://dev.to/capua/mapeando-con-javascript-1k4g</link>
      <guid>https://dev.to/capua/mapeando-con-javascript-1k4g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este post fue publicado originalmente en julio del 2015&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hablaremos de Mapbox y aprenderemos a manejar y reproyectar nuestros datos geoespaciales con QGIS, para añadirlos a un mapa estilizado por nosotros.&lt;/p&gt;

&lt;p&gt;El mundo de la cartografía es enorme, y puedo decir que me queda mucho por descubrir. Este artículo es parte de la experiencia que he obtenido en un proyecto reciente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcgovjdlmnjfmqfh0mnez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcgovjdlmnjfmqfh0mnez.png" alt="Alt Text" width="256" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Antes de &lt;em&gt;trastear&lt;/em&gt; con nuestros datos geoespaciales, primero necesitamos nuestro lienzo, el mapa.&lt;/p&gt;

&lt;p&gt;Mapbox es una plataforma para crear y usar mapas, y está basada en la librería de &lt;strong&gt;LeafletJS&lt;/strong&gt;. Tiene un buen abanico de herramientas, datos y servicios que se conectan muy bien entre sí, por ejemplo, podemos estilizar un mapa con &lt;em&gt;Mapbox Studio&lt;/em&gt;, una aplicación que usa &lt;em&gt;CartoCSS&lt;/em&gt; para darle vida a nuestro mapa junto con otras utilidades, para luego conectarlo con la librería &lt;em&gt;Mapbox.js&lt;/em&gt; para jugar con nuestros datos vía Javascript. &lt;/p&gt;

&lt;p&gt;Y eso amigos, en resumen, es lo que haremos hoy 🤗.&lt;/p&gt;

&lt;p&gt;El plan starter nos permite estilizar un mapa y guardar 100mb de datos en los servidores de Mapbox. Si subes los datos a los servidores de ellos, luego podríamos usarlos en Mapbox Studio para estilizarlos junto a nuestro mapa, pero en nuestro caso no lo haremos así, lo haremos con js usando geojsons a través de la librería Mapbox.js.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs75lwgxx04c2iss5rzod.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs75lwgxx04c2iss5rzod.png" alt="Alt Text" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;
Tarifas de Mapbox



&lt;h3&gt;
  
  
  Mapbox Studio
&lt;/h3&gt;

&lt;p&gt;Mapbox Studio está disponible para OS X, Windows y Linux. Incluso tenemos acceso a su código en &lt;a href="https://github.com/mapbox/mapbox-studio" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hablemos de sus posibilidades.&lt;/p&gt;

&lt;h4&gt;
  
  
  Datos
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdmtsxoa33mds7ng65vrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdmtsxoa33mds7ng65vrw.png" alt="Alt Text" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;
Gran Canaria con la vista previa a la izquierda y vista de datos a la derecha



&lt;p&gt;Nos permite añadir nuestros propios geodatos, además de todos los datos que nos ofrece por defecto, como calles, terreno, satélite… con la posibilidad de controlarlos y de inspeccionarlos a nuestra merced.&lt;/p&gt;

&lt;h4&gt;
  
  
  Estilo
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz8trytjqnn307ea0zhx7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz8trytjqnn307ea0zhx7.png" alt="Alt Text" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos darle colores y formas a nuestro mapa gracias al preprocesador de estilos CartoCSS desarrollado por Mapbox. También tenemos acceso a una coleccion de iconos llamados &lt;a href="https://www.mapbox.com/maki" rel="noopener noreferrer"&gt;Maki&lt;/a&gt; que están optimizados para tres tamaños diferentes y a un catálogo de tipografías con la posibilidad de añadir la nuestra propia.&lt;/p&gt;

&lt;p&gt;Las posibilidades de la aplicación son mayores, pero con esto nos bastará para cumplir con el objetivo del artículo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Empecemos
&lt;/h3&gt;

&lt;p&gt;Vamos a crear nuestro mapa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkps21lcryj54o01xvb2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkps21lcryj54o01xvb2p.png" alt="Alt Text" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;
Nuevo proyecto en Mapbox Studio.



&lt;p&gt;Cuando vamos a crear un nuevo proyecto, tenemos la posibilidad de elegir un mapa o de añadir datos propios para luego usarlos en algún mapa. En nuestro caso, como nuestros datos irán de la mano con js, vamos a experimentar un poco con CartoCSS. Elegiré el de &lt;em&gt;Run, Bike and Hike&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Lo primero que vemos al elegir el mapa es que además de éste, tenemos la hoja de estilos a nuestra derecha separadas en varios ficheros. En estos ficheros tenemos todo el estilo que forma Run, Bike and Hike y será el que modifiquemos para conseguir nuestra “obra”.&lt;/p&gt;

&lt;p&gt;Empezaré por cambiarle el color al mar. Para cambiar el aspecto de un elemento del mapa, debemos saber su identificador. Simplemente tenemos que ponernos en la vista de datos haciendo click en el botón que está a la derecha del zoom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5a4qdja6an1kfetwrdd6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5a4qdja6an1kfetwrdd6.png" alt="Alt Text" width="52" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En esta vista, si hacemos click en algún punto del mapa, aparecerá un &lt;em&gt;tooltip&lt;/em&gt; con la información de todos los datos de ese lugar. También podemos irnos a la sección Layers (Capas) del menú lateral izquierdo, el cual nos desplegará una ventana con la lista de todos los elementos que tenemos actualmente en nuestro mapa. Si os fijáis en la parte superior de esta ventana, veremos que los datos están bloqueados. Eso se debe a que se necesita un orden específico de capas para que el mapa funcione bien y en el caso de que quisiéramos añadir datos nuestros no podríamos, a menos que editemos el fichero &lt;strong&gt;project.yml&lt;/strong&gt; y borremos el listado de capas. En nuestro caso no necesitamos desbloquearlo.&lt;/p&gt;

&lt;p&gt;Una vez que sepamos el identificador del agua tenemos que identificarlo en nuestro proyecto. Lo encontraremos en el fichero &lt;strong&gt;bg&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nn"&gt;#water&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;polygon-fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;water&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//relleno del polígono&lt;/span&gt;
  &lt;span class="na"&gt;polygon-gamma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//gamma, para reducir huecos entre polígonos&lt;/span&gt;
  &lt;span class="nd"&gt;::shadow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//symbolizer&lt;/span&gt;
    &lt;span class="na"&gt;polygon-fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;water&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//otro relleno&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//opacidad&lt;/span&gt;
    &lt;span class="na"&gt;comp-op&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//operación de composición. efecto screen&lt;/span&gt;
    &lt;span class="na"&gt;image-filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;agg-stack-blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//sombra del agua(costas)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;zoom&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;12&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//estilo para zoom superior a 12&lt;/span&gt;
    &lt;span class="na"&gt;polygon-gamma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.75&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Las posibilidades son muy amplias: cambiar bordes, sombras, añadir patrones, aplicar efectos entre los elementos, pero no me complicaré mucho (ya me luciré mas tarde jaja) así que simplemente cambiaré algunos colores y la tipografía. Tal vez en algún artículo escriba sólo de CartoCSS y sus posibilidades, pero de momento podéis consultar la &lt;a href="https://github.com/mapbox/carto/blob/master/docs/latest.md" rel="noopener noreferrer"&gt;documentación&lt;/a&gt; para aprender todo lo que ofrece CartoCSS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frqfryieg065fxi0bx77z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frqfryieg065fxi0bx77z.png" alt="Alt Text" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;
Mapa antes y después del cambio



&lt;p&gt;Una vez tengamos nuestro mapa, tenemos que subirlo al servidor de Mapbox para generar un ID el cual usaremos más tarde porque de momento, tenemos que hablar un poco de los datos geoespaciales.&lt;/p&gt;
&lt;h3&gt;
  
  
  Datos geoespaciales
&lt;/h3&gt;

&lt;p&gt;Los datos geoespaciales o datos espaciales sirven para representar &lt;em&gt;features&lt;/em&gt; (&lt;strong&gt;puntos&lt;/strong&gt;, &lt;strong&gt;líneas&lt;/strong&gt; o &lt;strong&gt;áreas&lt;/strong&gt;) en una superficie. Estos datos pueden tener una tabla de datos con información.&lt;/p&gt;

&lt;p&gt;Para poder tratarlos, usaremos un GIS (&lt;em&gt;Geographic information system&lt;/em&gt;) donde podremos hacer una infinidad de cosas relacionadas con la geografía, como administrar los datos de cada punto, representar los datos o cambiarles la proyección, por nombrar algunas.&lt;/p&gt;

&lt;p&gt;El GIS que usaremos se llama &lt;a href="http://www.qgis.org/es/site/" rel="noopener noreferrer"&gt;QGIS&lt;/a&gt;, de código abierto, el cual aparte de tener las herramientas típicas de un sistema geográfico, tiene una buena comunidad de plugins muy interesantes. Ya le dedicaremos un artículo en el futuro.&lt;/p&gt;

&lt;p&gt;Hagamos lo que hagamos con nuestros datos, lo que nos interesa es, recordad, un fichero geojson.&lt;/p&gt;

&lt;p&gt;En el caso de que no tengamos a mano ningún fichero, podéis generar uno entrando en geojson.io, un editor a tiempo real, con la posibilidad de agregar features fácilmente y con muchas opciones para la exportación. También lo uso para visualizar ficheros y saber si están bien proyectados.&lt;/p&gt;

&lt;p&gt;En la siguiente parte cargaremos nuestros datos en un mapa con la librería de javascript &lt;strong&gt;mapbox.js&lt;/strong&gt; o &lt;strong&gt;leaftlet.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Github también tiene un buen API de mapas. Subid algún fichero a Gist y lo podréis comprobar. Éste es el mío&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Lo vamos a dejar por aquí!&lt;/p&gt;

&lt;p&gt;En la siguiente parte cargaremos nuestros datos en un mapa con la librería de javascript de mapbox o leaftlet.&lt;/p&gt;

&lt;p&gt;🌎&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>mapping</category>
      <category>cartograph</category>
    </item>
    <item>
      <title>Que comiencen los juegos</title>
      <dc:creator>Ayoze Barrera</dc:creator>
      <pubDate>Mon, 03 Feb 2020 16:39:11 +0000</pubDate>
      <link>https://dev.to/capua/que-comiencen-los-juegos-3ki4</link>
      <guid>https://dev.to/capua/que-comiencen-los-juegos-3ki4</guid>
      <description>&lt;h1&gt;
  
  
  Capua es un blog de desarrollo &amp;amp; experiencia de usuario.
&lt;/h1&gt;

&lt;p&gt;Tras una lucha “sangrienta” para conseguir el nombre de usuario &lt;strong&gt;capua&lt;/strong&gt; en &lt;em&gt;GitHub&lt;/em&gt;, ya no tenemos excusas para compartir nuestras locuras. Hace mucho tiempo que teníamos en mente este proyecto, pero al fin nos hemos puesto las pilas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capua
&lt;/h2&gt;

&lt;p&gt;Por contar un poco de donde procede el nombre del blog, nos gusta la temática romana, y Capua, antigua capital de Campania, tuvo el primer anfiteatro del mundo romano, donde los gladiadores dominaban la arena.&lt;/p&gt;

&lt;p&gt;Los desarrolladores, desde siempre, tienen que reciclarse &lt;strong&gt;diariamente&lt;/strong&gt; pues cada día salen nuevas tecnologías u otras se van actualizando, y para conseguir eso creemos que debemos ser como los gladiadores de la antigua Roma, capaces de enfrentarnos a cualquier bestia que se nos ponga por delante.&lt;/p&gt;

&lt;p&gt;Si has visto o si eres fan de &lt;em&gt;spartacus&lt;/em&gt;, es posible que te suene todo esto de Capua. También te será familiar nuestro grito de guerra:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Por Capua!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nuestra intención es compartir artículos interesantes de las cosas que hemos ido aprendiendo o que nos han enseñado a lo largo de los diferentes proyectos que hemos realizado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quiénes somos…
&lt;/h2&gt;


&lt;div class="ltag__user ltag__user__id__232522"&gt;
    &lt;a href="/ayozebarrera" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F232522%2Fc70ed0c6-13fb-4c77-8055-70c8d8386c7b.png" alt="ayozebarrera image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/ayozebarrera"&gt;Ayoze Barrera&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/ayozebarrera"&gt;Javascript freak 🤓 · Loving React ⚛· Fixie user 🚲 · Patriots fan 🏈!&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag__user ltag__user__id__160753"&gt;
    &lt;a href="/marioblas" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160753%2F5562a40e-4b64-4307-9a71-a5771edeb955.png" alt="marioblas image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/marioblas"&gt;Mario Blas 🇮🇨&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/marioblas"&gt;Web app developer • JavaScript • React • Expo&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  …y donde estamos
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm8tnffpug103nm60glo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm8tnffpug103nm60glo8.png" alt="Alt Text" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Las Palmas, Canary Islands, Spain ☺&lt;/p&gt;

&lt;h2&gt;
  
  
  Contenido
&lt;/h2&gt;

&lt;p&gt;Nuestros artículos se centrarán principalmente en dos campos, desarrollo y diseño. No descartamos hablar alguna vez de tecnología… o algún juego, quien sabe!&lt;/p&gt;

&lt;h3&gt;
  
  
  Desarrollo
&lt;/h3&gt;

&lt;p&gt;Estamos constantemente desarrollando aplicaciones con frameworks, servicios y plataformas de última hora.&lt;/p&gt;

&lt;p&gt;Nuestro mundo gira principalmente en torno a Javascript y todas las tecnologías relacionadas con éste lenguaje.&lt;/p&gt;

&lt;p&gt;Actualmente, nuestra librería principal es React.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxbbd88fhi6nubq9wa2v1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxbbd88fhi6nubq9wa2v1.png" alt="Alt Text" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Diseño
&lt;/h3&gt;

&lt;p&gt;Le damos mucha importancia al diseño de la experiencia de usuario (UX). UX es la calidad de experiencia que tiene un usuario cuando usa un diseño concreto.&lt;br&gt;
Algunas tecnologías de las que usamos nos permiten tener mayor flexibilidad en nuestra aplicación para así conseguir una UX más elaborada…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj1hgnp26cgoom0jxukqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj1hgnp26cgoom0jxukqm.png" alt="Alt Text" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probablemente hablemos de todo un poco, pero intentando no aburrir ☺.&lt;/p&gt;

&lt;h3&gt;
  
  
  Objetivos
&lt;/h3&gt;

&lt;p&gt;Somos algo novatos en el mundo de los blogs, pero intentaremos estar a la altura.&lt;/p&gt;

&lt;p&gt;Unos de los objetivos que pretendemos conseguir con Capua es crecer como redactores. No queremos tener un blog de textos copiados, y puestos para rellenar simplemente por tener muchos artículos y visitas.&lt;/p&gt;

&lt;p&gt;Le dedicaremos tiempo a cada artículo para intentar conseguir lo mejor de nosotros mismos. Y eso nos ayudará a conseguir otro de nuestros objetivos, la creación de nuestro propio imperio, nuestro lugar. Tenemos muchas ideas que llevamos guardando mucho tiempo.&lt;/p&gt;

&lt;p&gt;Ya veremos hacia donde crece esto y con quien.&lt;/p&gt;

&lt;p&gt;Dicho esto… Capua queda inaugurado!&lt;/p&gt;

&lt;p&gt;Hasta el próximo artículo ☺&lt;/p&gt;

</description>
      <category>capua</category>
      <category>design</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
