The Backend Is Built In

No Express. No Django. No Rails. FLIN is a complete backend framework — API routes, database, authentication, file storage, background jobs, and 420+ server-side functions. All in one binary.

Backend vs. Dashboard — What's the Difference?

Many beginners confuse the backend with the admin dashboard. Think of a restaurant: the frontend is the dining room, the backend is the kitchen, the API is the waiter — and FLIN is the food truck that does it all.

Frontend is the dining room, Backend is the kitchen, API is the waiter, FLIN is the food truck

Backend

The engine behind the scenes. Handles data, logic, authentication, file processing, emails, and API responses. Users never see it directly — but everything depends on it.

Admin Dashboard

A visual interface to manage your app's data. Browse records, view metrics, run queries. It's a frontend built on top of the backend — not the backend itself.

FLIN

Both at once. Write backend logic in .flin files, and FLIN auto-generates the admin dashboard at /_flin. No separate tools, no separate deployment.

Before FLIN vs. After FLIN

Traditional backends require dozens of config files, package managers, and build tools. FLIN replaces all of that with a single binary and .flin files.

Before FLIN: complex configuration mess. After FLIN: just app.flin
15+
to
0
Config Files
1,800+
to
0
Dependencies
5+
to
1
Languages
3 hrs
to
5 min
Setup Time

Everything a Backend Needs

FLIN's backend isn't a toy — it's production-grade. Here's everything you get out of the box, with zero npm installs.

API Routes

Define route GET /users and route POST /users with guards, validation, and response helpers. File-based routing — app/api/users/[id].flin becomes /api/users/:id.

Embedded Database

FlinDB is built into the binary. WAL with CRC-32 checksums, auto-checkpointing, per-entity data files. save user writes to disk. No PostgreSQL, no connection strings.

Authentication

Sessions, 8 OAuth providers, 2FA/TOTP, JWT, bcrypt, WhatsApp OTP — all native functions. Middleware guards protect routes. No Passport.js, no Auth0.

File Storage

Upload files with a file type field. 9 document formats auto-parsed (PDF, DOCX, XLSX...). Cloud backends: Local, S3, R2, GCS. Download grants for secure sharing.

Background Jobs

Queue tasks with job_queue(), check status with job_status(), schedule recurring work with job_recurring(). Built into the runtime — no Redis, no Bull, no Celery.

Email

send_email(to, subject, body) — one function. HTML templates, attachments, and bulk sending. Configure SMTP credentials in .env and you're done.

HTTP Client

http_get(), http_post(), http_put(), http_delete(), http_patch(). Call any external API from your backend. JSON parsing included.

Cryptography

bcrypt_hash(), aes_encrypt(), sha256(), hmac(), jwt_encode(), totp_secret(). Production-grade crypto without OpenSSL headaches.

Validation

43 decorators: @required, @email, @minLength, @max, @one_of, @unique, @index. Declare constraints on entities and route bodies — FLIN enforces them.

A Complete API in One File

Here's a full CRUD API with authentication, validation, and error handling. No framework, no ORM, no boilerplate.

app/api/products.flin
entity Product {
    name: text @required @minLength(2)
    price: money @min(0)
    category: text @one_of("Electronics", "Books", "Clothing")
    description: semantic text
    image: file
    active: bool = true

    @index(category)
    @index(active, category)
}

// List products with filtering
route GET /api/products {
    category = query.category
    products = match category {
        none -> Product.where(active == true)
        _ -> Product.where(active == true && category == category)
    }
    response.ok({ products: products })
}

// Create product (auth required)
route POST /api/products {
    guards { auth: required, csrf: required }
    validate {
        name: text @required
        price: money @required @min(0)
        category: text @required
    }
    product = Product {
        name: body.name,
        price: body.price,
        category: body.category,
        description: body.description
    }
    save product
    response.created(product)
}

// Semantic search ("comfortable office chair")
route GET /api/products/search {
    results = search query.q in Product
    response.ok({ results: results })
}

// Delete product
route DELETE /api/products/:id {
    guards { auth: required }
    product = Product.find(params.id)
    if product == none {
        response.not_found("Product not found")
    }
    delete product
    response.ok({ deleted: true })
}

420+ Server-Side Functions

Every function runs on the server. No client-side JavaScript needed for business logic. Here's a sampling of what's available.

Strings

trim, split, join, replace, slugify, base64, url_encode, pad...

35 functions

Math

abs, round, sqrt, pow, sin/cos, random, gcd, factorial, median...

35 functions

Lists

push, pop, sort, unique, map, filter, reduce, zip, group_by...

34 functions

Date/Time

now, today, format_date, add_days, diff_days, is_weekend...

35 functions

Crypto

uuid, md5, sha256, bcrypt, jwt, aes_encrypt, hmac, totp...

18 functions

Validation

is_email, is_url, is_uuid, matches_pattern, is_strong_password...

20 functions

HTTP Client

http_get, http_post, http_put, http_delete, http_patch, http_head

7 functions

Email & PDF

send_email, pdf_from_html, image processing, file conversion...

10 functions

AI

