Project Structure
Standard directory structures for FLIN applications. All templates use the app/ directory for file-based routing.
Quick Reference
| Template | Command | Complexity |
|---|---|---|
| Minimal | flin new myapp |
1 file |
| Starter | flin new myapp --template starter |
Beginner |
| Todo | flin new myapp --template todo |
Intermediate |
| Fullstack | flin new myapp --template fullstack |
Advanced |
Visit hub.flin.dev to discover and copy ready-made project templates, authentication systems, dashboards, e-commerce starters, and more.
Copy, don't install. Unlike npm, FLIN Hub templates are copied directly into your project — you own and control the code. No dependencies, no version lock, no black boxes.
1. Minimal Project
myapp/
├── app/
│ └── index.flin # Home → /
└── public/
└── index.html # HTML shell
Use for: Quick experiments, learning syntax
2. Starter Template
myapp/
├── app/
│ └── index.flin # Counter demo → /
├── public/
│ └── favicon.ico
└── README.md
Features:
- Reactive variables (
count = 0) - Event handlers (
click={count++}) - Inline styles (
<style>block)
Use for: Learning reactivity, first FLIN app
3. Todo Template
myapp/
├── app/
│ └── index.flin # Todo app → /
├── entities/
│ └── Todo.flin # Entity definition
├── public/
│ ├── favicon.ico
│ └── logo.png
└── README.md
Features:
- Entity definitions (
entity Todo { ... }) - Validators (
@required,@min) - CRUD operations (
save,delete) - Queries (
Todo.all,Todo.where(...)) - Form binding (
bind={newTodo})
Use for: Learning entities, data persistence
4. Fullstack Template
myapp/
├── app/ # File-based routing
│ ├── _middleware.flin # ROOT MIDDLEWARE (global auth)
│ ├── index.flin # Home → / (public)
│ ├── login.flin # Login → /login (public)
│ ├── register.flin # Register → /register (public)
│ │
│ ├── dashboard/ # Protected dashboard area
│ │ ├── _middleware.flin # DASHBOARD MIDDLEWARE
│ │ ├── index.flin # Dashboard → /dashboard
│ │ ├── profile.flin # Profile → /dashboard/profile
│ │ └── settings.flin # Settings → /dashboard/settings
│ │
│ └── api/ # API routes
│ ├── _middleware.flin # API MIDDLEWARE (CORS, rate limits)
│ ├── auth.flin # /api/auth (login/logout)
│ ├── users.flin # /api/users (GET, POST)
│ └── users/
│ └── [id].flin # /api/users/:id (GET, DELETE)
│
├── components/ # Reusable components
│ ├── Header.flin # <Header />
│ ├── Footer.flin # <Footer />
│ ├── Navbar.flin # <Navbar />
│ └── Card.flin # <Card />
│
├── entities/ # Data models
│ └── User.flin # User entity
│
├── styles/ # Shared CSS (auto-injected)
│ ├── global.css # Base styles, reset
│ ├── theme.css # Light/dark theme tokens
│ └── components.css # Shared component styles
│
├── public/ # Static assets
│ ├── favicon.ico
│ ├── icon.png
│ └── logo.png
│
├── translations.flin # i18n (EN/FR)
├── flin.config # Project configuration
└── README.md
Features:
- File-based routing (
app/= routes) - Dynamic routes (
[id].flin=:idparam) - API routes (
route GET { ... }) - Session management (
session.user) - Components (no imports needed)
- Shared styles (
styles/folder - no imports) - Entity with validators
- Time travel (
.history,.at()) - i18n (English/French)
- Theme switching (light/dark)
Use for: Production apps, learning full-stack FLIN
Directory Conventions
| Directory/File | Purpose | Auto-discovery |
|---|---|---|
app/ |
File-based routes | Yes |
app/api/ |
API endpoints | Yes |
app/**/_middleware.flin |
Middleware (auth, logging) | Yes |
components/ |
Reusable components | Yes |
entities/ |
Data models | Yes |
styles/ |
Shared CSS files | Yes |
public/ |
Static assets | Yes |
Middleware System
Middleware files intercept requests before/after route handlers. Place _middleware.flin in any directory to apply middleware to all routes in that directory and subdirectories.
Execution Order
Request → Root _middleware.flin → Nested _middleware.flin → Guards → Handler → Post (reversed)
Root Middleware
// Applies to ALL routes
middleware {
// Pre-handler: runs BEFORE route handler
start = now()
request_id = uuid()
// Skip auth for public routes
if path in ["/", "/login", "/register", "/api/auth"] {
next()
}
// Check authentication
if not session.user {
redirect("/login")
}
next()
}
Dashboard Middleware
// Extra protection for dashboard
middleware {
// Require authenticated user
if not session.user {
redirect("/login")
}
// Optional: require verified email
if not session.user.verified {
redirect("/verify-email")
}
next()
}
Middleware Results
| Result | Effect |
|---|---|
next() |
Continue to next middleware/handler |
redirect(url) |
Short-circuit with 302 redirect |
response(status, body) |
Short-circuit with custom response |
set_cookie(name, value, options) |
Set cookie on response |
delete_cookie(name) |
Remove cookie |
Guards System
Guards protect individual routes with specific requirements. Add guards at the top of any route file.
Authentication Guard
guards {
auth: required // Must be logged in
}
<h1>Welcome, {session.user.name}!</h1>
Role-Based Guard
guards {
auth: required
role: "admin" // Must have admin role
}
<h1>Admin Panel</h1>
Rate Limiting Guard
guards {
rate_limit: 5/minute // Max 5 requests per minute per IP
}
route POST {
// Login logic
}
Combined Guards
guards {
auth: required
role: "admin"
rate_limit: 100/minute
csrf: required
}
route DELETE {
// Protected by auth, role, rate limit, and CSRF
}
Available Guard Types
| Guard | Purpose | Example |
|---|---|---|
auth |
Require authentication | auth: required |
role |
Require specific role | role: "admin" |
rate_limit |
Limit requests | rate_limit: 10/minute |
ip_whitelist |
Allow only listed IPs | ip_whitelist: ["127.0.0.1"] |
ip_blacklist |
Block listed IPs | ip_blacklist: ["evil.com"] |
csrf |
Require CSRF token | csrf: required |
cors |
Configure CORS | cors: ["*.example.com"] |
method |
Restrict HTTP methods | method: ["GET", "POST"] |
content_type |
Require content type | content_type: "application/json" |
header |
Require specific header | header: "X-API-Key" |
Routing Rules
| File Path | Route |
|---|---|
app/index.flin |
/ |
app/about.flin |
/about |
app/blog/index.flin |
/blog |
app/blog/[slug].flin |
/blog/:slug |
app/api/users.flin |
/api/users |
app/api/users/[id].flin |
/api/users/:id |
Entity Location
Entities are always in the entities/ directory:
entity User {
email: string @email @required
name: string @min(2) @max(100)
role: string = "user"
}
Access from anywhere without imports:
user = User.create({ email: "...", name: "..." })
save user
Component Location
Components are in the components/ directory:
<header class="header">
<a href="/" class="logo">FLIN</a>
<nav>...</nav>
</header>
<style>
.header { ... }
</style>
Use from anywhere without imports:
<Header />
<Footer />
Styles Location
Shared CSS files are in the styles/ directory and auto-injected into every page:
myapp/
└── styles/
├── global.css # Always loaded first (reset, base)
├── theme.css # Theme variables (light/dark)
├── buttons.css # Shared button styles
└── utilities.css # Utility classes
Loading Order:
global.css— Base styles, resettheme.css— CSS variables for theming- Other files — Alphabetically
- Component
<style scoped>— Highest priority (overrides)
Use classes from anywhere without imports. Share styles across 50+ pages without duplication. Component <style scoped> can still override.
Configuration
Optional flin.config at project root:
{
name: "my-flin-app"
version: "1.0.0"
server: {
port: 3000
host: "localhost"
}
database: {
type: "flindb"
path: ".flin/data"
}
session: {
secret: "change-in-production"
maxAge: 86400
}
}
- Sample Apps — Try the built-in demos
- Entities — Data persistence
- FLIN Bible — Complete language reference