<?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: Giusseppe Marinelly</title>
    <description>The latest articles on DEV Community by Giusseppe Marinelly (@giusseppemarinelly).</description>
    <link>https://dev.to/giusseppemarinelly</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4126769%2F985a151a-c08b-49e7-bed6-c65df0e978ce.png</url>
      <title>DEV Community: Giusseppe Marinelly</title>
      <link>https://dev.to/giusseppemarinelly</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/giusseppemarinelly"/>
    <language>en</language>
    <item>
      <title>Tres proyectos, tres formas distintas de romperme la cabeza</title>
      <dc:creator>Giusseppe Marinelly</dc:creator>
      <pubDate>Tue, 15 Sep 2026 18:45:02 +0000</pubDate>
      <link>https://dev.to/giusseppemarinelly/tres-proyectos-tres-formas-distintas-de-romperme-la-cabeza-3k6k</link>
      <guid>https://dev.to/giusseppemarinelly/tres-proyectos-tres-formas-distintas-de-romperme-la-cabeza-3k6k</guid>
      <description>&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://gmarinelly.hashnode.dev/tres-proyectos-tres-formas-distintas-de-romperme-la-cabeza" rel="noopener noreferrer"&gt;mi blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Soy estudiante de Ingeniería en Computación y desarrollador. Este año construí tres cosas muy distintas entre sí, y cada una me obligó a desaprender algo. Las dejo aquí porque los problemas interesantes no siempre fueron los que esperaba.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Leer una báscula industrial por puerto serie
&lt;/h2&gt;

&lt;p&gt;El encargo era sustituir el software de pesaje de camiones de una planta. Yo venía de desarrollo web, así que mi primer instinto fue pedir el peso cuando lo necesitara, como una petición HTTP.&lt;/p&gt;

&lt;p&gt;No funciona así. Una báscula no expone una API: emite tramas continuas por el puerto serie, sin que se las pidas y a su propio ritmo. El flujo manda, y hay que escucharlo.&lt;/p&gt;

&lt;p&gt;Eso definió la arquitectura: un proceso leyendo el puerto de forma continua, un backend en &lt;strong&gt;FastAPI&lt;/strong&gt; que retransmite por &lt;strong&gt;WebSocket&lt;/strong&gt;, y dos estaciones de escritorio viendo el mismo peso en el mismo instante.&lt;/p&gt;

&lt;p&gt;Pero el reto de verdad no fue el hardware. Fue el modelo de estados. Un pesaje pasa por &lt;code&gt;en_planta&lt;/code&gt; → &lt;code&gt;pendiente_aprobacion&lt;/code&gt; → &lt;code&gt;aprobado&lt;/code&gt;/&lt;code&gt;rechazado&lt;/code&gt; → &lt;code&gt;completado&lt;/code&gt;, y un registro completado no se puede tocar: es un documento con consecuencias contables. Diseñé el esquema asumiendo que alguien va a intentar editarlo y que la respuesta correcta del sistema es impedirlo.&lt;/p&gt;

&lt;p&gt;Catorce tablas en PostgreSQL, migraciones con Alembic y pruebas con Pytest sobre SQLite aislado. Esto último no fue opcional: cuando un bug cambia un peso facturable, no te enteras en desarrollo, te enteras en una factura.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que aprendí:&lt;/strong&gt; integrar hardware te quita suposiciones que en web das por hechas. Que los datos llegan cuando los pides. Que puedes reintentar. Que el estado vive en tu base.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Epa: una app social donde el problema era la privacidad
&lt;/h2&gt;

&lt;p&gt;Epa es una app móvil para que los estudiantes de mi universidad organicen planes en el campus: mapa de actividades, grupos y mensajería, con acceso cerrado por correo institucional.&lt;/p&gt;

&lt;p&gt;Suena a CRUD. No lo es, porque dos funciones inocentes resultaron delicadas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ubicación.&lt;/strong&gt; Mostrar dónde está la gente es útil y también es vigilancia. La resolví como opt-in con caducidad automática: compartes tu ubicación por un rato y expira sola. Nadie tiene que acordarse de apagarla.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Media efímera.&lt;/strong&gt; "Efímero" en el cliente no significa nada: cualquiera intercepta la petición. La entrega de archivos la controla el servidor, no la app.&lt;/p&gt;

&lt;p&gt;Stack: React Native con Expo, TypeScript, Expo Router, NativeWind y Zustand del lado del cliente; Express, Prisma y PostgreSQL del lado del servidor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que aprendí:&lt;/strong&gt; en una app social, las decisiones difíciles casi nunca son técnicas. Son sobre qué le permites hacer a un usuario con los datos de otro.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. BeatWave: una PWA de música que funciona sin internet
&lt;/h2&gt;

&lt;p&gt;Tenía mi música en un servidor Navidrome propio y quería escucharla en el teléfono sin depender de una app de terceros. Así salió BeatWave: una PWA instalable que consume la API Subsonic de mi servidor.&lt;/p&gt;

