Built into every FLIN app

File Storage That Just Works

Upload files. Parse documents. Index content for AI search. Serve with download grants. Local or cloud — FLIN handles it all. No S3 buckets, no CDN configuration, no storage SDKs.

File Upload

The file field type on any entity enables file uploads. Files are stored in .flindb/blobs/ with content-addressable hashing. No configuration needed.

Document Parsing

Upload a PDF, DOCX, or CSV — FLIN extracts the text automatically via document_extract(). Nine formats supported out of the box. Feed parsed content directly into semantic search.

Cloud Backends

Start with local storage. Scale to AWS S3, Cloudflare R2, or Google Cloud Storage with one config change. Signed URLs, download grants, and shareable links — all built in.

How It Works

Add a file field to any entity. Upload through forms or API routes. Files are stored and served — that is the entire setup.

entities/document.flin
entity Document {
    title: text @required
    attachment: file                       // Basic file storage
    content: semantic file                 // Auto-parsed + AI-searchable
    category: text = "general"
}

// Upload via API route with validation
route POST /documents {
    guards { auth: required }
    validate {
        title: text @required
        content: file @required @extension(".pdf", ".docx") @max_size("50MB")
    }
    doc = Document { title: body.title, content: body.content }
    save doc
    response.created(doc)
}

// Upload via form
<form method="POST" action="/documents" enctype="multipart/form-data">
    <input type="file" name="content" />
    <button type="submit">Upload</button>
</form>

Two File Types, Two Superpowers

file stores any file. semantic file parses, chunks, embeds, and indexes — making documents AI-searchable on save.

file
// Store any file as-is
avatar: file

// Access properties
doc.avatar.name       // Original filename
doc.avatar.size       // Size in bytes
doc.avatar.type       // MIME type
doc.avatar.extension  // File extension

// Serve it
<img src={doc.avatar} />
<a href={doc.avatar}>Download</a>
semantic file
// Parse + embed + index on save
report: semantic file

// Text extraction (automatic)
// PDF → text, DOCX → text, etc.

// AI search across files
results = search "budget Q4"
    in Document by report

// RAG: ask questions about files
answer = ask_ai("Summarize the budget",
    ["context": results])

9 Document Formats, One Function

document_extract(file) extracts text from any supported document. No external parsers, no system dependencies, no cloud APIs.

PDF

Text extraction from standard PDF files

.pdf

DOCX

Microsoft Word documents

.docx

HTML

Web pages, exported articles

.html

CSV

Spreadsheet and tabular data

.csv

XLSX

Excel spreadsheets

.xlsx

JSON

Structured data files

.json

YAML

Configuration and data files

.yaml

RTF

Rich text documents

.rtf

XML

Structured markup documents

.xml

File Validators

Control file uploads with declarative validators. Enforced on every save — no bypass possible.

@max_size(max)

Limit maximum file size. Supports KB, MB, GB units. Example: @max_size("50MB")

@mime_pattern("type")

Restrict by MIME type with wildcards: @mime_pattern("image/*"), @mime_pattern("application/pdf")

@extension("ext")

Restrict by file extension: @extension(".pdf", ".doc", ".docx")

@min_size(min)

Enforce minimum file size to reject empty uploads: @min_size("1KB")

@image

Shorthand for image files only. Equivalent to @mime_pattern("image/*")

@document

Shorthand for document files: PDF, DOCX, XLSX, CSV, and other text-extractable formats.

Local to Cloud in One Config Change

Start with local storage. When you outgrow it, switch to any cloud provider without changing a single line of application code.

Local (Default)

Files stored in .flindb/blobs/ with content-addressable hashing. Zero configuration. Move the app, the files move with it.

AWS S3

Amazon S3 with region configuration. Signed URLs for secure downloads. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Cloudflare R2

S3-compatible object storage with zero egress fees. Same API, lower cost. Perfect for media-heavy applications.

Google Cloud Storage

GCS buckets with automatic lifecycle management. Signed URLs and IAM-based access control.

flin.config
# Local storage (default — zero config)
storage {
    backend: "local"
}

# AWS S3
storage {
    backend: "s3"
    bucket: "my-app-files"
    region: "us-east-1"
}

# Cloudflare R2
storage {
    backend: "r2"
    bucket: "my-app-files"
    account_id: "abc123"
}

Download Grants and Secure Sharing

Control who can download files, how many times, and for how long. Generate signed URLs and password-protected download links.

Secure File Sharing
// Generate a download grant with restrictions
grant = doc.attachment.grant(
    max_uses: 5,              // Limit to 5 downloads
    expires: 1.day,           // Expires in 24 hours
    password: "secret123"     // Require password
)
download_url = grant.url

// Or use signed URLs (time-limited, no password)
signed = doc.attachment.signed_url(3600)  // Valid for 1 hour

// Or a permanent shareable link
link = doc.attachment.shareable_url()

Time-Limited

Signed URLs expire after a configurable duration. No permanent public links unless you want them.

Use-Limited

Set a maximum number of downloads per grant. After the limit, the link stops working.

Password-Protected

Require a password to download. Perfect for sharing sensitive documents with external parties.

Storage Architecture

Content-addressable blob storage with SHA-256 hashing. Duplicate files are stored once. Integrity verified on every read.

.flindb/
.flindb/
├── wal.log                # Write-ahead log
├── schema.json            # Entity schemas
├── blob_refs.json         # Reference tracking index
├── data/
│   ├── Document.flindb    # Document records
│   └── User.flindb        # User records
├── blobs/                 # Content-addressable file storage
│   └── {shard}/{hash}/
│       ├── data.pdf       # Original file
│       ├── preview_100.webp
│       ├── preview_300.webp
│       └── preview_800.webp
├── semantic/              # Vector embeddings
│   └── vs_config.json
└── backups/
    └── backup-2026-02-16.flindb

Admin Console Integration

The built-in admin console at /_flin includes full file management with category tracking, size monitoring, and one-click downloads.

Category Breakdown

See how storage is distributed across entity types: images, documents, uploads by category — all in real time.

Size Tracking

Total storage used, per-category sizes, and individual file sizes. Monitor growth and plan capacity.

File Browser

Browse, download, and delete files directly from the admin console. No FTP, no shell access, no cloud dashboard needed.

No S3. No CDN. No Cloud Storage API.

Traditional stacks require AWS S3, Google Cloud Storage, and a CDN for file serving. FLIN handles it all — from local development to cloud production — with zero configuration changes to your application code.