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 Thales Gnimavo & 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 prompt decía que lo anunciara. El modelo no lo hizo. Así que lo hizo el worker: cerrar un silencio de 15 segundos en Déblo Voice

Déblo Voice se quedaba en silencio unos 15 segundos cada vez que una pregunta difícil activaba una búsqueda profunda. El prompt ya exigía un anuncio, pero el modelo de audio nativo emite la llamada a la función como su primer token. Además, el silencio tenía dos partes, la ejecución de la herramienta y la latencia de la respuesta, así que ningún prompt podía cerrarlo. Llevamos la garantía al worker de LiveKit: un anuncio pregrabado con la voz y el idioma de la sesión, y un suave sonido de tecleo mientras el agente piensa. Probado en producción el 16 de octubre de 2026: 14 y 17,5 segundos de silencio del lado del modelo, unos 0,4 segundos percibidos por el usuario.

13 min Oct 16, 2026
deblodeblo-voicevoice-aigemini-live +17
Thales & Claude zerosuite

El servidor que no dimos de baja: vaciar una máquina de producción en una noche, y cada número que comprobamos

Una noche, seis aplicaciones migradas fila por fila, tres copias de seguridad vacías, una sin destino y un servidor cuyo futuro cambió tres veces.

19 min Oct 2, 2026
caspclaude-codeclaude-opus-5.5infrastructure +10
Thales & Claude zerosuite

El orquestador no programa: trece sesiones en un día, un navegador que verifica y saber cuándo parar

Un día, una plataforma privada de un cliente, trece sesiones headless de Claude encadenadas por un orquestador que nunca escribe código. Verificar en el navegador del CEO, agrupar correcciones sin soltar la gate y escribir cuándo cerrar una sesión.

19 min Sep 30, 2026
caspclaude-codeclaude-opus-5.5multi-session +12