Back to flin
flin

Cómo se ve FLIN en la práctica: primeros ejemplos

Ejemplos reales de código FLIN: aplicación de tareas, dashboard reactivo, rutas de API, consultas a base de datos -- todo en un solo lenguaje.

Juste A. Gnimavo (Thales) & Claude | March 26, 2026 5 min flin
EN/ FR/ ES
flinrust

La teoría es barata. Cada nuevo lenguaje promete simplicidad, cada nuevo framework afirma resolver la complejidad, y cada manifiesto se lee bien hasta que intentas construir algo real. FLIN ha publicado su visión, su arquitectura y su filosofía. Ahora es momento de mostrar el código.

Este artículo presenta seis aplicaciones FLIN completas, progresando de trivial a sustancial: un contador, un hello-world con enlace de entrada, una aplicación de tareas completa con persistencia, un blog con comentarios, una API con endpoints CRUD y un dashboard en tiempo real con consultas temporales. Cada ejemplo es un programa funcional -- no un boceto, no pseudocódigo, no un extracto simplificado que oculta las partes difíciles.

El objetivo es responder a la pregunta que todo desarrollador hace cuando se enfrenta a un nuevo lenguaje: ¿cómo se ve realmente cuando me siento a construir algo?

Ejemplo 1: el contador (3 líneas)

flincount = 0

<button click={count++}>{count}</button>

Tres líneas. Una variable reactiva. Un elemento HTML. Un manejador de eventos. Guarda esto como counter.flin, ejecuta flin dev, y el navegador se abre con un botón mostrando 0. Haz clic. El número incrementa. No hay nada más que configurar, nada más que instalar, nada más que entender.

Ejemplo 2: enlace de entrada (5 líneas)

flinname = ""

<div>
    <input placeholder="Your name" value={name}>
    <h1>Hello, {if name then name else "World"}!</h1>
</div>

El atributo value={name} crea un enlace bidireccional. Cuando el usuario escribe en la entrada, name se actualiza. Cuando name se actualiza, el contenido del <h1> se re-renderiza.

Ejemplo 3: la aplicación de tareas (43 líneas)

flintodos = []
filter = "all"
newTodo = ""

entity Todo {
    title: text
    done: bool = false
    created: time = now
}

filtered = match filter {
    "all" -> Todo.all
    "active" -> Todo.where(done == false)
    "completed" -> Todo.where(done == true)
}

<main>
    <h1>My Todos</h1>

    <input value={newTodo} placeholder="What needs to be done?"
           enter={save Todo { title: newTodo }; newTodo = ""}>

    <nav>
        <button click={filter = "all"}>All</button>
        <button click={filter = "active"}>Active</button>
        <button click={filter = "completed"}>Done</button>
    </nav>

    {for todo in filtered}
        <div class="todo-item">
            <input type="checkbox" checked={todo.done}
                   change={todo.done = !todo.done; save todo}>
            <span class={if todo.done then "done" else ""}>{todo.title}</span>
            <button click={delete todo}>x</button>
        </div>
    {/for}

    <footer>{Todo.where(done == false).count} items left</footer>
</main>

La palabra clave entity declara un tipo de datos persistente. El compilador de FLIN genera una tabla de base de datos en FlinDB, registra métodos de consulta y habilita el rastreo temporal. La expresión match selecciona la consulta de base de datos apropiada según el filtro. La palabra clave save crea o actualiza registros. La palabra clave delete los elimina.

Ejemplo 4: un blog con comentarios (65 líneas)

flinentity Post {
    title: text
    content: semantic text
    slug: text
    published: bool = false
    created: time = now
}

entity Comment {
    post: Post
    author: text
    content: text
    created: time = now
}

posts = Post.where(published == true).order(created, "desc")

<main>
    <h1>My Blog</h1>

    {for post in posts}
        <article>
            <h2><a href="/post/{post.slug}">{post.title}</a></h2>
            <p>{post.content.slice(0, 200)}...</p>
            <small>{post.created.format("MMMM D, YYYY")}</small>
        </article>
    {/for}
</main>

El tipo semantic text indica a FLIN que genere automáticamente embeddings vectoriales, habilitando la búsqueda semántica. post: Post en la entidad Comment crea una relación de clave foránea. El enrutamiento basado en archivos con post/[slug].flin crea una ruta dinámica.

Ejemplo 5: endpoints de API (30 líneas)

flin// api/users.flin
entity User {
    name: text
    email: text
    role: text = "user"
    active: bool = true
}

route GET {
    User.where(active == true)
}

route POST {
    user = User {
        name: body.name,
        email: body.email,
        role: body.role || "user"
    }
    save user
    user
}

