a3t is a universal, context-aware asset loader for JavaScript and TypeScript applications. It allows you to retrieve any overrideable resource—prompts, configuration, i18n strings, templates, JSON, XML, or binary assets—using a filename-friendly key. a3t supports hierarchical lookups (database overrides, filesystem, then inline defaults), caching, and context sensitivity (language, workspace, build hash, etc.), all with a focus on developer experience.
Modern applications frequently need to override configuration, language strings, prompts, or entire assets:
- Rapid prototyping: Developers want to hardcode defaults for speed, then override without redeploying.
- Customization: Organizations want to tweak behavior, branding, or messaging per workspace, language, or deployment.
- Internationalization: Seamless i18n often means overrides at various levels and contexts.
- Live updates: Some asset changes (e.g., prompts, templates) should be live-editable by admins or scripts, not just by shipping code.
- Fast: Forever-cache with explicit, instant invalidation.
- Unified API: Retrieve any asset with
a3t.get(key, [defaultValue])(ora3t.__(key, [defaultValue])for the i18 devs). - Filename-friendly keys: Map directly to file paths, e.g.,
prompts/summary.txt. - Database overrides: Live, context-sensitive customization (via MongoDB or pluggable backend).
- Filesystem fallback: Loads assets from disk if not overridden.
- Inline defaults: Rapid prototyping with a default value, optional.
- Context-aware: Supports language, workspace, system, buildHash, nonce, and more.
- Forever-cached with nonce: Cache resolved assets until the nonce changes for instant global invalidation.
- Framework-agnostic: Works in Meteor (server-side), Fastify, Express, and other Node.js frameworks.
npm install a3tFor Deno:
import a3t from "https://deno.land/x/a3t/deno.ts";const a3t = require('a3t');
// Initialize with filesystem backend
a3t.init({
fs: { rootPath: './assets' },
context: { language: 'en', workspace: 'default' }
});
// Get assets
const prompt = await a3t.get('prompts/summary.txt', 'Default summary prompt');
const config = await a3t.get('config/app.json', '{}');
const i18n = await a3t.__('i18n/welcome.txt', 'Welcome!');
// With context override
const spanishWelcome = await a3t.get('i18n/welcome.txt', 'Bienvenido!', { language: 'es' });
// Multiple assets
const assets = await a3t.getMultiple(['config/app.json', 'prompts/summary.txt']);- Meteor (server-side): Uses Meteor's
AssetsAPI to load shipped assets. - Fastify/Express/Other Node.js: Uses
fs/fs/promisesto read files from the filesystem. - Pluggable DB: Default implementation uses MongoDB, but you can provide your own backend.
When you call a3t.get(key, [defaultValue]), a3t resolves the key using the following steps:
- Database overrides (most to least specific):
- workspace + language + key
- workspace + key
- language + key
- system + key
- key (global)
- Filesystem asset: Loads from disk using the key as the path (e.g.,
private/prompts/summary.txt). - Inline default: Uses the provided default value (if any).
- Not found: Returns
undefined.
Cache: The resolved value is cached forever for the current context (including
nonce) including misses from the DB. To invalidate the cache and force all clients to reload assets, increment thenonce.
assets/
i18n/
en.json
es.json
prompts/
summary.txt
templates/
note.xml
images/
logo.png
a3t includes comprehensive logging using pino for performance-critical tracing. You can configure logging or disable it completely for production:
// Enable logging with default settings
a3t.init({
fs: { rootPath: './assets' },
logging: { enabled: true }
});
// Configure pino logger options
a3t.init({
fs: { rootPath: './assets' },
logging: {
enabled: true,
pino: {
level: 'info',
transport: {
target: 'pino-pretty',
options: { colorize: true }
}
}
}
});
// Disable logging completely for production
a3t.init({
fs: { rootPath: './assets' },
logging: { enabled: false }
});a3t provides full Deno compatibility with TypeScript support:
import a3t from "https://deno.land/x/a3t/deno.ts";
// Filesystem backend
a3t.init({
fs: { rootPath: './assets' },
context: { language: 'en' }
});
// HTTP backend for remote assets
a3t.init({
fs: { httpBaseUrl: 'https://example.com/assets/' }
});
const asset = await a3t.get('prompts/summary.txt', 'Default');You can call setA3tContext() per request or session to provide user-specific or tenant-specific context.
// Express middleware example
app.use((req, res, next) => {
a3t.setContext({
language: req.headers['accept-language']?.split(',')[0] || 'en',
workspace: req.user?.workspace || 'default'
});
next();
});const { MongoClient } = require('mongodb');
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
a3t.init({
db: {
mongodb: {
client: client,
database: 'myapp',
collection: 'assets'
}
}
});After updating an override in the database, increment the nonce to make all clients re-resolve assets.
// After updating database overrides
a3t.incrementNonce();You can customize database and filesystem logic by providing custom backends:
// Custom database backend
a3t.setDbBackend({
async findAsset(query) {
// Your custom database logic
return value || null;
}
});
// Custom filesystem backend
a3t.setFsBackend({
async readAsset(key) {
// Your custom filesystem logic
return content || null;
},
async readBinaryAsset(key) {
// Your custom binary file logic
return buffer || null;
}
});| Feature | i18n Libraries (e.g., i18next) | Meteor Assets | Custom Config | a3t |
|---|---|---|---|---|
| Strings | Yes | No | Maybe | Yes |
| Binary Assets | No | Yes | No | Yes |
| Templates/XML | No | Yes | Maybe | Yes |
| DB Override | Sometimes | No | Sometimes | Yes |
| Fallback Chain | i18n only | No | No | Yes (DB→FS→inline) |
| Context-aware | Language only | No | Maybe | Yes (full) |
| DX/Ease | Good for i18n, not generic | OK | Varied | Excellent |
See API.md for complete API documentation.
npm testThe test suite includes 43 comprehensive tests covering:
- Context management and query hierarchy
- Caching behavior and invalidation
- Database backend functionality
- Filesystem backend operations
- Framework compatibility
- Error handling and edge cases
- Short, unique, and memorable (stands for "asset", using 3 for "s").
- Easy to search for and avoids naming collisions.
- Instinctive, mirroring established i18n/config APIs, but generalized.
MPL-2.0