FiveAI Fusion language
SpaceFive · the official Five demo

One language.
One binary.
The whole web.

SpaceFive is a batteries-included web framework written in pure Five. HTTP, WebSocket, PostgreSQL, bcrypt, AES, i18n — all native runtime calls. No Node. No FFI. No ORM server. One static binary talking straight to Postgres, and three real apps running on it right now.

—
assets tracked
—
portfolio value
—
people on payroll
1
static binary
01 — LIVE DEMOS

Three apps, same framework,
same aesthetic.

Everything you click is served by a Five handler: hypermedia partial updates, server-rendered forms, CSV export, photo uploads, realtime events.

02 — FOR xBASE & HARBOUR DEVELOPERS

You already know this language.
Only the screen changed.

If you wrote Clipper, FoxPro or Harbour, a SpaceFive page reads like a dialog you have written a hundred times. Every example below is live: the widget on the right was rendered by the code on the left, for this very request.

A menu — MENU … ENDMENU
MENU hMenu MENUBAR
   MENUITEM "Assets"      ACTION "/assets"
   MENUITEM "People"      ACTION "/people"
   MENUITEM "+ New asset" ACTION "/assets/new" GOLD
ENDMENU
cHtml := MENU_HTML( hMenu )
rendered on this request

Exactly the FiveWin syntax. MENU_HTML() returns the markup; the skin decides what it looks like.

Stat cards — DASHBOARD … STAT
hStat := DB_ONE( cAssetStats, {} )

DASHBOARD hDash
   STAT "Total assets"   VALUE hStat[ "n" ] GOLD
   STAT "Total value"    VALUE Money( hStat[ "total" ], "USD" ) GOLD
   STAT "Active"         VALUE hStat[ "active" ] OK
   STAT "In maintenance" VALUE hStat[ "maint" ] WARN
ENDDASHBOARD
cHtml := DASH_HTML( hDash )
rendered on this request

One query, four STAT lines. GOLD, OK and WARN are the colours; the numbers are live from PostgreSQL.

Total assets
14
Total value
$66,745
Active
12
In maintenance
1
A browse — TABLE … COLUMN
aRows := DB_QUERY( cFirstEmployees, {} )

TABLE hList OF aRows LINK "/people/:id"
   COLUMN "name"       HEADER "Employee" THUMB "photo" SUB "emp_no"
   COLUMN "position"   HEADER "Position"
   COLUMN "status"     HEADER "Status" BADGE
   COLUMN "salary"     HEADER "Salary" MONEY CURRENCY "currency" RIGHT
ENDTABLE
cHtml := TABLE_HTML( hList )
rendered on this request

TBrowse for the web: one COLUMN per field. THUMB, BADGE, MONEY and RIGHT say how to show it; LINK makes every row clickable.

EmployeePositionStatusSalary
Photo cards — GALLERY … CARD
GALLERY hCards OF aRows LINK "/people/:id"
   CARD PHOTO "photo"  INITIALS "name"
   CARD BADGE "status"
   CARD TAG   "position"
   CARD TITLE "name"
   CARD META  "department"
   CARD VALUE "salary" CURRENCY "currency"
ENDGALLERY
cHtml := GALLERY_HTML( hCards )
rendered on this request

CARD maps a field to a role on the card: photo, badge, tag, title, meta, value. The card itself is one HTML file in the skin.

A GET form — FORM … GET … COMBO
FORM hForm ACTION "/people" OF hReq
   GET   "emp_no" LABEL "Employee no." VALUE "E-2001"
   GET   "name"   LABEL "Name"
   COMBO "status" LABEL "Status" VALUE "active" ITEMS aStatuses
   GET   "salary" LABEL "Salary (annual)" VALUE 90000
   BUTTON "Save" GOLD
   LINK   "Cancel" ACTION "/"
ENDFORM
cHtml := FORM_HTML( hForm )
rendered on this request

@ SAY … GET for the browser. The CSRF token travels with the form, and Save really creates an employee.

Cancel

From the DOS screen to the browser

You wroteYou write nowWhat it does
@ 10, 5 SAY "Name" GET cNameGET "name" LABEL "Name" VALUE cNameA labelled text field in a form.
MENU oMenu … MENUITEM … ENDMENUMENU hMenu MENUBAR … MENUITEM … ENDMENUHeader buttons, sidebar chips, tabs — one syntax.
TBrowse / dbEdit()TABLE hList OF aRows … COLUMN … ENDTABLEA clickable list with thumbnails, badges and money columns.
USE customers INDEX ON nameaRows := DB_QUERY( cSql, { cName } )PostgreSQL, parameter-bound, no ORM server.
SET COLOR TO W+/Bpublic/skins/<skin>/skin.cssThe look is a skin: CSS and small HTML templates a designer can edit.
ACTIVATE WINDOW oWndFV_SERVE( nPort, "public", {| hReq | APP_DISPATCH( hReq ) } )The whole web server, in one line of main.prg.
03 — UNDER THE HOOD

Native runtime, no glue.

Every layer is a Five runtime library call. There is nothing to install besides PostgreSQL.

FV_SERVE

HTTP, fully owned

Headers and cookies in, status and set-cookie out. Each request runs on its own VM thread.

WsServe · WsSend

Realtime

Zero-dependency WebSocket server. The feed on this page is listening to it.

PG_OPEN · PG_QUERY

PostgreSQL, direct

Parameter-bound queries over pgx. Idempotent migrations run at boot.

PWHASH · ENCRYPT · SECEQ

Secure by default

bcrypt passwords, AES-256-GCM sessions, constant-time compares, CSRF double-submit.

T()

i18n built in

Catalog-driven translations with a per-request locale. This page is served in six languages from locales/*.json.

hx.js

Hypermedia UI

A 54-line HTMX-style shim: partial swaps, CSRF headers, no build step, no framework.

04 — THE CODE

Request is a hash. Response is a hash.
Handler is a block.

This is the real route table and a real handler from the running app.

routes/routes.prg
// asset manager — gallery, list, detail, CRUD, export
ROUTE( "GET",  "/assets",            {| hReq | ASSET_DASHBOARD( hReq ) } )
ROUTE( "GET",  "/assets/cards",      {| hReq | ASSET_CARDS( hReq ) } )
ROUTE( "POST", "/assets",            {| hReq | ASSET_CREATE( hReq ) } )
ROUTE( "GET",  "/assets/export.csv", {| hReq | ASSET_EXPORT( hReq ) } )

// main.prg — the whole server
FV_SERVE( hCfg[ "port" ], "public", {| hReq | APP_DISPATCH( hReq ) } )

// a handler: query → hash → JSON. The result lives in a variable; RETURN returns it.
FUNCTION ASSET_LIST( hReq )
   LOCAL aRows := Rows( hReq, 1000, 0 )
   LOCAL hRes  := RES_JSON( { "ok" => .T., "assets" => aRows, "count" => Len( aRows ) } )

RETURN hRes
 wss · /wsconnecting
Realtime feed from RT_BROADCAST. Create a record in another tab and watch it land here: New asset · New employee