Trwth Dashboard Guide
Trwth is a local-first dashboard framework built in pure JavaScript and CSS. It emphasizes transparent formulas, offline capability, and keeping data on your machine by default.
What makes Trwth different?
- Local-first: works fully offline; no external CDNs or package managers are required.
- Formula-centric: dashboards are configured with a declarative appConfig and column formulas.
- Secure by default: avoids third-party scripts; optional encryption for persisted data.
Philosophy: every view should clearly show who it’s about (keys), what it measures (columns & formulas), and why the result is true (transparent config & totals).
Browser Support
- Chrome 90+
- Firefox 90+
- Safari 14+
- Edge 90+
Installation
Local Files (recommended)
Place the framework files into your project and include them directly—no internet required.
<!-- Include your local build(s) --> <link rel="stylesheet" href="../css/base.css"> <script src="../js/trwth.core.js"></script> <script src="../js/trwth.dashboard.js"></script>
Project Structure
/project
/css
base.css
/js
trwth.core.js
trwth.dashboard.js
/data
loans.csv
guide/index.html
Note: Avoid remote CDNs to ensure offline operation and minimize supply-chain risk.
Basic Usage
HTML
Add a container for the dashboard UI.
<div id="dashboard"></div>
Config + Mount
Trwth reads a declarative window.appConfig that defines columns, formulas, and filters.
<script>
// Minimal example
window.appConfig = {
description: "Branch performance overview",
table: [
{ heading: "Branch", id: "Branch_Number", column_type: "data", data_type: "integer", source: "loan" },
{ heading: "Principal", id: "Principal", column_type: "data", data_type: "currency", source: "loan" },
{ heading: "Loan Count", id: "loan_count", column_type: "formula", formula: "count", data_type: "integer", source: "loan" },
{ heading: "Avg Principal", id: "avg_principal", column_type: "formula", formula: "average", data_type: "currency", source: "loan", target_id: "Principal" }
],
primary_key: "Portfolio"
};
// Mount the dashboard
Trwth.Dashboard.mount("#dashboard", { appConfig: window.appConfig });
</script>
Formulas
Formulas compute per-group values after filters and translation are applied. Supported built-ins:
columns: [
{ heading: "Branch", id: "Branch_Number", column_type: "data", data_type: "integer", source: "loan" },
{ heading: "Principal", id: "Principal", column_type: "data", data_type: "currency", source: "loan" },
// COUNT (target_id optional)
{ heading: "Loan Count", id: "loan_count", column_type: "formula", formula: "count", data_type: "integer", source: "loan" },
// DISTINCT COUNT
{ heading: "Distinct Borrowers", id: "distinct_borrowers", column_type: "formula", formula: "distinct_count", data_type: "integer", source: "loan", target_id: "Borrower_ID" },
// AVERAGE / AVG
{ heading: "Avg Principal", id: "avg_principal", column_type: "formula", formula: "average", data_type: "currency", source: "loan", target_id: "Principal" },
// SUM
{ heading: "Total Principal", id: "sum_principal", column_type: "formula", formula: "sum", data_type: "currency", source: "loan", target_id: "Principal" },
// MIN / MAX (dates resolve to earliest/latest)
{ heading: "Earliest Open", id: "min_open", column_type: "formula", formula: "min", data_type: "date", source: "loan", target_id: "Open_Date" },
{ heading: "Largest Balance", id: "max_balance", column_type: "formula", formula: "max", data_type: "currency", source: "loan", target_id: "Average_Balance" },
// DISTINCT — joined by ", "
{ heading: "Product Types", id: "product_types", column_type: "formula", formula: "distinct", data_type: "string", source: "loan", target_id: "Product_Code" },
]
Formula Reference
| Formula | What it does | target_id |
Source | Example |
|---|---|---|---|---|
count |
Counts rows after filters | Optional | Optional | {formula:"count", id:"loan_count", source:"loan"} |
average / avg |
Mean of numeric field | Required | Optional | {formula:"avg", id:"avg_principal", source:"loan", target_id:"Principal"} |
sum |
Total of numeric field | Required | Optional | {formula:"sum", id:"sum_principal", source:"loan", target_id:"Principal"} |
min |
Minimum value (earliest date) | Required | Optional | {formula:"min", id:"min_open", data_type:"date", target_id:"Open_Date"} |
max |
Maximum value (latest date) | Required | Optional | {formula:"max", id:"max_balance", data_type:"currency", target_id:"Average_Balance"} |
distinct |
Unique values joined by “, ” | Required | Optional | {formula:"distinct", id:"product_types", target_id:"Product_Code"} |
distinct_count |
Count of unique values | Required | Optional | {formula:"distinct_count", id:"distinct_borrowers", target_id:"Borrower_ID"} |
Config Reference
Trwth uses a single appConfig object as the source of truth.
Top-level
| Key | Type | Description |
|---|---|---|
description | string | Markdown/HTML description for the page |
table | Array<Column> | Column definitions (data & formulas) |
primary_key | string | Unique identifier field (e.g., Portfolio) |
filters | object | Optional global filters |
Column
| Key | Type | Required | Description |
|---|---|---|---|
heading | string | Yes | Column header |
id | string | Yes | Field key |
column_type | "data" | "formula" | Yes | Data source column or computed |
data_type | string | Yes | e.g., integer, currency, date, string |
source | string | No | Source name (CSV/JSON alias) |
formula | string | When formula | One of the formula names above |
target_id | string | As needed | Target field for aggregation |
filter | string | No | Inline filter expression |
Data Sources
CSV (local)
Load CSV via file input (no network):
<input type="file" id="csvLoans" accept=".csv">
<script>
document.getElementById('csvLoans').addEventListener('change', e => {
Trwth.Dashboard.loadCsv('loan', e.target.files[0], { headers: true });
});
</script>
JSON (local)
<input type="file" id="jsonUsers" accept=".json">
<script>
document.getElementById('jsonUsers').addEventListener('change', async e => {
const file = e.target.files[0];
const text = await file.text();
const data = JSON.parse(text);
Trwth.Dashboard.updateData('users', data);
});
</script>
Security Note: All parsing happens locally in the browser; no data leaves your machine unless you explicitly export/sync.
Customization
Theme
Trwth.Dashboard.setTheme({
colors: {
primary: '#2E8BC0',
secondary: '#58C6B1'
},
fonts: {
primary: 'Inter, sans-serif',
monospace: 'Fira Code, monospace'
}
});
Custom CSS
.trwth-table th, .trwth-table td { padding: 8px 12px; }
.trwth-badge { border-radius: 8px; padding: 2px 8px; }
Security
Local-first defaults
Trwth avoids third-party scripts and external calls by default.
Optional Encryption
Trwth.Security.enable({
encryption: true,
algorithm: 'AES-256-GCM',
getKey: async () => myKeyBytes
});
Examples
Branch Performance
Demonstrates formula aggregation and filtering.
window.appConfig = {
description: "Branch performance (local CSV)",
primary_key: "Portfolio",
table: [
{ heading: "Portfolio", id: "Portfolio", column_type: "data", data_type: "unique", source: "loan" },
{ heading: "Principal", id: "Principal", column_type: "data", data_type: "currency", source: "loan" },
{ heading: "Loan Count", id: "loan_count", column_type: "formula", formula: "count", data_type: "integer", source: "loan" },
{ heading: "Avg Principal", id: "avg_principal", column_type: "formula", formula: "average", data_type: "currency", source: "loan", target_id: "Principal" },
{ heading: "Earliest Open", id: "min_open", column_type: "formula", formula: "min", data_type: "date", source: "loan", target_id: "Open_Date" }
]
};
Trwth.Dashboard.mount("#dashboard", { appConfig: window.appConfig });
Troubleshooting
Overflow or horizontal scrolling?
- Ensure your container uses the updated styles (min-width: 0 on grid children).
- Keep tables/code inside the provided .api-table / .code-block wrappers.
Data not appearing?
- Verify your source alias matches column.source.
- Confirm the primary_key is present in your data.