Storage & RAG
Upload files, search PDFs with natural language, build AI chat over your documents. Zero configuration.
The file Type
Store files directly in your entities:
entity User {
name: text
avatar: file // Standard file storage
}
// File properties
user.avatar.name // "profile.jpg"
user.avatar.size // 1048576 (bytes)
user.avatar.size_formatted // "1 MB"
user.avatar.type // "image/jpeg"
user.avatar.url // "/files/abc123.jpg"
The semantic file Type
Add semantic to make files searchable with AI:
entity Document {
title: text
content: semantic file // Auto-parsed, chunked, embedded
}
// Upload a PDF
doc = Document {
title: "Company Report",
content: uploaded_file
}
save doc
// Search with natural language
results = search "quarterly revenue" in Document by content
💡 What Happens Automatically
When you save a semantic file, FLIN: extracts text, splits into chunks, generates embeddings, and indexes for search. Zero configuration.
Supported File Types
| Type | Extensions | Processing |
|---|---|---|
| Documents | pdf, docx, doc, txt, md | Text extraction + chunking |
| Spreadsheets | xlsx, xls, csv | Table extraction |
| Images | jpg, png, gif, webp | OCR + caption generation |
| Code | js, py, rs, go, etc. | Syntax-aware chunking |
RAG: Chat With Your Documents
Use ask with context from to build AI chat over your files:
entity Manual {
title: text
content: semantic file
}
// Ask questions about your manuals
answer = ask "What is the return policy?" with context from Manual
// Answer includes sources
answer.text // The generated answer
answer.sources // Which documents were used
answer.sources[0].file // Source file
answer.sources[0].page // Page number
answer.sources[0].score // Relevance score
File Upload UI
entity Photo {
image: file
caption: text
}
selected_file = none
<input type="file"
accept="image/*"
change={selected_file = event.files[0]} />
<button click={
if selected_file {
save Photo {
image: selected_file,
caption: "My photo"
}
}
}>Upload</button>
Multiple Files
files = []
<input type="file"
multiple
change={files = event.files} />
<button click={
{for file in files}
save Document { content: file, title: file.name }
{/for}
}>Upload {files.len} files</button>
Storage Backends
FLIN supports local and cloud storage:
| Backend | Use Case | Config |
|---|---|---|
| Local (default) | Development, small apps | .flindb/blobs/ |
| S3 | AWS deployments | AWS_* env vars |
| R2 | Cloudflare (zero egress) | R2_* env vars |
| GCS | Google Cloud | GCS_* env vars |
Configuration
storage {
// Default: local storage
backend: "local"
path: ".flindb/blobs"
// Or use S3
// backend: "s3"
// bucket: "my-app-files"
}
upload {
max_size: 100.mb
allowed_types: ["image/*", "application/pdf"]
}
Real Example: Document Q&A
entity KBArticle {
title: text
content: semantic file
}
question = ""
answer = none
loading = false
fn askQuestion() {
if question.len > 5 {
loading = true
answer = ask question with context from KBArticle {
limit: 10,
include_sources: true
}
loading = false
}
}
<main>
<input
placeholder="Ask about your documents..."
value={question}
enter={askQuestion()} />
<button click={askQuestion()} disabled={loading}>
{if loading then "Thinking..." else "Ask"}
</button>
{if answer}
<div class="answer">
<p>{answer.text}</p>
<h4>Sources</h4>
{for source in answer.sources}
<div class="source">
<span>{source.file.name}</span>
<span>Page {source.page}</span>
<span>{(source.score * 100).round()}% match</span>
</div>
{/for}
</div>
{/if}
</main>
What FLIN Replaces
❌
S3 SDK
❌
Pinecone
❌
LangChain
❌
Unstructured.io
❌
multer
❌
Elasticsearch
All replaced by one type: semantic file