Welcome to FI.js Documentation
FI.js is a lightweight Local-First JavaScript framework designed to simplify the creation of data-driven single-page applications (SPAs). It empowers both programmers and non-programmers to build efficient, secure, and dynamic applications with ease. By engaging AI and focusing on transparency, extensibility, and connectedness, FI.js allows industries like banking, healthcare, insurance, and government (we call them Institutions .e.g. public and private) to transition from complex legacy systems to more agile development environments.
The problem we solve is that when an institutions' data is stored in the cloud, the institutions become “borrowers” of their own data. FI.js adopted a local-first approach to provide institutions to take back control of their data. In the context of serving heavily regulated industries, FI.js adapts a local-first approach to solve several critical problems related to data privacy, security, reliability, and operational efficiency. Here's a detailed breakdown:
- Data Privacy and Regulatory Compliance
- Problem: Institutions operate in highly regulated environments where customer data must remain secure and often cannot leave the institution's private network. Sending sensitive data to the cloud can violate compliance regulations, such as GLBA (for banking), HIPAA (for healthcare), or state-level financial data protection laws.
- FI.js Local-First Solution:
- Data is processed and stored on local devices within the institution’s secure infrastructure, ensuring compliance with strict regulations.
- Data Security and Risk Mitigation
- Problem: Institutions face significant risks from cyberattacks, ransomware, and unauthorized access when relying on centralized cloud-based systems.
- FI.js Local-First Solution:
- Storing and processing data locally reduces attack surfaces by eliminating the need for continuous cloud interaction.
- Local-first systems manage state locally, decentralizing the data and reducing the incentive for large-scale breaches.
- Protects against accidental leaks or vulnerabilities introduced by third-party integrations.
- Disaster Recovery and Business Continuity
- Problem: Relying on centralized systems can make institutions vulnerable to catastrophic failures or data loss during outages or cyberattacks.
- FI.js Local-First Solution:
- Local-first architecture ensures critical operations continue to function locally even if legacy systems and the Internet are unavailable.
- Institutions have control over their data under the local-first architecture--knowing where FI.js data sources are located, how data is accessed, and how data is preserved.
- Extensibility and Transparency
- Problem: software systems issues arises from the tension between growing complexity, user control, and both the need predictable results and the ability to create solutions to business problems without or limited use of developers.
- FI.js Local-First Solution:
- FI.js uses accessible and open data formats (e.g., JSON, JavaScript) stored locally, making it easier for developers and non developers to build new apps, libraries, and features.
- FI.js rejects black-box behaviors, giving users full insight into operations and data flow.
Quick Start
This Quick Start guide will walk you through setting up FI.js and building & running a simple application. FI.js includes single page applications that work right out of the box--no learning curve to begin using FI.js. You'll learn how to:
- Download and set up the FI.js framework.
- Run the application using test data.
- Understand how the framework works at a high level through this example.
- Review a basic FI.js application using a sample
appConfig
.
Step 1: Download the FI.js Framework
- Visit the FI.js GitHub Repository
- Open your web browser and navigate to the FI.js GitHub repository.
- Download the Repository
- Click the green "Code" button located near the top right corner.
- Select "Download ZIP" from the dropdown menu.
- Save the ZIP file to a directory of your choice on your computer.
Step 2: Extract and Set Up the Framework
- Extract the ZIP File
- Navigate to the directory where you saved the ZIP file.
- Right-click the ZIP file and select "Extract All..." or use your preferred extraction tool.
- Choose a destination folder for the extracted files.
Step 3: Prepare the Sample Data
- Obtain the Test Data File
- Ensure you have a test data file named
random_generated_loan_data.csv
in the/data
directory. This CSV file should contain randomly generated loan data that theQuiskstart
application will use. - If you don't have this file, create a simple CSV with headers like
Portfolio
,Branch
,Principal
,OpenDate
, etc., and add some sample data. - Your directory structure should look like this:
/FI.js-main /apps /demos Quickstart.html ... /profitability loanProfit.html ... /core /data random_generated_loan_data.csv /libraries ...
You can leave random_generated_loan_data.csv
in \data
or you can copy it to another secure local folder. Note: All data processing and storage occur locally on the user’s machine, minimizing the risk of data breaches. By keeping data within the local environment, FI.js prevents unauthorized access and interception that can occur during data transmission over networks.
Step 4: Open the Application in a Browser
- Open the Quickstart Application
- Double-click
Quickstart.html
to open it in your default web browser. - Find and open the
Quickstart.html
file. - Alternatively, right-click the file, select "Open with", and choose your preferred browser.
Step 5: Interact with the Application
- The application should load, provide a button to select
loan
source where you selectrandom_generated_loan_data.csv
, and clickRun Quckstart- using a date range
button. You should see a table or presentation of data showing theBranch
andOfficer
for loans that meet the criteria specified in your formula.
Result | |||
---|---|---|---|
200106555 (2) | 23 | 92 | $1,212,609.43 |
200102722 (1) | 23 | 92 | $313,590.84 |
Step 6: Review the App Configuration
- In
Quickstart.html
, locate the<script>
section whereappConfig
is defined. Here's the code for reference: - Explanation of the No-code configuration:
- description (optional): App Authors can describe their app to make it easier to understand and share.
- libraries: Specifies the APIs and libraries the app uses. Libraries are collections of central dependencies: functions, attributes, and dictionaries--which are assembled for specific functionalities and help maintain code organization and reusability. In this example, the
averageBalance
function in thefinancial
library is used to calculate the average principal balance. Note: Functions, attributes, and dictionaries are defined later in this guide. - Purpose: Group related components for modular application development.
- Definition: Created for particular sets of functionality, such as financial calculations or organizational data.
- formula: Act as the kernel of the FI.js framework, coordinating the interaction between raw data, libriaries, advanced operations, and outputs. This formula checks if each loan in data source is opened between October 31, 2020, and November 3, 2024. If true, it returns the average loan principal; otherwise, the loan is ignored from the final results.
- groupBy: Formula results are grouped and aggregated by field specified by groupBy. In this example, results are grouped by the
portfolio
field. For example, results of all instances of a particularportfolio
will be combined. - presentation: Defines the presentation layer of FI.js apps. If you define columns, FI.js will create a table to display formula results. If you define form fields (e.g. input) FI.js will render the results in a form. Quickstart configures two columns to display app results, showing
Branch
and LoanOfficer
.
Core Concepts
FI.js emphasizes clarity, transparency, and iterative development. It streamlines the creation of Single-Page Applications (SPAs) and encourages the fusion of human reasoning with AI-driven insights, leading to faster, more informed decision-making. Understanding the core components of FI.js is essential for building robust and efficient applications. These components work together to handle data processing, logic execution, and presentation within your single-page applications (SPAs).
- Formulas
- Purpose: Perform dynamic calculations and data filtering.
- Syntax: FI.js formulas use a combination of arithmetic operations, conditional operators, and truth propagation.
- Variables in FI.js formulas represent data fields or properties derived from your data sources. They allow formulas to perform operations based on the values of these fields. Here's a breakdown of how to define and use these variables:
- source (object identifier): The name of the data source (e.g.,
loan
). - field (property): The specific data attribute within the source (e.g.,
open
). - Functions
- Purpose: Encapsulate complex logic and operations.
- Definition: Defined within libraries to ensure consistency and reusability.
- Attributes
- Purpose: Store static values or configurations.
- Definition: Defined within libraries for organized access.
- Dictionaries
- Purpose: Handle predefined sets of values, such as interest rates or loan classifications.
- Definition: Organized within libraries for consistent access across the application.
- Libraries
- Purpose: Group related components for modular application development.
- Definition: Created for particular sets of functionality, such as financial calculations or organizational data.
- Process: loading libraries in apps (SPAs) features:
- Support for Local and Remote Libraries:
- Local libraries are JavaScript files stored within the project directory.
- Remote libraries are APIs fetched over HTTP/HTTPS
- Offline-First Design:
- Remote API responses are cached in IndexedDB. This is an intentionally simple and easy to understand approach.
- If offline, the application retrieves data from the IndexedDB cache.
- If data exists in the cache and is less than 24 hours old, it is used instead of making a network request.
Formulas are the heart of FI.js, defining and evaluating the logic of applications and data transformations using a human-readable syntax.
Understanding Variables in Formulas
1. Data Sources and Fields
Variables such as loan.open
are structured as source.field, where:
To define these variables, ensure that your data sources are correctly configured in your single page application and that each source contains the necessary fields.
Example Formula:
This formula checks if the loan's open date is between October 31, 2020, and November 3, 2024. If true, it returns the loan principal; otherwise, it returns null
.
Functions in Fi.js are reusable JavaScript functions used for calculations or data manipulation within your application.
Example Function:
This function calculates the monthly loan payment based on the principal amount, annual interest rate, and the number of amortization months.
Attributes are constants or fixed values used throughout the application. They provide essential data points that can be referenced in formulas and functions.
Example Attribute:
This attribute defines a servicing factor used in calculating loan servicing expenses.
Dictionaries are key-value pairs used for data lookups and mappings. They allow for flexible data retrieval and manipulation based on predefined keys.
Example Dictionary:
This dictionary maps various loan types to their respective identifiers, facilitating easy lookups within formulas and functions.
Libraries are collections of functions, attributes, and dictionaries organized for specific functionalities. They enable modular development, maintain code organization, and enhance reusability. Expreienced developers can create their own libraries following the libary
schema.
Example Library Structure:
Data Flow
Data in FI.js is handled through a unidirectional data flow, ensuring consistency, predictability, and easy debugging. State management is centralized, making it simple to understand and manipulate.
Data Handling
FI.js data handling approach is simple yet robust. You can connect to various data sources—APIs, databases, or in-memory structures—and transform them into meaningful, reactive components.
Statistics
The following statistics are available to Fi.js libraries
- min: The smallest value in the dataset.
- max: The largest value in the dataset.
- mean: The average value of the dataset, calculated by summing all values and dividing by the count of values.
- median: The middle value of the dataset when sorted in ascending order. If the count of values is even, the median is the average of the two middle values.
- areaMode: The most frequent value in the dataset after grouping values into ranges determined by a rounding factor. This focuses on the notion of clusters or areas.
- The area_mode function calculates the mode (the most frequently occurring value) of a dataset after grouping the values into ranges (or "areas") determined by a rounding factor. The rounding factor is dynamically derived from the minimum non-zero value in the dataset, ensuring that the grouping reflects the scale of the data.
- This method is particularly useful for analyzing datasets with high variability or continuous values, where determining the exact mode requires logical grouping based on proximity.
- nonzeroMin: The smallest non-zero value in the dataset.
- variance: A measure of the spread of the dataset, calculated as the average of the squared differences from the mean.
- stdDeviation: The standard deviation of the dataset, representing the square root of the variance. It measures the average distance of values from the mean.
- twoStdDeviations: Two standard deviations from the mean, often used to identify a range where approximately 95% of the data lies in a normal distribution.
- threeStdDeviations: Three standard deviations from the mean, often used to identify a range where approximately 99.7% of the data lies in a normal distribution.
- sum: The total of all values in the dataset.
- count: The number of values in the dataset.
- unique: The count of unique values in the dataset, ignoring duplicates.
- YTDfactor: The yearToDateFactor function determines a scaling factor for a given field name based on its associated time period. The factor is used to adjust calculations to a year-to-date basis.
- 12 if the field name suggests monthly data (e.g., contains "MTD").
- 365 if the field name suggests daily data (e.g., contains "day" or "daily").
- 1 as the default, assuming yearly data if no specific time period is detected.
- convexProbability: The Convex Probability Array represents a weighted or interpolated probability distribution created for the unique values in the dataset.
AI Integration
FI.js integrates seamlessly with AI models, helping to auto-generate UI elements, recommend code patterns, or assist with complex logic. This synergy between human and AI input opens new frontiers in rapid development and innovation.
Security & Transparency
FI.js is Local-first, a design and architectural principle in software development that prioritizes running applications and storing & connecting data sources locally on a user's device rather than relying solely on cloud-based services. Local-first and FI.js is about ownership and empowerment; we focus on providing offline-first functionality, tranparency, control, better privacy, and faster performance by emphasizing the local environment. Here's a detailed breakdown:
-
Offline-First Functionality:
- Applications should work seamlessly without an internet connection. Data is stored and processed locally, and unlike typical Local-first designs, FI.js does not synchronize with remote services.
- Benefit: Offline functionality ensures uninterrupted usage.
-
Data Privacy and Ownership:
- Data resides on the user's device and inside the organization's security edge, giving them more control and eliminating the reliance on external servers. This ensures better privacy and security.
- Users have complete control as they know exactly where their data is stored—on their local device—giving them full ownership.
- No Hidden Transfers are permitted, since data is processed locally, there are no opaque processes transferring or storing it on remote servers without user knowledge.
- Benefit: Sensitive data stays local and is less vulnerable to breaches, and no more worries about your vendor staying in business to support your platform.
-
Portability and Transparency:
- Users can use the application independently of any central service, which reduces vendor lock-in.
- Local-first design inherently improves transparency, offering users clear insight and control over how their data is used and stored.
- Benefit: Reduces reliance on expensive cloud infrastructure and enforces 100% transparency.
-
State Management:
- The current state is limited to the local machine, local Javascript runtime code, loaded DOM, defined data sources, and preloaded APIs. Nothing is distributed to the 'cloud' e.g. eliminates the dance between front-end and back-end code. And no seven figure AWS bills.
- FI.js defines inputs and outputs, so the current state is well-managed, each change is predictable, enabling AI to operate on reliable data.
- Benefit: Maintaining a clear and authoritative snapshot of all relevant data and functions—offers significant advantages, particularly when integrating AI.
Formulas
Formulas
In the FI.js framework, formulas serve as the core mechanism that connects data with functions, enabling powerful interactions. They allow users to perform dynamic calculations across multiple data sources, execute complex financial and analytical operations, and deliver results to defined outputs—all within a consistent, no-code, no-SQL, and human-readable syntax. Before diving deeper, let’s explore the syntax that makes it all possible.
In FI.js, formulas act as the kernel of the framework, coordinating the interaction between raw data, advanced operations, and outputs. As the foundation of the system, formulas provide:
- Central Coordination: Directing how data flows and is processed from sources to outputs.
- Simplified Abstraction: Translating simple syntax into complex computations.
- Dynamic Adaptability: Adjusting to various operations, from simple functions to AI-powered insights.
- Empowered Accessibility: Allowing users of all technical levels to harness powerful data interactions without needing code or SQL.
Formulas act as the Kernel
Secure Environment
Data Files
Form Content
Data Streams
Functions
Advanced Operations
AI
API Calls
Results in Browser
Secure Environment
loan.csv
Profit
Function
! {{ }} - == *
Operations
AI
Treasury API
Results in Browser
Understanding Variables in Formulas
Variables in FI.js formulas represent data fields or properties derived from your data sources. They allow formulas to perform operations based on the values of these fields. Here's a breakdown of how to define and use these variables:
1. Data Sources and Fields
Variables such as loan.open
are structured as source.field, where:
- source: The name of the data source (e.g.,
loan
). - field: The specific data attribute within the source (e.g.,
open
).
To define these variables, ensure that your data sources are correctly configured in your single page application and that each source contains the necessary fields.
When working with formulas in FI.js, it's crucial to understand how to reference your data sources. For detailed instructions on importing and setting up your data, refer to the Setting Up Data Sources section.
2. Metric Properties: Units and Tally
In your formula, variables like units
and tally
are built-in metric properties used by FI.js.
Defining Units
Units represent the total number of instances of the groupBy
field that have been combined or aggregated.
Defining Tally
Tally counts the number of instances within each groupBy
field that have a valid result according to the formula.
3. Defining Variables in Formulas
FI.js intuitively connects the data sources required by the formula based on the variable names in formula, for instance
groupBy: 'Portfolio',
...
tally
: pulls the count of valid instances per portfolio.units
: pulls the total number of portfolios.loan.class
,loan.open
: Fields from theloan
data source.loan.principal
: The principal amount from theloan
data source.
FI.js Supported Formula Syntax
Arithmetic Operations (JavaScript)
- Addition (+)
- Subtraction (-)
- Multiplication (*)
- Division (/)
- Modulus (%)
- Exponentiation (**)
- Increment (++)
- Decrement (--)
Logical NOT
The ! operator is known as the logical NOT operator. It's used to invert the boolean value of an operand. Here’s a quick rundown of how it works: Logical NOT (!): If the operand is true, the result is false, and if the operand is false, the result is true.
Conditional (Ternary) Operators (JavaScript)
Operators that take three operands— a condition followed by a question mark ?, then an expression to execute if the condition is truthy, followed by a colon :, and finally the expression to execute if the condition is falsy. Conditional expressions allow for decision-making:
Format:Note the condition uses >
in this code. The >
comparison in our framework and most porgamming environments is an evaluation of two values to determine their relationship. This can involve checking if they are equal, not equal, greater than, less than, greater than or equal to, or less than or equal to each other. Here are the main types of comparison operators:
==
: Equal to - checks if two values are equal.- Example:
5 == '5'
(true)
- Example:
===
: Strict equal to - checks if two values are equal and of the same type.- Example:
5 === 5
(true),5 === '5'
(false)
- Example:
!=
: Not equal to - checks if two values are not equal.- Example:
5 != '5'
(false)
- Example:
!==
: Strict not equal to - checks if two values are not equal and not of the same type.- Example:
5 !== '5'
(true)
- Example:
>
: Greater than - checks if the left value is greater than the right value.- Example:
10 > 5
(true)
- Example:
<
: Less than - checks if the left value is less than the right value.- Example:
5 < 10
(true)
- Example:
>=
: Greater than or equal to - checks if the left value is greater than or equal to the right value.- Example:
5 >= 5
(true)
- Example:
<=
: Less than or equal to - checks if the left value is less than or equal to the right value.- Example:
5 <= 10
(true)
- Example:
In this example, if the checking account has been open for less than 90 days (checking.daysSinceOpen < 90
) include the checking account balance in the result (? checking.balance
) else include nothing for this account in the final result (: null
)
Comparison Operators:
==
: Equal to - checks if two values are equal.===
: Strict equal to - checks if two values are equal and of the same type.!=
: Not equal to - checks if two values are not equal.!==
: Strict not equal to - checks if two values are not equal and not of the same type.>
: Greater than - checks if the left value is greater than the right value.<
: Less than - checks if the left value is less than the right value.>=
: Greater than or equal to - checks if the left value is greater than or equal to the right value.<=
: Less than or equal to - checks if the left value is less than or equal to the right value.
Array Membership (Set Inclusion) Operator
The 'in' operator enables set inclusion testing, allowing you to check if a value belongs to a predefined set:
Format:- Purpose: Useful for filtering conditions based on membership in specified groups or classifications.
- Purpose: Useful for filtering conditions where operand is NOT a member of a specified group or classification.
Date Handling in Formulas
Formulas can process date conditions by calculating day differences:
Format:- Internally, dates are converted to the number of days since the specified date.
- Purpose: Enables easy comparison of dates to implement date-based filtering or time-based calculations.
Truth Propagation with Conditional Locks
Truth propagation allows certain conditions to “lock” all other conditions within the formula to true once any one condition evaluates as true. Use double curly braces {{ }}
to define such locks:
- Purpose: Useful for creating conditions that apply to all formulas within the same groupBy field once true. In this case, If 1 loan is high risk, then by extension the borrower is high risk, thus all loans ought to have the high risk factor applied else no factor will be applied.
Properties in FI.js
In FI.js, Properties are essential elements that define how data is managed, processed, and presented within your single-page applications (SPAs). Properties are categorized into two primary types:
- Presentation Properties
- Metrics Properties (Units and Tally)
Understanding these categories and their roles will enable you to effectively configure and visualize your data-driven applications.
1. Presentation Properties
Presentation Properties dictate how data is displayed to the end-user. They are primarily used within the presentation
section of the appConfig
to define the structure and content of the data presentation layers, such as tables or charts.
Structure
Components
- heading: The display name of the column as it appears in the user interface.
- field: The key or path to the data attribute that populates the column. It can reference nested fields using dot notation (e.g.,
customer.gender
).
Example
In this example:
- The application will display two columns: Branch and Principal.
- Each column corresponds to the
branch
andprincipal
fields in the data source.
2. Properties
Metrics Properties provide quantitative insights into the data by tracking and summarizing specific aspects. In FI.js, the primary metrics properties are units
and tally
.
2.1 Units
Units represent the total number of instances of a particular groupBy
field that have been combined or aggregated within the application.
Purpose
- Aggregation: Helps in understanding the scale or volume of data grouped by a specific category.
- Contextualization: Provides context to the presented data by indicating how many records contribute to each group.
Example
metrics: {
units: 'Portfolio',
},
};
In this example:
- Units are grouped by the
Portfolio
field. - If there are 5 portfolios,
units
will represent these 5 groups.
2.2 Tally
Tally counts the number of instances within each groupBy
field that have a valid result according to the specified formula
.
Purpose
- Validation: Indicates how many records within each group meet the criteria defined in the
formula
. - Quality Control: Helps assess the completeness or accuracy of the data being presented.
Example
metrics: {
units: 'Portfolio',
tally: 'Portfolio',
},
};
In this example:
- Tally counts how many loans within each
Portfolio
have anopen
date between October 31, 2020, and November 3, 2024. - If a portfolio has 10 loans and 7 meet the criteria, the tally for that portfolio is 7.
Logic Behind Units and Tally
- Units:
- Definition: Total instances of the
groupBy
field. - Calculation: Counts all unique groups based on the
groupBy
field. - Use Case: Provides a high-level overview of how data is distributed across different groups.
- Definition: Total instances of the
- Tally:
- Definition: Instances within each group that have valid results as per the
formula
. - Calculation: For each group defined by
groupBy
, counts the number of records that satisfy theformula
. - Use Case: Measures the effectiveness or relevance of data within each group, highlighting areas that meet specific criteria.
- Definition: Instances within each group that have valid results as per the
Combined Use Case
When used together, Units and Tally offer a comprehensive view of your data:
- Units show the scope of your data across different groups.
- Tally reveals the subset of data within those groups that meet specific conditions.
Example Scenario:
- Units: Number of portfolios.
- Tally: Number of loans within each portfolio that are active (based on the
formula
).
This combination allows stakeholders to quickly assess both the distribution and the quality of the data.
Visual Representation
To better understand how Properties function within FI.js, consider the following diagram:
/FI.js-main /apps /data test_loan_data.csv /libraries /core /styles ...
The diagram illustrates the hierarchical structure of FI.js application, highlighting where different components like presentation
, units
, and tally
fit within the overall framework.
Summary
- Properties in FI.js are essential for configuring how data is displayed and analyzed within your applications.
- Presentation Properties focus on the structure and content of the user interface.
- Metrics Properties (
units
andtally
) offer valuable insights into the data's distribution and the effectiveness of your data processing logic.
By effectively utilizing both types of Properties, you can create robust, insightful, and user-friendly applications with FI.js.
Cases
The primary measure of an innovation's usefulness is utility and usefulness. We have included practical banking industry applications. Keep in mind that the FI.js framework is flexible.
- Performing Risk Assessments
- The first step is to find and launch the risk application from the
apps/risk/
folder. Let's start withcommercialCheckingRisk
provided in the distribution - Click on
Configuration
(note that the "Arrow" – which looks like an arrow pointing down informs users that more content can be viewed inside the app's "Configuration." If the "arrow" is pointing upward, users can collapse the current view by clicking on the arrow or the associated heading) - Next, click on
description
. Notice that you can view the description that was created by the app designer. - {in process}
FAQ
Q: Do I need extensive JavaScript knowledge?
A: Not necessarily. FI.js has been designed to be useful out of the box and lower the barrier to entry. Even those with limited coding experience can build powerful applications.
Q: How does FI.js handle legacy system integration?
A: FI.js is designed to bridge traditional industries and modern web development. Its extensibility allows you to connect to legacy systems, gradually replacing complexity with clarity.
Q: My formula is not returning any results?
A: Make sure your conditional (Ternary) operators include three operands— a condition followed by a question mark ?, then an expression to execute if the condition is truthy, followed by a colon :, and finally the expression to execute if the condition is falsy.