Un lenguaje de programación declarativo para la web, escrito en español.
aplicación MiTienda
incluir modelos/Producto
incluir paginas/inicio
incluir paginas/detalle
página inicio en "/"
título "Bienvenido" clase "hero"
descripción "Los mejores productos al mejor precio"
mostrar Producto recientes
máximo 8
ordenados por precio
si falla
mostrar "Sin conexión"
reintentar en 5 segundos
si el usuario está conectado
botón "Mi cuenta" ir a cuenta
si no
botón "Entrar" clase "btn-primario" ir a login
optimizar para móvil
caché 10 minutos
Eso es todo. Sin webpack. Sin JSX. Sin configuración.
npm install -g @davidbc01/telarO clona el repositorio para desarrollar:
git clone https://github.com/davidbc01/telar
cd telar
npm install
npx ts-node src/cli.ts nuevo mi-proyecto👉 ¿Primera vez? La guía de inicio rápido te lleva de cero a tu primera web interactiva en 5 minutos.
# Crear un proyecto nuevo — genera telar.config.json, src/, public/, todo listo
telar nuevo mi-proyecto
cd mi-proyecto
# Verificar la sintaxis
telar verificar src/app.telar
# Compilar a HTML + CSS + JS
telar compilar src/app.telar
telar compilar src/app.telar -o dist/
# Servir en el navegador con live reload
telar servir src/app.telar
telar servir src/app.telar -p 3050 # en otro puerto, si el 3000 está ocupado
# Gestionar paquetes
telar añadir formulario
telar quitar formulario
telar paquetes
telar buscar <término>mi-proyecto/
app.telar → punto de entrada
paginas/ → una página por archivo
inicio.telar
sobre-nosotros.telar
modelos/ → modelos de datos
Producto.telar
componentes/ → componentes reutilizables
estilos.css → estilos personalizables
telar.paquetes.json
src/app.telar orquesta el proyecto con incluir:
aplicación MiProyecto
estilos "https://cdn.tailwindcss.com" # opcional
incluir modelos/Producto
incluir paginas/inicio
incluir paginas/detalle
Telar genera un estilos.css editable en la raíz del proyecto. Puedes cambiarlo libremente o usar Tailwind:
# CSS propio — edita estilos.css
título "Hola" clase "hero"
botón "Entrar" clase "btn-grande" ir a login
# Con Tailwind
aplicación MiApp
estilos "https://cdn.tailwindcss.com"
botón "Entrar" clase "bg-indigo-600 text-white px-6 py-3 rounded-xl" ir a login
Un diseño envuelve el contenido de tus páginas — navbar, pie, lo que sea compartido. Si declaras uno, se aplica automáticamente a todas las páginas sin tener que hacer nada más:
diseño principal
navbar
título "Mi Tienda"
pie
descripción "© 2026 Mi Tienda"
página inicio en "/"
título "Bienvenido" # se inserta al final del diseño, automáticamente
Si una página necesita un diseño distinto, lo declara explícitamente:
página contacto en "/contacto"
diseño principal
título "Contacto"
Los componentes son piezas reutilizables con parámetros nombrados — sin paréntesis, sin argumentos posicionales que memorizar:
componente Tarjeta con producto y destacado
mostrar producto.nombre
mostrar producto.precio
si destacado
título "⭐ Destacado"
página inicio en "/"
Tarjeta con producto y destacado
Se pueden combinar tantos parámetros como haga falta, separados por y — tanto al declarar el componente como al usarlo. También aceptan contenido pasado desde fuera, con contenido como marcador de dónde va:
componente Tarjeta con producto
título producto.nombre
contenido
página inicio en "/"
Tarjeta con producto
descripción "Esto se inserta donde está 'contenido'"
Si no hay ningún marcador contenido explícito, lo que se pase se inserta al final — igual que hace diseño con el contenido de una página.
Y un componente de un solo parámetro se puede usar como plantilla de una lista real, para que cada elemento se vea con tu diseño en vez del genérico "campo: valor":
componente TarjetaProducto con producto
mostrar producto.nombre
mostrar producto.precio
página inicio en "/"
mostrar Producto recientes
máximo 8
con TarjetaProducto
con TarjetaProducto conecta el componente a los datos reales que llegan de /api/producto — cada producto.propiedad se rellena con el valor real de cada elemento, uno por uno, no con texto fijo. Solo componentes de un único parámetro sirven como plantilla de lista (el elemento de la lista es ese único valor); si el componente declara más de uno, Telar avisa al compilar.
Si escribes mal el nombre de un diseño o un componente, Telar lo detecta al compilar (telar verificar o telar compilar) y te dice cuáles están declarados de verdad — antes de v0.18 esto compilaba en silencio y el error solo se notaba mirando la web ya en el navegador.
Un segmento entre paréntesis en la ruta se convierte en un parámetro. telar servir lo resuelve en tiempo real: una sola página compilada sirve cualquier valor de id, la resolución ocurre en el navegador.
página detalle en "/producto/(id)"
título "Detalle del producto"
mostrar Producto donde id = parametro.id
GET /producto/42 y GET /producto/999 sirven el mismo producto-id.html; el id real se lee de la URL y se usa para pedir /api/producto?id=42 a tu backend. Tu API tiene que soportar ese filtro — Telar solo genera la petición, no el servidor de datos.
página registro en "/registro"
campo "Email" email requerido
campo "Contraseña" contraseña requerido mínimo 8
botón "Registrarse" registrar
requerido, mínimo N y máximo N generan los atributos HTML5 correspondientes (required, minlength, maxlength) y un mensaje de error visible por campo. Al pulsar un botón con una acción, Telar valida todos los campos de la página antes de enviar nada — si algo no es válido, no se llega a hacer la petición. Si todo es correcto, los valores reales del formulario se envían como JSON a /api/accion/<nombre>.
página contador en "/"
variable cuenta = 0
título "Contador"
texto cuenta
botón "Sumar" suma cuenta
botón "Restar" resta cuenta
variable declara estado local a la página, sin llamar a ninguna API. texto cuenta muestra el valor y se actualiza sola cada vez que cambia. suma <variable> / resta <variable> son acciones incorporadas — todo pasa en el navegador, al hacer clic, sin red de por medio. Las variables a nivel de aplicación (compartidas entre páginas) y la asignación de valores arbitrarios quedan para una versión futura.
{ "tema": "oscuro" }página inicio en "/"
botón "🌙 Cambiar tema" alterna tema
Sin declarar tema en telar.config.json, Telar sigue el sistema operativo del visitante (igual que siempre). "oscuro" o "claro" lo fija para toda la web, sin importar el sistema operativo. El botón alterna tema es opcional y se puede combinar con cualquiera de los dos: alterna en vivo y lo recuerda entre visitas con localStorage, sin llamar a ninguna API.
aplicación MiBlog
colección Articulos en "src/contenido/articulos"
página blog en "/blog"
listar Articulos
ordenados por fecha
página detalle en "/blog/(slug)"
diseño principal
artículo Articulos
Cada archivo .md dentro de la carpeta declarada, con cabecera YAML (título, fecha, lo que necesites), se convierte en una página real — un HTML de verdad por artículo, generado en tiempo de compilación, con el contenido ya dentro. No es como las rutas dinámicas normales (que resuelven un id en el navegador con JS): aquí el contenido existe en disco al compilar, así que se genera directamente, mejor para SEO y sin depender de JS para ver el artículo.
---
título: Mi primer artículo
fecha: 2026-08-01
---
Contenido en **Markdown** normal: negrita, *cursiva*, `código`, listas, citas y enlaces.listar muestra la lista (con ordenados por y máximo, igual que mostrar), enlazando a la URL real de cada artículo. artículo solo se puede usar en una página con ruta dinámica ((slug)) — Telar avisa si falta, porque sin eso todos los artículos se generarían con el mismo nombre de archivo, pisándose entre sí.
dominio, favicon y meta se declaran en telar.config.json, en la raíz del proyecto — no en app.telar:
{
"dominio": "https://mitienda.com",
"favicon": "https://mitienda.com/favicon.ico",
"meta": { "theme-color": "#0B0B0D" }
}Y en la página, lo que sí es contenido real:
página inicio en "/"
imagen "https://mitienda.com/img/portada.jpg"
título "Bienvenido a Mi Tienda"
descripción "La mejor tienda online de zapatillas"
Cada página genera automáticamente sus etiquetas og:title, og:description, twitter:card y similares a partir del título y la descripción — sin nada que configurar. imagen "url" se muestra en la página como una imagen normal y, si es la primera de esa página, se usa también como og:image/twitter:image.
Declarar dominio en el config añade dos cosas más: og:url con la URL absoluta real de cada página, y dos archivos nuevos generados en la raíz — sitemap.xml y robots.txt, listos para subir tal cual (incluyendo la URL real de cada artículo de una colección). Las rutas dinámicas normales (/producto/(id)) se excluyen del sitemap automáticamente, porque no representan una URL real.
favicon añade el icono de la pestaña del navegador en todas las páginas — y si no lo declaras pero tienes public/favicon.ico, se usa automáticamente, sin escribir nada. meta añade cualquier etiqueta <meta> personalizada que necesites (color de tema, título para apps de iOS, verificación de Search Console...) — tantas como haga falta, como pares clave-valor en el objeto.
El desarrollo web moderno tiene un problema de complejidad acumulada. Para construir una aplicación simple hoy, un desarrollador necesita:
- Aprender JavaScript y sus peculiaridades históricas
- Elegir entre decenas de frameworks
- Configurar bundlers y herramientas de build
- Gestionar dependencias
- Pensar en optimización de rendimiento
- Manejar errores asíncronos
- Escribir CSS responsivo
Todo eso es trabajo que no tiene nada que ver con el problema que el desarrollador quería resolver.
Un lenguaje donde describes la intención, y el compilador toma todas las decisiones técnicas.
Telar compila a HTML + CSS + JavaScript optimizados. El desarrollador nunca toca esos archivos. El lenguaje tiene opiniones fuertes y defaults inteligentes: responsive, accesible y optimizado por defecto.
Declarativo siempre — Describes qué quieres, no cómo conseguirlo.
El silencio no existe — Telar nunca falla silenciosamente. Los errores son claros, en español, y sugieren cómo arreglarlos.
✗ app.telar:12:9 — se esperaba un número
10 │ mostrar productos recientes
11 │ ordenados por precio
→ 12 │ máximo muchos
^^^^^
13 │ si falla
Sugerencia: los números van sin comillas. Prueba con: máximo 10
Defaults con opinión — Optimización móvil, caché, accesibilidad ARIA y lazy loading activados por defecto. Sin configuración.
Legibilidad humana — El código de Telar puede ser leído por alguien sin experiencia técnica. No es un objetivo estético: es una restricción de diseño.
🟢 En desarrollo activo
| Fase | Estado |
|---|---|
| Especificación del lenguaje | ✅ Completa (v0.1) |
| Lexer — tokenización | ✅ Completo |
| Parser — validador de sintaxis | ✅ Completo |
| Generación de HTML + CSS | ✅ Completo |
| Generación de JavaScript | ✅ Completo |
| CLI — compilar, servir, verificar, nuevo | ✅ Completo |
| Publicado en npm | ✅ Completo |
| Live reload en telar servir | ✅ Completo |
| Extensión VS Code | ✅ Completo |
| Mensajes de error con contexto visual | ✅ Completo |
| Gestor de paquetes | ✅ Completo |
Sintaxis usar y bloque código |
✅ Completo |
| Tests completos (278) + CI/CD | ✅ Completo |
Proyectos multi-archivo con incluir |
✅ Completo |
| Estilos personalizables + Tailwind | ✅ Completo |
Palabra clave clase en elementos |
✅ Completo |
| Diseños y componentes reutilizables | ✅ Completo |
| Rutas dinámicas con parámetros | ✅ Completo |
| Formularios con validación | ✅ Completo |
| Variables y estado local | ✅ Completo |
| Temas visuales | ✅ Completo |
| SEO y metadatos automáticos | ✅ Completo |
| Documentación escrita | ✅ Completo |
| Tests del CLI + cobertura ampliada | ✅ Completo |
Gramática limpia (sin tipo/filtrados por/hacer) |
✅ Completo |
| Componentes conectados a listas de datos reales | ✅ Completo |
| Componentes con varios parámetros nombrados y slots | ✅ Completo |
| Colecciones de contenido (Markdown) | ✅ Completo |
| Estructura de proyecto: telar.config.json + src/ + public/ | ✅ Completo |
| Validación semántica (diseños/componentes inexistentes) | ✅ Completo |
Control del <head> (favicon, meta personalizadas) |
✅ Completo |
Tests de integración de telar servir |
✅ Completo |
| Lanzamiento público | 🟪 Pendiente |
| Web oficial de Telar | 🟪 Pendiente |
- Lexer, parser y generador básico
- Mensajes de error en español
- CLI con
compilar,serviryverificar
- Generación de JavaScript
- CLI instalable vía npm
- Condiciones dinámicas y cargadores de datos
- Live reload en
telar servir - Extensión para VS Code
- Mensajes de error con contexto visual
- Comandos
añadir,quitar,buscarypaquetes - Paquetes como repositorios de GitHub con prefijo
telar-
- Palabra clave
usaren el lenguaje - Bloque
códigopara JavaScript directo - Comando
telar nuevo
- 94 tests automatizados
- CI/CD con GitHub Actions
- Directiva
incluirpara proyectos multi-archivo - Estilos personalizables con
estilos.css - Soporte para Tailwind y CSS externo con
estilos "url" - Palabra clave
claseen títulos, botones, campos y más telar nuevogenera estructura completa con páginas reales- Live reload en todos los archivos
.telary.css - CSS base mejorado con Inter, modo oscuro y variables
- Sintaxis
diseño <nombre>para estructuras compartidas entre páginas - Diseño por defecto aplicado automáticamente si existe uno declarado
- Sintaxis
componente <Nombre>para elementos reutilizables, sin paréntesis ni argumentos posicionales - Uso con
NombreComponente con argumento(rediseñado en v0.23 con varios parámetros nombrados y slots)
- Parámetros en URLs:
página detalle en "/producto/(id)" - Acceso al parámetro con
mostrar Modelo donde campo = parametro.nombre telar servirresuelve rutas dinámicas en tiempo real, no solo archivos estáticos
campo requerido,campo mínimo N [caracteres],campo máximo N [caracteres]- Mensajes de error por campo, mostrados junto al campo inválido
- Los botones
hacerahora validan los campos antes de enviar, y envían sus valores reales en el POST (antes no se enviaba nada)
variable cuenta = 0— estado local por páginatexto cuenta— muestra el valor y se actualiza solabotón "Sumar" suma cuenta/resta cuenta— acciones incorporadas que mutan la variable sin llamar a ninguna API
tema oscuro/tema claroenapp.telar, fijo para toda la web- Sin declarar tema, sigue el sistema operativo automáticamente (comportamiento igual que antes de v0.12)
botón "X" alterna tema— alterna en vivo, recordado entre visitas conlocalStorage- Colores de tema totalmente personalizados (más allá de oscuro/claro) quedan para una versión futura
og:title,og:description,og:image,twitter:cardautomáticos a partir de título/descripción/imagen — sin configuracióndominioentelar.config.jsonhabilitaog:urlabsoluta,sitemap.xmlyrobots.txtimagen "url"— se muestra en la página y, si es la primera de esa página, se usa también como imagen para compartir en redes- Las rutas dinámicas (
/producto/(id)) se excluyen del sitemap automáticamente
docs/inicio-rapido.md— guía de 5 minutos, de instalación a primera web interactivadocs/sintaxis.md— referencia completa (ya se mantenía al día desde v0.8)examples/blog/yexamples/tienda/— reescritos desde cero: los anteriores usaban sintaxis que nunca existió y ni siquiera compilaban. Los nuevos sí, verificado- De paso, dos bugs reales de
telar nuevo: no respetaba rutas absolutas (creaba el proyecto en el sitio equivocado sin avisar) y generaba un nombre de aplicación inválido en ese caso
- Tests del CLI (
nuevo,compilar,verificar) — antes no tenían ninguna cobertura automática - Cobertura de combinaciones diseño + rutas dinámicas + componentes
- Bug real corregido: el CDN de Tailwind (
estilos "https://cdn.tailwindcss.com", el ejemplo destacado del propio README) generaba<link rel="stylesheet">en vez de<script src="...">— nunca había funcionado - 22 tests nuevos (181 en total)
- Rediseño deliberado de la sintaxis antes de comprometerse a la estabilidad de v1.0: cada palabra clave tiene que aportar significado
campo "X" tipo email→campo "X" email—tipono aportaba nadamostrar Modelo filtrados por id = parametro.id→mostrar Modelo donde id = parametro.idbotón "X" hacer sumar/restar/cambiar tema/acción→suma/resta/alterna tema/accióna secas —hacerera puro pegamento- De paso, dos paquetes locales (
formulario,lista) tenían sintaxis que nunca fue real (unsi funcionatras un botón que no existe, una interpolación de texto que Telar nunca ha soportado) — corregidos
mostrar Modelo ... con NombreComponente— antes, los componentes y las listas de datos eran dos sistemas que nunca se hablaban entre sí- Cada propiedad del parámetro del componente se rellena con el valor real de cada elemento de la lista, no con texto fijo
- Probado de extremo a extremo con un DOM real y datos simulados
- Referenciar un
diseñoocomponenteque no existe (típicamente un typo) ahora es un error de compilación, con las opciones válidas declaradas en la sugerencia - Antes compilaba en silencio: el diseño simplemente no se aplicaba, o el componente generaba un comentario HTML invisible en la práctica
- La validación cubre páginas, diseños, y bloques
si/si noanidados
- Antes, el servidor de desarrollo (rutas dinámicas, live reload, recompilación al vuelo) solo se había verificado a mano toda la sesión — ahora tiene 7 tests de integración con peticiones HTTP reales
telar servir src/app.telar -p 3050— puerto configurable, útil si el 3000 está ocupado o para correr varias instancias
según campo = valor→donde campo = valor, el mismo patrón queWHEREen SQL — "según" sonaba a prosa justo al lado del operador=
- Prueba combinando todo lo construido esta sesión en un solo proyecto (diseño + componente + lista real + ruta dinámica + variable + tema + SEO + formulario) — 4 bugs reales encontrados que ningún test aislado había pillado
campo "X" área de textogeneraba un<input>en vez de un<textarea>real desde v0.10campo "X" texto/númerono generaban tipos HTML5 válidos (type="texto", sintype="number"nunca)- Botones/títulos/descripciones con texto sin letras (
"+","−") generaban una clase CSS rota (boton-vacía) - Bug crítico corregido a raíz de construir telar.dev:
botón "X" ir a "https://..."— documentado desde siempre — nunca había funcionado; solo aceptaba nombres de página internos - 13 tests de regresión nuevos (218 en total)
favicon "url"— icono de pestaña, antes imposible de declararmeta "nombre" "valor"— cualquier etiqueta<meta>personalizada (color de tema, título de app iOS, verificación de buscadores...), repetible- Motivado por comparar Telar con frameworks como Astro y encontrar este hueco real al intentar montar telar.dev
- 8 tests nuevos (226 en total)
componente Tarjeta con producto y destacado— parámetros nombrados en vez del "item" genérico de antes, tantos como haga falta separados pory- Slots: contenido pasado desde fuera con
contenidocomo marcador de dónde va, o al final si no se indica (mismo criterio quediseño) si <parámetro>— nuevo, comprueba un parámetro booleano. Se evalúa de verdad (ternario JS real) cuando el componente se usa como plantilla de una lista; en el uso suelto se renderiza siempre (limitación documentada, ese camino no tiene datos reales detrás)- Validación: número de argumentos incorrecto, o un componente de varios parámetros usado como plantilla de lista (solo vale con uno), ahora son errores de compilación claros
- Motivado también por la comparación con Astro — "componentes más potentes" era el segundo de los tres huecos identificados
- 19 tests nuevos (245 en total)
colección Articulos en "src/contenido/articulos"— cada.mdde la carpeta, con cabecera YAML, se convierte en un elemento reallistar Articulos— lista generada en tiempo de compilación, enlazando a la URL real de cada artículoartículo Articulos— genera un HTML real y distinto por cada archivo .md, con el contenido ya dentro (a diferencia de las rutas dinámicas normales, que resuelven todo en el navegador con JS porque los datos vienen de una API en vivo)- Conversor Markdown → HTML propio: encabezados, negrita, cursiva, código, listas, citas, enlaces
- El
sitemap.xmlincluye la URL real de cada artículo automáticamente - Tercero y último de los huecos que salieron al comparar Telar con Astro — el más grande de los tres, casi un subsistema nuevo
- De paso, arreglado otro caso de colisión de palabra reservada: una página no podía llamarse "articulo" (mismo problema que tuvimos con
imagencomo nombre de campo en v0.13) - 17 tests nuevos, con archivos
.mdreales en disco (262 en total)
- Rediseño completo de cómo se organiza un proyecto, motivado por comparar Telar con Astro y encontrar que todo estaba mezclado en un único
app.telar: configuración del sitio y código telar.config.json(raíz del proyecto):idioma,dominio,tema,favicon,meta— ya no van dentro de ningún.telar, y si aparecen ahí, Telar avisa con un error clarosrc/:app.telar,paginas/,contenido/(si usas colecciones) — todo el código, en un sitio fijopublic/:estilos.css,favicon.ico, imágenes, lo que sea — se copia tal cual al resultado. Unfavicon.icoahí se detecta solo, sin declarar nadatelar nuevogenera la estructura completa de golpe — nada que crear a mano- Bug real corregido de paso: el idioma llevaba sin usarse nunca — el HTML siempre decía
lang="es"sin importar lo que se declarara. Ahora se traduce de verdad ("inglés"→lang="en", etc.) - Otra colisión de palabra reservada encontrada y arreglada:
datos Articulofallaba porque "Articulo" colisiona con la palabra clave de colecciones — mismo arreglo que ya se había hecho para nombres de página - Los 3 proyectos reales de esta sesión (
examples/blog,examples/tienda, telar.dev) migrados a la estructura nueva y reverificados compilando - Breaking change total — se decidió deliberadamente no mantener compatibilidad con la estructura antigua, estando pre-v1.0
- 269 tests en total
- Un proyecto real con todo lo de esta sesión a la vez — sacó el bug más serio de toda la sesión: dos páginas con
mostrardel mismo modelo generaban dos funciones JS con el mismo nombre, y la segunda pisaba a la primera en silencio (sin error, sin aviso) - Cada cargador ahora tiene un nombre único por página, con el HTML y el JS sincronizados vía
data-instancia - Arreglado también de raíz otro bug sistémico:
consumirIdentificador()(17 sitios del parser) ya acepta cualquier palabra reservada en posición de nombre, en vez de ir parcheando colisión por colisión - 8 tests de regresión nuevos (278 en total)
- Sintaxis estable — sin breaking changes
- Comunidad activa
- Al menos un proyecto real construido con Telar
- Sitio en telar.dev con guía de inicio rápido y referencia de sintaxis
- Playground online para escribir y compilar Telar desde el navegador
- Showcase de proyectos reales construidos con el lenguaje
La mayoría de los lenguajes de programación usan palabras clave en inglés. Esto añade una barrera invisible para los más de 500 millones de hispanohablantes que aprenden a programar.
Telar no pretende reemplazar el inglés como lengua franca de la programación. Pretende demostrar que la sintaxis de un lenguaje puede ser un dialecto estructurado de cualquier idioma humano, y que eso reduce drásticamente la curva de aprendizaje.
El proyecto está en sus primeras fases. La contribución más valiosa ahora mismo es probar la sintaxis:
- Sigue la guía de inicio rápido (5 minutos, de cero a tu primera web)
- Lee la especificación y la referencia de sintaxis
- Intenta escribir tu caso de uso real en Telar
- Abre un issue con lo que se sintió forzado o incómodo
Toda la discusión de diseño del lenguaje ocurre en Issues.
Apache 2.0 — Ve LICENSE para más detalles.
Telar está en sus primeras fases. La sintaxis puede cambiar. Las ideas son bienvenidas.