&lt;p&gt;La parte divertida fue el offline. Guardar pistas en &lt;strong&gt;IndexedDB&lt;/strong&gt; y servirlas desde un &lt;strong&gt;service worker&lt;/strong&gt; es directo en teoría; en la práctica el trabajo está en decidir qué pasa cuando la red vuelve a medias, cuando el caché y el servidor no coinciden, o cuando el usuario cierra la app a mitad de descarga.&lt;/p&gt;

&lt;p&gt;También integré la &lt;strong&gt;Media Session API&lt;/strong&gt;, que es de esas cosas que casi nadie nota y todos esperan: controles en la pantalla de bloqueo, con carátula y título. Cuando falta, la app se siente rota aunque funcione.&lt;/p&gt;

&lt;p&gt;Stack: React 19, TypeScript, Vite y vite-plugin-pwa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que aprendí:&lt;/strong&gt; offline-first no es "cachear cosas". Es aceptar que tu app va a vivir permanentemente en un estado intermedio entre conectada y desconectada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que tienen en común
&lt;/h2&gt;

&lt;p&gt;Que en los tres el problema real estaba en otro lado del que yo pensaba. En el primero creí que era el hardware y era el modelo de datos. En el segundo creí que era el mapa y era la privacidad. En el tercero creí que era el reproductor y era la sincronización.&lt;/p&gt;

&lt;p&gt;Escribo sobre lo que construyo en &lt;a href="https://gmarinelly.com" rel="noopener noreferrer"&gt;gmarinelly.com&lt;/a&gt;, y el código está en &lt;a href="https://github.com/giusseppemarinelly-droid" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Si trabajas con integración de hardware, offline-first o apps móviles, me interesa mucho leer cómo lo resolviste tú.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>From Spreadsheets to a Self-Hosted Mini-ERP: Building an Inventory System with an AI Layer</title>
      <dc:creator>Giusseppe Marinelly</dc:creator>
      <pubDate>Tue, 15 Sep 2026 18:31:04 +0000</pubDate>
      <link>https://dev.to/giusseppemarinelly/from-spreadsheets-to-a-self-hosted-mini-erp-building-an-inventory-system-with-an-ai-layer-1e8k</link>
      <guid>https://dev.to/giusseppemarinelly/from-spreadsheets-to-a-self-hosted-mini-erp-building-an-inventory-system-with-an-ai-layer-1e8k</guid>
      <description>&lt;p&gt;Inventory at the company I work for used to live in spreadsheets scattered&lt;br&gt;
across warehouses. Nobody could see another site's stock, shortages got&lt;br&gt;
caught too late, and goods sent out to events came back unreconciled. So I&lt;br&gt;
built a replacement — end to end, from the database to the server it runs on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The constraint that shaped everything
&lt;/h2&gt;

&lt;p&gt;This wasn't a greenfield side project with unlimited time. It had to ship,&lt;br&gt;
work for non-technical warehouse staff, and run on infrastructure I could&lt;br&gt;
maintain alone. That constraint killed a lot of "clean" ideas in favor of&lt;br&gt;
boring, reliable ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  One client, two targets
&lt;/h2&gt;

&lt;p&gt;Instead of a separate mobile app and web app, I built a single React Native +&lt;br&gt;
Expo client that compiles to both an Android APK and a static web export,&lt;br&gt;
with no duplicated code:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
# same codebase, two artifacts
eas build --platform android
expo export --platform web

Distribution skips app stores entirely — direct APK install, plus JS-only
OTA updates through EAS Update, so warehouse staff get fixes without
reinstalling anything.

Multi-branch by design, not by accident

Each warehouse ("casa") manages its own inventory independently, with
equivalences between boxes and loose units handled at the domain layer, not
bolted on with if statements scattered across the codebase. A dedicated
events module handles temporary dispatch — checklist out, automatic
reconciliation on return.

An AI layer that can fail without taking the app down

I added a layer on the Claude API for three things: an admin chatbot, invoice
reading through vision, and product-rotation analysis. The important design
decision wasn't the AI part — it was isolating it so that a missing API key,
a timeout, or a rate limit degrades that one feature gracefully instead of
crashing the request pipeline. If the AI layer is unavailable, the core
inventory system doesn't even notice.

The migration nobody asks about until it's too late

The system started on Vercel + Render + Supabase — fast to prototype, but
three separate billing relationships and three separate points of failure
for one internal tool. I migrated everything to a single self-hosted VPS
managed with Coolify: containerized Postgres, own domain, Let's Encrypt SSL,
zero downtime during the cutover.

That's the unglamorous part of "full stack" that portfolios rarely show —
not just writing the API, but being the one who gets paged if the server
falls over.

Where it landed

- In daily use as the company's actual inventory system, not a demo.
- Three services (web, API, database) collapsed into one Docker deployment.
- Users get improvements over the air, without reinstalling.

Full case study, architecture diagram and stack breakdown:
https://www.gmarinelly.com/proyectos/inventario

I'm a Full Stack developer and Computer Engineering student in Venezuela,
open to remote roles. More projects (including a truck-weighing system with
real hardware integration) at https://www.gmarinelly.com.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>fullstack</category>
      <category>mobile</category>
      <category>reactnative</category>
      <category>software</category>
    </item>
  </channel>
</rss>
