Skip to content

Quick Start

This guide walks you through creating a simple module in Fullfinity, showing what each file contains. (If you just want the structure generated for you, run fullfinity new library — see Developing Modules — then fill in the files below.)

Modules you build live under addons/.

Terminal window
mkdir -p addons/library/models
mkdir -p addons/library/views
mkdir -p addons/library/security
touch addons/library/__init__.py
touch addons/library/models/__init__.py

Create addons/library/manifest.json:

{
"name": "Library",
"identifier": "library",
"category": "module_category_services",
"description": "Manage books and authors",
"dependencies": ["core"],
"icon": "IconBook",
"color": "#4A90D9"
}

Create addons/library/models/author.py:

from fullfinity.engine.base import *
class Author(Model):
name = Char(max_length=255, required=True, description="Author Name")
email = Char(max_length=255, description="Email")
bio = Text(description="Biography")
active = Boolean(default=True)

Create addons/library/models/book.py:

from fullfinity.engine.base import *
class Book(Model):
name = Char(max_length=255, required=True, description="Book Title")
isbn = Char(max_length=20, index=True, description="ISBN")
author = ManyToOne("Author", related_name="books", description="Author")
published_date = Date(description="Publication Date")
price = Monetary(default=0.0, description="Price")
status = Selection(
choices=["Available", "Borrowed", "Reserved"],
default="Available",
description="Status"
)

Register both model files in addons/library/models/__init__.py — a model file is only imported (and its model registered) if it is listed here:

from . import author
from . import book

Create addons/library/views/author_views.json:

[
{
"data_type": "UiView",
"name": "author_list_view",
"identifier": "author_list_view",
"type": "List",
"model": "Author",
"arch": [
{
"content": [
{"type": "field", "name": "name", "properties": {"widget": "Text"}},
{"type": "field", "name": "email", "properties": {"widget": "Text"}},
{"type": "field", "name": "active", "properties": {"widget": "Badge"}}
]
}
]
},
{
"data_type": "UiView",
"name": "author_form_view",
"identifier": "author_form_view",
"type": "Form",
"model": "Author",
"arch": [
{
"type": "row",
"content": [
{
"type": "column",
"span": 6,
"content": [
{"type": "field", "name": "name", "properties": {"widget": "TextInput", "size": "lg"}},
{"type": "field", "name": "email", "properties": {"widget": "TextInput"}}
]
},
{
"type": "column",
"span": 6,
"content": [
{"type": "field", "name": "active", "properties": {"widget": "Switch"}}
]
}
]
},
{
"type": "row",
"content": [
{
"type": "column",
"span": 12,
"content": [
{"type": "field", "name": "bio", "properties": {"widget": "RichTextEditor"}}
]
}
]
}
]
}
]

Create addons/library/views/book_views.json:

[
{
"data_type": "UiView",
"name": "book_list_view",
"identifier": "book_list_view",
"type": "List",
"model": "Book",
"arch": [
{
"content": [
{"type": "field", "name": "name", "properties": {"widget": "Text"}},
{"type": "field", "name": "author", "properties": {"widget": "Text"}},
{"type": "field", "name": "isbn", "properties": {"widget": "Text"}},
{"type": "field", "name": "status", "properties": {"widget": "Badge", "colors": {"Available": "green", "Borrowed": "orange", "Reserved": "blue"}}}
]
}
]
},
{
"data_type": "UiView",
"name": "book_form_view",
"identifier": "book_form_view",
"type": "Form",
"model": "Book",
"arch": [
{
"type": "statusbar",
"name": "status",
"properties": {
"widget": "Badge",
"variant": "dot",
"colors": {"Available": "green", "Borrowed": "orange", "Reserved": "blue"}
}
},
{
"type": "row",
"content": [
{
"type": "column",
"span": 6,
"content": [
{"type": "field", "name": "name", "properties": {"widget": "TextInput", "size": "lg"}},
{"type": "field", "name": "author", "properties": {"widget": "DataCombo"}},
{"type": "field", "name": "isbn", "properties": {"widget": "TextInput"}}
]
},
{
"type": "column",
"span": 6,
"content": [
{"type": "field", "name": "published_date", "properties": {"widget": "DatePickerInput"}},
{"type": "field", "name": "price", "properties": {"widget": "NumberInput"}}
]
}
]
}
]
}
]

Create addons/library/views/actions.json:

[
{
"data_type": "WindowAction",
"name": "Authors",
"identifier": "authors_action",
"model": "Author",
"modes": "List,Form",
"views": ["author_list_view", "author_form_view"]
},
{
"data_type": "WindowAction",
"name": "Books",
"identifier": "books_action",
"model": "Book",
"modes": "List,Form",
"views": ["book_list_view", "book_form_view"]
}
]

Create addons/library/views/menus.json:

[
{
"data_type": "UiMenu",
"name": "Library",
"identifier": "library_menu",
"sequence": 20,
"icon": "IconBook"
},
{
"data_type": "UiMenu",
"name": "Authors",
"identifier": "authors_menu",
"parent": "library_menu",
"action": "authors_action",
"sequence": 10
},
{
"data_type": "UiMenu",
"name": "Books",
"identifier": "books_menu",
"parent": "library_menu",
"action": "books_action",
"sequence": 20
}
]

Create addons/library/security/security.json:

[
{
"data_type": "Group",
"name": "Librarian",
"identifier": "library_librarian",
"category": "Library"
},
{
"data_type": "ModelAccess",
"name": "Author Access",
"identifier": "author_access",
"model": "Author",
"read_perm": true,
"write_perm": true,
"create_perm": true,
"delete_perm": true,
"group": "library_librarian"
},
{
"data_type": "ModelAccess",
"name": "Book Access",
"identifier": "book_access",
"model": "Book",
"read_perm": true,
"write_perm": true,
"create_perm": true,
"delete_perm": true,
"group": "library_librarian"
}
]

From the CLI:

Terminal window
docker compose exec fullfinity fullfinity -db dev --init library

Or from the UI: go to Settings → Modules, find “Library”, and click Install (restart the server first if it was already running).

After installation:

  • A “Library” menu appears in the sidebar
  • You can create Authors and Books
  • The records are available through the generic data API, keyed by model name — e.g. POST /api/query/Author and POST /api/query/Book to list records, POST /api/create/Book to create one. See the API Overview for the full endpoint set.