Construye una aplicación web descentralizada desde cero con Vue, Vite y Tailwind CSS desplegada con IPFS
A lo largo del tiempo las tecnologias y herramientas para contruir, desplegar y entregar sitios web han avanzado a tal punto de que un desarrollo desde cero se ha convertido en la opción mas logica para lograr el producto que queremos ofrecer. Esto es por la facilidad que nos entregan muchos frameworks de componentes como React, Svelte y en este caso Vue para poder enfocarnos en los puntos mas importantes que nuestra app deberia de incluir, como:
- Facil automización
- Integración de lifecycle para realizar tareas asincronas
- Reutilización de componentes
- Agilización del desarrollo
- Buenas herramientas de build
- Y facil integración con plataformas para CI/CD
En esta era web 2.0, existen muchas plataformas para desplegar tu sitio web estatico (o fullstack) de forma sencilla y muchas de ellas son "gratuitas", con facil integración de codigo y plataformas de git para automatizar el delivery de tu app. Algunas de estas pltaformas te pueden sonar: Netlify, Vercel, Glitch, GitHub Pages, Firebase, etc. La mayoría de estos servicios en general ofrecen un buen resultado a la hora desplegar contenido estatico en internet, pero existe un problema...
¿Por que deberia de descentralizar mi App?
Existen varios motivos por lo cual deberias de pensar que las opciones y herramientas descentralizadas pueden ser el futuro de internet gracias a las propuestas que se plantean como, que entender que el gasto que las personas individuales hacen para poner sus equipos en marcha es el costo justo y suficiente para que el mundo pueda acceder a todos los recursos sin necesidad de tener una infraestructura ridiculamente grande (para servir un par de assets). En este caso en concreto deberiamos enfocarnos en un par de preguntas:
-
¿Es mi proveedor de hosting una ayuda o un servicio? Al momento de desplegar nuestra app a una plataforma como las anteriores nombradas deberiamos tomar en cuenta de que estamos poniendo nuestra confianza en manos de un tercero, que ofrece un servicio a cambio de algo. Muchos de estos servicios solo son un gancho para que accedas a un tier mas grande al momento de que tu app crezca. Ademas existe siempre un limite; Dynos, Build Time, Resource Usage etc., cada empresa limita tu proyecto a cierta cantidad de "algo" para que cuando tengas la necesidad de crecer, solo lo puedas hacer con ellos, ya que tu infraestructura estrá ligada a su propio servicio. Por lo que es facil pensar de que es gratis o es una inversión que hacen en ti, pero !No lo es! nada es gratis.
-
¿Son mis proyectos mios y privados en un servicio externo? No. Sin ir mas lejos podriamos decir que hasta nuestra plataforma de Git favorita nos "roba" codigo para entrenar a sus IA's, entonces no es correcto pensar que nuestros datos son nuestros una vez están distribuidos en la red, y no solo que no sean nuestros, porque aunque sean builds publicas, la mayoria de las veces esas builds le perteneceran a la plataforma en concreto.
Por eso nos tomamos la tarea de ofrecer una alternativa viable para poder desplegar tus sitios, sin ningun tipo de costo, disponibles por toda internet y sin acceder a terminos y condiciones que pueden ser perjudiciales para nuestros proyectos. Y por eso creemos que una herramienta web3 como IPFS es perfecta para un usecase como este. ¿Quieres saber que es IPFS y saber por que todas las herrmientas para construir la web3 no solo están basadas en blockchain? Mira este articulo
¿Empezamos?
Una aclaración: Esta web está hecha desde cero y no es la primera implementacion de un framework para distribuir a IPFS, si quieres hacer un boilerplate mas especifico deberias mirar un proyecto como VIPFS.
Setup
Nota: Se necesitan conociemientos basicos de: Shell y Node para este tutorial.
Para poder trabajar con Vite e IPFS necesitaremos instalar algunas cosas antes de meter las manos en la masa:
-
Asegurate de que tienes node 16 o superior instalado en tu sistema, sino descarga e instala node desde aca. Luego revisa si todo salio bién, escribiendo en la consola:
$ node -v$ npm -v
Si todo está en orden deberian de salirte las versiones correspondientes:

-
Instala IPFS en tu sistema:
npm install -g ipfsEsto instalara la CLI de IPFS con la cual trabajaremos mas adelante.
-
Creamos nuestro proyecto con Vite Y Vue3:
npm init vite@latest awesome-wallet --template vuecd awesome-walletnpm install
-
Vue Router, Vuex y Tailwind
npm i --save vue-router@nextnpm i --save vuex@nextnpm install -D tailwindcss postcss autoprefixernpx tailwindcss init -p
Por favor si nunca has trabajado con tailwind mira como instalarlo para vite
Una vez instalado todo lo necesario para un proyecto "grande" con Vue, como normalmente lo hariamos, ahora estamos listos para empezar a escribir algo de codigo. Para esto necesitamos un editor o un IDE, puedes usar el que mas te guste, pero nosotros utilizaremos VSCode.
Pasos a seguir
A partir de ahora ponemos a tu disposición cada sección por el titulo de su implementación.
Estructura de proyecto y Usando el modo Dev
La estructura de las carpetas del proyecto deberian ser algo asi (inicialmente):
.
├─ .gitignore
├─ index.html
├─ package-lock.json
├─ package.json
├─ README.md
├─ vite.config.js
├─ .vscode
│ └─ extensions.json
├─ public
│ └─ favicon.ico
└─ src
├─ App.vue
├─ main.js
├─ assets
│ └─ logo.png
└─ components
└─ HelloWorld.vueToma en cuenta que estrá sujeta a cambios.
Podemos empezar el proyecto en modo dev con el sieguiente comando:
npm run dev.
Una vez empecemos a trabajar, vite nos refrescara automaticamente las vistas para que podamos trabajar con un fluojo mucho mas comodo.
Cada cosa que toquemos será mostrada en solo milisegundos en el navegador.
Vue setup y primeras vistas
Dentro de nuestro archivo ./src/main.js necesitamos declarar un para de cosas
pero para ello primero vamos a crear un par de archivos para hacer el setup de
vue router y nuestras dos views:
Creamos una pequeña template para introducir el router:
./src/App.vue
<template>
<div class="w-full h-full flex flex-col">
<div class="flex px-20 py-10 items-center">
<h1 class="text-2xl">Awesome wallet</h1>
<div class="ml-auto flex items-center">
<router-link class="hover:text-indigo-500 font-bold px-4" to="/">Home</router-link>
<router-link class="hover:text-indigo-500 font-bold px-4" to="/auth">Join</router-link>
</div>
</div>
<div class="flex-1">
<router-view />
</div>
</div>
</template>Configuramos nuestras rutas:
./src/router.js
import { createRouter, createWebHashHistory } from "vue-router";
const routes = [
{
path: "/",
component: () => import("./views/Home.vue"),
},
{
path: "/auth",
component: () => import("./views/Auth.vue"),
},
];
export default createRouter({
routes,
history: createWebHashHistory(),
});Creamos el componente home:
./src/views/Home.vue:
<template>
<div class="w-full h-full flex items-center justify-center">
<h1 class="text-3xl">Hello world</h1>
</div>
</template>Creamos el componente Auth
./src/views/Auth.vue:
<template>
<div class="w-full h-full flex items-center justify-center">
<h1 class="text-3xl">Auth</h1>
</div>
</template>Por ultimo editamos nuestro ./src/main.js:
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import "./main.css";
const app = createApp(App);
app.use(router);
app.mount("#app");Se ha modificado de como estaba anteriormente para incluir el router y el css proveido por tailwind (ver como instalar tailwind).
Un poco de funcionalidad
Ahora podriamos decir que tenemos una app estatica lista, pero para que nuestro sitio tenga alguna funcionalidad en concreto, agregaremos algo de condigo extra. A este punto podrias saltarte al paso de Build y Deploy.
El objetivo de nuestra app por ahora será de encriptar un secret y poder verlo al escribir una contraseña que solo tu sepas, con el objetivo de en un proximo blog, hacer una wallet con stellar-sdk.
Para esto, creamos los siguientes archivos:
./src/store.js
import { createStore } from "vuex";
export default createStore({
state: {
username: "",
encryptedToken: "",
},
mutations: {
setUsername(state, username) {
state.username = username;
},
setEncryptedToken(state, token) {
state.encryptedToken = token;
},
},
actions: {
setAuth({ commit }, { username, encryptedToken }) {
commit("setUsername", username);
commit("setEncryptedToken", encryptedToken);
},
removeAuth({ commit }) {
commit("setUsername", "");
commit("setEncryptedToken", "");
},
},
});Modificamos nuestras vistas ./src/views/Home.vue
y
./src/views/Auth.vue