ask_ai, search (semantic), keyword_search, 8 LLM providers...

15 functions

Auth

8 OAuth providers, sessions, 2FA/TOTP, WhatsApp OTP, JWT...

25 functions

Entities

save, delete, destroy, where, find, order_by, sum, avg, count...

24 functions

Maps

keys, values, has_key, get, set, merge, pick, omit, entries...

15 functions

Middleware & Guards

Protect your routes with a single file. Authentication, CSRF protection, rate limiting, and role-based access — all declarative.

app/_middleware.flin
middleware {
    matcher: ["/dashboard/**", "/api/**"]
    exclude: ["/", "/login", "/register"]

    // Check authentication
    if session.user == none {
        redirect("/login")
    }

    // Continue to route handler
    next()

    // Post-handler: add headers
    set_header("X-Powered-By", "FLIN")
}
L2-3
Pattern MatchingGlob patterns select which routes are protected and which are public.
L6-8
Session CheckRedirect unauthenticated users. Sessions are persisted via cookies automatically.
L11
next()Passes control to the route handler. Code after next() runs post-response.
L14
Post-HandlerSet headers, log requests, or run cleanup after the route has responded.

Route Guards & Validation

Every route can declare guards and validation rules. FLIN rejects invalid requests before your code runs.

app/api/orders.flin
route POST /api/orders {
    // Guards — reject before processing
    guards {
        auth: required
        csrf: required
    }

    // Validation — reject if body is invalid
    validate {
        product_id: int @required
        quantity: int @required @min(1) @max(100)
        email: text @required @email
        notes: text @maxLength(500)
    }

    // Your code — only runs if guards + validation pass
    product = Product.find(body.product_id)
    if product == none {
        response.not_found("Product not found")
    }

    order = Order {
        product_id: body.product_id,
        quantity: body.quantity,
        email: body.email,
        total: product.price * body.quantity
    }
    save order

    // Send confirmation email
    send_email(body.email, "Order Confirmed", "Your order #" + to_text(order.id) + " is confirmed.")

    response.created(order)
}

Guards

auth: required rejects unauthenticated requests. csrf: required validates CSRF tokens. Guards run before validation.

Validate Block

Declare expected fields with types and decorators. Invalid requests get a 400 Bad Request with field-level error messages — automatically.

Response Helpers

response.ok(), response.created(), response.bad_request(), response.not_found(), response.forbidden(), response.conflict().

File-Based Routing

Your file structure is your routing table. No router configuration, no route registration, no mapping files.

Project Structure
myapp/
├── app/
│   ├── index.flin            → GET  /
│   ├── about.flin            → GET  /about
│   ├── _middleware.flin      → Auth guard
│   ├── dashboard/
│   │   ├── index.flin        → GET  /dashboard
│   │   └── settings.flin     → GET  /dashboard/settings
│   └── api/
│       ├── users.flin        → GET|POST /api/users
│       └── users/
│           └── [id].flin     → GET|PUT|DELETE /api/users/:id
├── entities/
│   └── User.flin             → Entity definition
├── components/               → Reusable UI
├── layouts/                  → Page wrappers
├── i18n/                     → Language files
└── .flindb/                  → Database (auto-created)

Transactions & Background Jobs

Complex backend operations — atomic transactions, scheduled tasks, and async processing — all built in.

Transactions & Jobs
// Atomic transaction — all or nothing
begin_transaction()
    order = Order { user_id: user.id, total: total }
    save order

    payment = Payment { order_id: order.id, amount: total }
    save payment

    user.balance = user.balance - total
    save user
commit_transaction()

// Background job — non-blocking
job_id = job_queue("send_invoice", {
    order_id: order.id,
    email: user.email
})
status = job_status(job_id)

// Recurring job — cron-like
job_recurring("cleanup_expired", "0 2 * * *")
job_schedule("send_reminder", add_hours(now(), 24))
L1-10
TransactionsAll three saves succeed or none do. If payment fails, the order is rolled back.
L13-17
Job QueueQueue work for async processing. Returns a job ID to check status later.
L20-21
SchedulingCron-style recurring jobs and one-time scheduled tasks. No external scheduler needed.

Auto-Generated Admin Console

Every FLIN app ships with a full admin dashboard at /_flin. It's not a separate project — it's generated from your backend code.

Entity Browser

Browse, search, sort, create, edit, and delete records for every entity. Inline editing, bulk actions, CSV export.

Query Editor

Execute FLIN queries live: User.where(active == true).count. Query history saved in IndexedDB.

REST API Docs

Auto-generated Swagger-like documentation for all your routes. Test endpoints directly from the browser.

Real-Time Metrics

Request counts, response times, status codes, memory usage, database size — live gauges refreshing every 5 seconds.

Request Logs

Filterable log viewer with level, source, and search. Auto-polling every 2 seconds. Clear logs with one click.

AI Gateway

Monitor AI provider usage, check API key configuration, and manage embedding providers from a single panel.

Your Backend, Simplified

Stop juggling 15 tools. Install FLIN, write your logic, and ship. The backend is already there.

curl -fsSL https://flin.sh | bash