La palabra clave route declara un manejador de método HTTP. body es el cuerpo de la solicitud parseado (JSON). params proporciona parámetros de URL. El valor de retorno se serializa automáticamente a JSON con el código de estado apropiado.

Ejemplo 6: un dashboard con viaje en el tiempo (35 líneas)

flinentity Metric {
    name: text
    value: number
    recorded: time = now
}

revenue_today = Metric.where(name == "revenue").first
revenue_yesterday = revenue_today @ yesterday

change = if revenue_yesterday then
    ((revenue_today.value - revenue_yesterday.value) / revenue_yesterday.value) * 100
else
    0

<div class="dashboard">
    <div class="metric">
        <h3>Revenue</h3>
        <span class="value">{revenue_today.value.format()}</span>
        <span class={if change > 0 then "up" else "down"}>
            {change.to_fixed(1)}%
        </span>
    </div>

    <div class="history">
        <h3>Revenue History</h3>
        {for version in revenue_today.history.last(7)}
            <div class="history-item">
                <span>{version.recorded.format("MMM D")}</span>
                <span>{version.value.format()}</span>
            </div>
        {/for}
    </div>
</div>

El operador @ es la sintaxis de consulta temporal de FLIN. revenue_today @ yesterday recupera el estado de la métrica de ingresos tal como existía ayer. FlinDB mantiene el historial completo de cada entidad automáticamente.

Los patrones

Después de seis ejemplos, ciertos patrones emergen:

Un archivo, una preocupación. Cada archivo .flin es una unidad autocontenida. No hay separación de "frontend" y "backend."

La reactividad es invisible. Las variables son reactivas por defecto. El desarrollador nunca piensa en gestión de estado, suscripciones o re-renderizado.

La persistencia es una palabra clave. save y delete son operaciones a nivel de lenguaje, no llamadas a bibliotecas.

Las consultas son cadenas de métodos. Entity.where(...), Entity.all, Entity.find(...) -- las consultas de base de datos se leen como inglés.

El tiempo es un concepto de primera clase. Cada entidad tiene historial. El operador @ consulta estados pasados.


Siguiente en la serie: The Roadmap to FLIN v1.0 -- 3.452 pruebas pasan, 409 funciones integradas funcionan, y esto es todo lo que queda antes del lanzamiento estable.

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude deblo

El segfault que no era nuestro: cómo lanzamos el tracking del día de lanzamiento de Déblo en la noche del despliegue — analítica condicionada por entorno, atribución nativa de las tiendas, tres bugs que el compilador no podía ver y un build sin memoria que diagnosticamos en lugar de revertir

El 1 de julio de 2026 — el día del lanzamiento — el riesgo nunca fue el texto. Era que las campañas de pago salieran a ciegas. Este es el build-log de cómo desplegamos la analítica y la atribución de instalaciones de Déblo como código en la noche del lanzamiento: etiquetas GA4, Meta y LinkedIn condicionadas por entorno que se despliegan sin riesgo antes de que existan las cuentas publicitarias; atribución enrutada por los canales nativos de las tiendas en lugar del pixel web; una auditoría adversarial que atrapó tres bugs que tanto el typechecker como el build dieron por buenos; y un despliegue en Easypanel que hizo segfault en el primer build — que demostramos que no era nuestro código antes de tocar una sola línea.

18 min Jul 1, 2026
deblolaunch-dayclaude-opus-4.8claude-code +26
Thales & Claude thales

Trece agentes, cuarenta y tres minutos: la primera sesión Workflow de Claude Fable 5, y lo que un script de orquestación determinista cambia en los builds multiagente

Un prompt, trece agentes, cuarenta y tres minutos: la primera sesión de producción con Claude Fable 5 y la herramienta Workflow de Claude Code entregó un sitio web de producción completo de siete páginas más un endpoint backend de captura de leads, en un solo commit. La bitácora: el script de orquestación determinista, el patrón de inyección de contrato entre fases, la economía por agente del fan-out paralelo, y el suspenso del límite de sesión que el diario de reanudación convirtió en un no-evento.

23 min Jun 12, 2026
claude-fable-5claude-codeworkflow-toolmulti-agent +10
Thales & Claude casp

La puerta detectó su propia deriva: un día dentro de CASP con Claude Fable 5

Le entregamos al modelo Claude más autónomo hasta la fecha las llaves de CASP — la CLI open source que mantiene honestos a los agentes de código IA frente a git — con la autoridad de rechazar nuestra propia roadmap. Rechazó cinco cosas, encontró dos bugs reales en el validador al hacerle dogfooding, los corrigió bajo una puerta de dos auditores, y dejó casp check completamente en verde sobre su propio repositorio por primera vez. CASP 0.3.0 es el resultado.

15 min Jun 10, 2026
caspzerosuiteworkflowai-cto +9