Y para terminar el front end creamos un servicio para generar, encriptar y
desencriptar nuestra key, en la el archivo
./src/services/crypto.service.js
import { AES, enc, lib } from "crypto-js";
export const randomUUID = () => {
return lib.WordArray.random(16).toString(enc.Hex);
};
export const encrypt = (text, key) => {
return AES.encrypt(text, key).toString();
};
export const decrypt = (text, key) => {
return AES.decrypt(text, key).toString(enc.Utf8);
};Despues de todo esto deberiamos tener algo asi:

Ahora nuestra app está lista y en este punto podriamos subirla a cualquier proveedor de hosting para sitios estaticos, pero ahora empieza la magia de ipfs....
Build y Deploy
Ya solo nos quedaconstruir nuestro sitio y distribuir a IPFS, para eso vamos a
añadir los siguients scripts a nuestro package.json
{
"build": "vite build",
"deploy": "cd dist && npx all-relative && cd .. && jsipfs add -r dist/",
"release": "npm run build && npm run deploy"
}Abre una terminal y ejecuta tu daemon:
$ jsipfs daemonAbre otra terminal y ejecuta el script de deploy:
$ npm run releaseY finalmente tendremos algo como esto en la consola:

Esto significa que nuestros arvhivos están ahora en ipfs y disponibles a travez
de todas las gateways de ipfs, por lo que ¡ESTA VIVO!. Toma encuenta de que
a pesar de que todos los assets son accesibles con su hash el que nos interesa
es el de la carpeta base, por lo que lo copiamos para mas tarde:
QmbBkfkRbXZzLgvSx7FFnLmHHDEpZktAPVVA2Am8wtFkS4.
Pero aca no podemos parar, ya que la accesibilidad de nuestra app sigue siendo limitada y debemos solucionarlo..
Pineando el contenido
Cuando creamos un archivo o varios de ellos en nuestro repositorio de IPFS,
solamente lo podemos ver nosotros en el localhost y nuestros amigos que tengan
un nodo propio solo si nuestro nodo está andando mientras ellos lo clonan. Por
lo que si miramos el hash de nuestra carpeta dist (por ejemplo)
QmbBkfkRbXZzLgvSx7FFnLmHHDEpZktAPVVA2Am8wtFkS4 en la gateway local
http://localhost:8080/ipfs/QmbBkfkRbXZzLgvSx7FFnLmHHDEpZktAPVVA2Am8wtFkS4 que
expone nuestro deamon (que seguimos ejecutando desde la build) vamos a poder
visusalizar nuestra app, pero si cerramos el daemon de ipfs y queremos pasarle
nuestro sitio a alguien, no lo va a poder ver, y esto no tiene sentido... ¿por
que tendria que dejar mi daemon activo para que otros puedan ver mi sitio?.
Pues por como IPFS funciona para que un archivo esté disponilbe para otros
usuarios tienen que haber nodos que estén "hosteando" nuestros archivos por
lo que si nuestros amigos (que ya clonaron la data) o yo cierro mi nodo y no
existe nadie disponible que haya clonado y esté ofreciendo nuestra data, si
alguien externo quisiese acceder con el hash a través de otra gateway, va a ser
imposible.
¿Entonces cual es la solución para que mi app no dependa de mi o de otros nodos relacionados ami?
Hay dos respuestas validas para esto:
-
Solicitar nuestros archivos en gateways de nodos publicos que admitan el pineo de contenido. Aqui puedes encontrar una lista de nodos publicos en los que puedes solicitar el hash de tu carpeta dist, por ejemplo
https://ipfs.io/ipfs/QmbBkfkRbXZzLgvSx7FFnLmHHDEpZktAPVVA2Am8wtFkS4la cual es la gateway publica oficial de ipfs (y el hash es nuestro), y no solo lo podrias hacer en uno o dos, mientras mas nodos tengan tu app, mejor. Pero esto tiene un par de problemas: 1) es publico por lo que puede llegar a ser lento en algunas ocaciones. 2) Es un trabajo que tienes que hacer manualmente, y se vuelve mas dificil si nombras tus archivos para que esten disponibles con ipns. -
Lo mas factible seria utilizar un servicio de pineo, lo que basicmanete es un servicio para replicar tu archivos de ipfs en una cantidad ridiculamente enorme de nodos en todo el mundo. Por lo que a de mas tambien funciona como una CDN y tu sitio es rapidamente accesible a traves de cualquier gateway a nivel mundial. En este caso existen servicios como pinata que con solo introducir el hash de tu app, tienes una replicación automatica en muchos nodos, al instante.
Como hayas decidido distribuir, ahora se puede decir que tu sitio está disponible para su uso a través de la red de la red ipfs.
Configurando un dominio
Este paso es totalmente opcional ya que ipfs siempre va a mantener el hash de tus archivos, y puedes versionar con ipfs name en IPNS.
Si tienes acceso a un servicio de nombres de dominio como Namecheap, Google Domains, GoDaddy o cualquier otro servicio de dominio incluyendo gratuitos como Freenom, puedes seguir estos pasos. Si no tienes un nombre de dominio para asignar, puedes leer esta sección. Nos sumergiremos en el uso de servicios de nombres descentralizados como Ethereum Naming Service (ENS) mas adelante.
-
Asegurate de copiar la url de tu sitio de una gateway confiable en este caso la gateway de infura hace algo especial, si colocas el hash como en cualquier gateway, te crea un subdminio base de la siguiente manera
https://infura-ipfs.io/ipfs/QmbBkfkRbXZzLgvSx7FFnLmHHDEpZktAPVVA2Am8wtFkS4el resultado es un subdominio que puedes utilizar forwarded o aliased con tu proveedor de dominios preferido:https://bafybeif64byoox5dsv7whhzlhsvijxpvbs4oaeqwufpwgmad3mv2zgmtte.ipfs.infura-ipfs.io/ -
Configura la redirección permanente con tu proveedor de hosting, recuerda que el modo de forwarding sea de 301:

