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.

Thales & Claude | March 30, 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