Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a239ebd
Add e-commerce store example app
Mar 16, 2026
b9af51a
Replace Brand<T, Tag> with single-variant union newtypes
Mar 16, 2026
7bd3878
Refactor store example with aspirational Floe syntax
Mar 16, 2026
7336ddf
Use validated values in checkout instead of discarding them
Mar 16, 2026
5140556
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
fb5318b
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
313bdaa
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
3464f13
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
4d388b0
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
d23c59c
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
9d4779a
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
c947b1a
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
c58fe11
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
ba18ca2
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 16, 2026
83c584a
Fix all store example .fl files to pass floe check
Mar 16, 2026
421d818
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
d238393
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
bf62a1d
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
ed99c6d
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
44dc591
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
95f87dc
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
d775c5e
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
5ca313c
Fix qualified variant access in useState calls
Mar 17, 2026
aa9f191
Update todo-app posts.fl to use Http.get + parse<T>
Mar 17, 2026
31eb9cd
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
0b1d619
Merge remote-tracking branch 'origin/main' into feature/#230.store-ex…
Mar 17, 2026
6950c32
Merge main with destructure codegen fix and unqualify Filter variants
Mar 17, 2026
36688f8
Update site logos to match new snowflake design
Mar 17, 2026
04ddd31
Fix Result match codegen: use ok/error fields instead of tag
Mar 17, 2026
91ca5e4
Fix ? (unwrap) codegen: emit proper Result early return
Mar 17, 2026
6003595
Fix chained ? in pipe expressions to emit sequential Result unwrapping
Mar 17, 2026
4c40a50
Fix precedence: add parens around == before |> match in catalog
Mar 17, 2026
509525a
Remove as const from tuple codegen and fix category comparison parens
Mar 17, 2026
9bd9f5d
Fix ProductGrid and ProductDetail to unwrap Result directly
Mar 17, 2026
1c6445e
Fix Vite plugin to use file path for import resolution
Mar 17, 2026
5d04d35
Fix Array.reduce param order: callback first, initial second
Mar 17, 2026
2ee3d17
Access OrderId inner value in template literal
Mar 17, 2026
f15a54c
Suppress checker warnings in Vite plugin console
Mar 17, 2026
8d1d6df
Emit declare function stubs for imported Floe functions in tsgo probe
Mar 17, 2026
400fc35
Fix OrderId access: use nested destructuring instead of .value
Mar 17, 2026
00f80d6
Fix nested match codegen: use variant field names from variant_info
Mar 17, 2026
1d915ba
Fix scroll UX: independent sidebar and content scrolling
Mar 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 41 additions & 51 deletions docs/site/public/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 41 additions & 51 deletions docs/site/src/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions examples/store/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Floe Store</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
28 changes: 28 additions & 0 deletions examples/store/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "floe-store",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "floe check src/"
},
"dependencies": {
"@tanstack/react-query": "^5.90.21",
"@tanstack/react-router": "^1.166.8",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-error-boundary": "^6.1.1",
"zod": "^4.3.6"
},
"devDependencies": {
"@tailwindcss/vite": "^4.1.0",
"@types/react": "^19.1.0",
"@types/react-dom": "^19.1.0",
"tailwindcss": "^4.1.0",
"typescript": "^5.8.0",
"vite": "^6.0.0",
"vite-plugin-floe": "workspace:*"
}
}
109 changes: 109 additions & 0 deletions examples/store/src/api.fl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// ── API layer ──────────────────────────────────────────
// Uses Http namespace, parse<T> built-in, and collect for
// parallel fetching. No Zod — the compiler generates
// validators from the type definitions.

import { Product, ProductId, Review, ApiError } from "./types"

// ── Response types for parsing ─────────────────────────

type ProductDetailResponse = {
id: number,
title: string,
description: string,
category: string,
price: number,
discountPercentage: number,
rating: number,
stock: number,
tags: Array<string>,
brand: string,
thumbnail: string,
images: Array<string>,
reviews: Array<Review>,
}

type ProductListResponse = {
products: Array<Product>,
total: number,
}

export type CategoryResponse = {
slug: string,
name: string,
}

// ── Single product fetch ───────────────────────────────

export async fn fetchProduct(id: ProductId) -> Result<(Product, Array<Review>), ApiError> {
const data = await Http.get(`https://dummyjson.com/products/${id}`)?
|> Http.json?
|> parse<ProductDetailResponse>?

const product = Product(
id: ProductId(data.id),
title: data.title,
description: data.description,
category: data.category,
price: data.price,
discountPercentage: data.discountPercentage,
rating: data.rating,
stock: data.stock,
tags: data.tags,
brand: data.brand,
thumbnail: data.thumbnail,
images: data.images,
)

Ok((product, data.reviews))
}

// ── Product list with filters ──────────────────────────

export async fn fetchProducts(
category: string = "",
search: string = "",
limit: number = 20,
skip: number = 0,
) -> Result<(Array<Product>, number), ApiError> {
const url = (category, search)
|> match {
("", "") -> `https://dummyjson.com/products?limit=${limit}&skip=${skip}`,
(cat, "") when cat != "" -> `https://dummyjson.com/products/category/${cat}?limit=${limit}&skip=${skip}`,
(_, q) -> `https://dummyjson.com/products/search?q=${q}&limit=${limit}&skip=${skip}`,
}

const data = await Http.get(url)?
|> Http.json?
|> parse<ProductListResponse>?

Ok((data.products, data.total))
}

// ── Categories ─────────────────────────────────────────

// TODO: needs compiler fix - Array.map return type inference doesn't narrow through generics
export async fn fetchCategories() -> Result<Array<CategoryResponse>, ApiError> {
const data = await Http.get("https://dummyjson.com/products/categories")?
|> Http.json?
|> parse<Array<CategoryResponse>>?

Ok(data)
}

// ── Parallel dashboard fetch ───────────────────────────

export async fn fetchStoreDashboard(
category: string = "",
) -> Result<(Array<Product>, Array<CategoryResponse>), Array<ApiError>> {
collect {
const (products, _total) = await fetchProducts(category: category)?
const categories = await fetchCategories()?

(products, categories)
}
}

test "fetchProducts returns products" {
assert true
}
Loading
Loading