Esta solución redireccionara todas las request a la gateway que utilizas como tu gateway principal, y no actuará como un proxy. Esto puede que se convierta en una experiencia de usuario poco agradable y tal vez algo tosca, por lo que aun hay un layer mas que podrías implementar para que el resultado final sea lo mas pulido posible:
Utiliza un servicio de DNS dedicado: A de mas de ayudarte con tu sitio en un formato web2 proveyendo cosas como defensa contra ataques (que en este caso no importa demasiado) y otras mas utiles como manejo de los registros DNS en tu sitio y encriptado automatico por SSL, podemos considerar que tanto para Web 2 y 3 tener un proveedor de DNS por separado siempre es buena opción.
Para que tu dominio (en este caso vueipfs.ml) sea realmente el nombre de tu sitio en la barra de busquedas, sin redirecciones ni hacky stuff, debemos realizar un par de pasos con nuestro porvedor de DNS favorito (en este caso cloudflare).
- Apuntar los nameservers desde tu proveedor de dominios, a los namservers de
cloudflare
Para saber como agregar un sitio a tu proveedor de DNS debes mirar sus instrucciones.
- Generar un par de registros:

En un registro TXT a el subdominio _dnslink debemos colocar el siguiente
contenido: dnslink=/ipfs/{tu_hash_de_ipfs}
En un registro CNAME debemos apuntar nuestro root (@) a una gateway, en este
caso cloudflare tiene una propia: cloudflare-ipfs.com
Lo que hicimos es un implementación de dnslink si quieres saber como dnslink funciona mira esto.
Y ya tenemos un sitio con vida y la demo la puedes visitar en http://vueipfs.ml/
Conclusión
Las herramientas como IPFS e HyperCore son el paso hacia el futuro en cuanto a WEB3 se refiere y aunque el proceso de deploy pueda parecer algo ma extenso, es algo que puedes hacer de extremo a extremo, empezand por tu computadora sin depender de ningun servicio externo y aunque en este caso, utilizamos un servicio de pineo masivo, es posible que no necesites hacerlo si tu web adquiere cierta popularidad y aun asi no significa que estas plataformas tengan el poder de todas las maquinas en donde se pinean los archivos.
Es momento de pensar que estamos en una epoca privilegiada del internet donde cualquier persona con los conocimientos tecnicos sufiecientes tiene la oportunidad de construir proyectos increibles que estan a la palma de la mano gracias a la manera en la que queremos hacer las cosas con web3.
Con implementaciones estables y adopción de los conceptos basicos de como esto funciona es la manera en la que en devland queremos dar entender que afuera existe un internet mas independiente, mas libre y autogorbenado, donde no solo podemos desplegar sitios web a producción, sino que podemos crear economias, sistemas de comunicación multidireccionales sin necesidad de que exista el hombre en el medio, gobernanzas y sistema de repartición justa de bienes y servicios, etc.
Quizas sea el comienzo y quizas deberias tu unirte al avance.