Blueprints

Unified schema system - define once, use everywhere for validation, forms, models, and CRUD.

Overview

Blueprints are Domma's unified schema system. Define your data structure once, then use it everywhere:

Overview

Validation

Built-in + custom

Forms

Auto-generation

Models

Reactive data

CRUD

Complete system

<div class="grid grid-cols-4 grid-cols-md-4 gap-4 mb-4"><div class="card text-center">
        <div class="card-body">
            <span data-icon="check-circle" data-size="32" class="text-success mb-2"></span>
            <h4 class="text-sm font-semibold">Validation</h4>
            <p class="text-xs text-muted">Built-in + custom</p>
        </div>
    </div>
    <div class="card text-center">
        <div class="card-body">
            <span data-icon="layout" data-size="32" class="text-primary mb-2"></span>
            <h4 class="text-sm font-semibold">Forms</h4>
            <p class="text-xs text-muted">Auto-generation</p>
        </div>
    </div>
    <div class="card text-center">
        <div class="card-body">
            <span data-icon="database" data-size="32" class="text-info mb-2"></span>
            <h4 class="text-sm font-semibold">Models</h4>
            <p class="text-xs text-muted">Reactive data</p>
        </div>
    </div>
    <div class="card text-center">
        <div class="card-body">
            <span data-icon="grid" data-size="32" class="text-warning mb-2"></span>
            <h4 class="text-sm font-semibold">CRUD</h4>
            <p class="text-xs text-muted">Complete system</p>
        </div>
    </div>
</div>

Full Documentation: See the Reference Documentation for comprehensive guide with tutorials and examples.

Blueprint Anatomy

A blueprint is a JavaScript object defining field types, validation, and UI configuration.

const userBlueprint = {
    name: {
        type: 'string',           // Field type
        required: true,           // Validation
        minLength: 2,
        maxLength: 50,
        label: 'Full Name',       // Form config
        placeholder: 'Enter name'
    },
    email: {
        type: 'email',
        required: true,
        label: 'Email Address',
        validate: (value) => {    // Custom validator
            return /\S+@\S+/.test(value) || 'Invalid email';
        }
    },
    age: {
        type: 'number',
        min: 0,
        max: 120,
        label: 'Age'
    },
    active: {
        type: 'boolean',
        default: true,
        label: 'Active User'
    }
};
Field Properties
type required default min / max minLength / maxLength pattern validate label placeholder help
<div class="blueprint-methods">
    <span class="blueprint-method">type</span>
    <span class="blueprint-method">required</span>
    <span class="blueprint-method">default</span>
    <span class="blueprint-method">min / max</span>
    <span class="blueprint-method">minLength / maxLength</span>
    <span class="blueprint-method">pattern</span>
    <span class="blueprint-method">validate</span>
    <span class="blueprint-method">label</span>
    <span class="blueprint-method">placeholder</span>
    <span class="blueprint-method">help</span>
</div>

Built-in Types

Domma provides 7 built-in types for common data structures:

Built-in Types
M.types.string

Text data

M.types.number

Numeric values

M.types.boolean

True/false

M.types.array

Lists

M.types.object

Nested data

M.types.date

Timestamps

M.types.any

No validation

<div class="grid grid-cols-4 grid-cols-md-3 gap-3"><div class="card">
        <div class="card-body">
            <code class="text-primary">M.types.string</code>
            <p class="text-xs text-muted mt-1">Text data</p>
        </div>
    </div>
    <div class="card">
        <div class="card-body">
            <code class="text-primary">M.types.number</code>
            <p class="text-xs text-muted mt-1">Numeric values</p>
        </div>
    </div>
    <div class="card">
        <div class="card-body">
            <code class="text-primary">M.types.boolean</code>
            <p class="text-xs text-muted mt-1">True/false</p>
        </div>
    </div>
    <div class="card">
        <div class="card-body">
            <code class="text-primary">M.types.array</code>
            <p class="text-xs text-muted mt-1">Lists</p>
        </div>
    </div>
    <div class="card">
        <div class="card-body">
            <code class="text-primary">M.types.object</code>
            <p class="text-xs text-muted mt-1">Nested data</p>
        </div>
    </div>
    <div class="card">
        <div class="card-body">
            <code class="text-primary">M.types.date</code>
            <p class="text-xs text-muted mt-1">Timestamps</p>
        </div>
    </div>
    <div class="card">
        <div class="card-body">
            <code class="text-primary">M.types.any</code>
            <p class="text-xs text-muted mt-1">No validation</p>
        </div>
    </div>
</div>

Blueprint Examples

Explore pre-built blueprints for common use cases.

Blueprint Examples
<div id="blueprint-tabs"></div>
/**
 * Blueprint Examples - from public/showcase/blueprints.
 */
export function mount(root) {
    const blueprints = {
        contact: {
            name: { type: 'string', required: true, minLength: 2, label: 'Full Name', placeholder: 'Enter your full name' },
            email: { type: 'email', required: true, label: 'Email Address', placeholder: 'you@example.com' },
            message: { type: 'textarea', required: true, minLength: 10, rows: 4, label: 'Message', placeholder: 'Your message here...' }
        },
        registration: {
            email: { type: 'email', required: true, label: 'Email Address' },
            password: {
                type: 'password',
                required: true,
                minLength: 8,
                label: 'Password',
                help: 'At least 8 characters',
                validate: (value) => {
                    if (!/[A-Z]/.test(value)) return 'Need uppercase letter';
                    if (!/[0-9]/.test(value)) return 'Need a number';
                    return true;
                }
            },
            confirmPassword: {
                type: 'password',
                required: true,
                label: 'Confirm Password',
                validate: (value, data) => {
                    return value === data.password || 'Passwords do not match';
                }
            },
            agreeToTerms: {
                type: 'boolean',
                required: true,
                label: 'I agree to the Terms of Service',
                validate: (value) => value || 'You must accept the terms'
            }
        },
        settings: {
            notifications: { type: 'boolean', default: true, label: 'Email Notifications' },
            theme: { type: 'select', options: ['light', 'dark', 'auto'], default: 'auto', label: 'Theme' },
            language: {
                type: 'radio',
                options: [
                    { value: 'en', label: 'English' },
                    { value: 'es', label: 'Español' },
                    { value: 'fr', label: 'Français' }
                ],
                default: 'en',
                label: 'Language'
            }
        },
        product: {
            name: {
                type: 'string',
                required: true,
                maxLength: 100,
                label: 'Product Name',
                formConfig: {
                    span: 2,  // Span 2 columns in grid layout
                    tooltip: 'The display name of your product'
                }
            },
            sku: {
                type: 'string',
                required: true,
                pattern: /^[A-Z0-9-]+$/,
                label: 'SKU',
                formConfig: {
                    placeholder: 'e.g. PROD-001',
                    tooltip: 'Stock Keeping Unit - unique product identifier'
                }
            },
            price: {
                type: 'number',
                required: true,
                min: 0,
                step: 0.01,
                label: 'Price (£)',
                formConfig: {
                    placeholder: '0.00',
                    tooltip: 'Product price in GBP'
                }
            },
            category: {
                type: 'select',
                required: true,
                options: ['Electronics', 'Clothing', 'Home'],
                label: 'Category',
                formConfig: {
                    tooltip: 'Product category for organisation'
                }
            },
            stock: {
                type: 'number',
                required: true,
                min: 0,
                label: 'Stock Quantity',
                formConfig: {
                    placeholder: '0',
                    tooltip: 'Current available inventory'
                }
            },
            description: {
                type: 'textarea',
                required: true,
                maxLength: 1000,
                rows: 5,
                label: 'Description',
                formConfig: {
                    span: 2,  // Full width in 2-column grid
                    placeholder: 'Product description...',
                    helperText: 'Maximum 1000 characters',
                    tooltip: 'Detailed product description for customers'
                }
            },
            inStock: {
                type: 'boolean',
                default: true,
                label: 'In Stock',
                formConfig: { span: 2 }  // Full width
            }
        },
        userProfile: {
            firstName: {
                type: 'string',
                required: true,
                minLength: 2,
                label: 'First Name',
                formConfig: { placeholder: 'Enter first name' }
            },
            lastName: {
                type: 'string',
                required: true,
                minLength: 2,
                label: 'Last Name',
                formConfig: { placeholder: 'Enter last name' }
            },
            email: {
                type: 'email',
                required: true,
                label: 'Email Address',
                formConfig: {
                    placeholder: 'you@example.com',
                    helperText: 'We will never share your email'
                }
            },
            phone: {
                type: 'tel',
                label: 'Phone Number',
                formConfig: { placeholder: '+44 20 1234 5678' }
            },
            bio: {
                type: 'textarea',
                rows: 4,
                maxLength: 500,
                label: 'Biography',
                formConfig: {
                    span: 2,  // Full width
                    placeholder: 'Tell us about yourself...',
                    helperText: 'Maximum 500 characters'
                }
            },
            website: {
                type: 'url',
                label: 'Website',
                formConfig: {
                    placeholder: 'https://example.com',
                    hint: '(optional)'
                }
            },
            role: {
                type: 'select',
                required: true,
                options: ['Developer', 'Designer', 'Manager', 'Other'],
                label: 'Role',
                default: 'Developer'
            },
            newsletter: {
                type: 'boolean',
                label: 'Subscribe to newsletter',
                default: false,
                formConfig: { span: 2 }
            }
        }
    };
    // Initialize blueprint tabs - CREATE HTML FIRST!
    const tabItems = [
        { label: 'Contact', value: 'contact' },
        { label: 'Registration', value: 'registration' },
        { label: 'Settings', value: 'settings' },
        { label: 'Product (Grid)', value: 'product' },
        { label: 'User Profile (Grid)', value: 'userProfile' }
    ];
    // Build tabs HTML structure
    let tabsHTML = '<div class="tabs"><div class="tab-list" role="tablist">';
    tabItems.forEach((item, index) => {
        tabsHTML += `<button type="button" class="tab-item${index === 0 ? ' active' : ''}" role="tab" data-tab="${item.value}">${item.label}</button>`;
    });
    tabsHTML += '</div><div class="tabs-content">';
    tabItems.forEach((item, index) => {
        tabsHTML += `<div class="tab-panel${index === 0 ? ' active' : ''}" role="tabpanel" data-panel="${item.value}" id="tab-${item.value}"></div>`;
    });
    tabsHTML += '</div></div>';
    // Sanitize and insert HTML
    $(root).find('#blueprint-tabs').html(tabsHTML);
    // NOW initialize the tabs component
    const tabsInstance = E.tabs($(root).find('#blueprint-tabs .tabs').get(0), {
        animation: true,
        onChange: (e) => {
            const exampleKey = tabItems[e.index].value;
            showBlueprintExample(exampleKey);
        }
    });
    function showBlueprintExample(key) {
        const blueprint = blueprints[key];
        const container = $(root).find(`#tab-${key}`);

        // Escape JSON for safe HTML insertion
        const blueprintCode = JSON.stringify(blueprint, null, 2)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');

        const html = `
            <div class="grid grid-cols-1 grid-cols-md-2 gap-4">
                <div>
                    <h4 class="font-semibold mb-2">Blueprint Code</h4>
                    <pre class="blueprint-code">${blueprintCode}</pre>
                </div>
                <div>
                    <h4 class="font-semibold mb-2">Generated Form</h4>
                    <div class="result-pane" id="form-${key}"></div>
                </div>
            </div>
        `;

        container.html(html);

        // Generate and render form - ONE-STEP API
        // Use grid layout for product and userProfile examples
        const formLayout = (key === 'product' || key === 'userProfile') ? 'grid' : 'stacked';
        const formColumns = 2;

        F.render(`#form-${key}`, blueprint, {}, {
            layout: formLayout,
            columns: formColumns,
            submitText: 'Submit',
            onSubmit: (data) => {
                E.toast('Form submitted successfully!', { type: 'success' });
                console.log('Submitted:', data);
            },
            onValidationError: (errors) => {
                E.toast('Please fix validation errors', { type: 'error' });
                console.error('Validation errors:', errors);
            }
        });
    }
    // Show first example
    showBlueprintExample('contact');
    return () => tabsInstance.destroy();
}

Field-Level Styling

Control form layout and field appearance using formConfig properties.

Form-Level Options

F.render('#form', blueprint, {}, {
    layout: 'grid',      // or 'stacked', 'inline'
    columns: 2,          // 2 or 3 columns (grid only)
    labelPosition: 'top', // or 'left', 'floating'
    showLabels: true,
    showHelperText: true
});

Field-Level Options

fieldName: {
    type: 'string',
    required: true,
    label: 'Field Label',
    formConfig: {
        span: 2,              // Span 2 columns
        placeholder: 'Text',  // Placeholder
        helperText: 'Help',   // Below field
        hint: '(optional)',   // Next to label
        tooltip: 'Info',      // Hover tooltip (NEW!)
        disabled: false       // Disable field
    }
}

Grid Layout Example

Use layout: 'grid' with columns: 2 and formConfig.span to control field width:

const addressBlueprint = {
    street: {
        type: 'string',
        required: true,
        label: 'Street Address',
        formConfig: { span: 2 }  // Full width (spans 2 columns)
    },
    city: {
        type: 'string',
        required: true,
        label: 'City'
        // No span = takes 1 column (left side)
    },
    postcode: {
        type: 'string',
        required: true,
        label: 'Postcode'
        // No span = takes 1 column (right side)
    },
    country: {
        type: 'select',
        options: ['UK', 'USA', 'Canada'],
        label: 'Country',
        formConfig: { span: 2 }  // Full width
    }
};

// Render with grid layout
F.render('#form', addressBlueprint, {}, {
    layout: 'grid',
    columns: 2
});

Tip: The Product (Grid) and User Profile (Grid) tabs above demonstrate grid layout with field spanning.

Blueprint → Form Generation

Automatically generate forms from blueprints with full validation.

Blueprint → Form Generation

Blueprint Definition

const contactBlueprint = {
            name: {
            type: 'string',
            required: true,
            minLength: 2,
            label: 'Full Name'
            },
            email: {
            type: 'email',
            required: true,
            label: 'Email'
            },
            message: {
            type: 'textarea',
            required: true,
            minLength: 10,
            rows: 4,
            label: 'Message'
            }
            };

            // Generate and render form (one-step)
            F.render(
            '#contact-form',    // selector
            contactBlueprint,   // schema
            {},                 // initial data
            {                   // options
            layout: 'stacked',
            onSubmit: (data) => {
            console.log(data);
            }
            }
            );
        

Generated Form

<div class="grid grid-cols-1 grid-cols-md-2 gap-4"><div>
        <h4 class="font-semibold mb-2">Blueprint Definition</h4>
        <pre class="code-block language-javascript">const contactBlueprint = {
            name: {
            type: 'string',
            required: true,
            minLength: 2,
            label: 'Full Name'
            },
            email: {
            type: 'email',
            required: true,
            label: 'Email'
            },
            message: {
            type: 'textarea',
            required: true,
            minLength: 10,
            rows: 4,
            label: 'Message'
            }
            };

            // Generate and render form (one-step)
            F.render(
            '#contact-form',    // selector
            contactBlueprint,   // schema
            {},                 // initial data
            {                   // options
            layout: 'stacked',
            onSubmit: (data) =&gt; {
            console.log(data);
            }
            }
            );
        </pre>
    </div>
    <div>
        <h4 class="font-semibold mb-2">Generated Form</h4>
        <div class="result-pane">
            <div id="contact-form"></div>
        </div>
    </div>
</div>
/**
 * Blueprint → Form Generation - from public/showcase/blueprints.
 */
export function mount(root) {
    // Contact Form Example - ONE-STEP API
    const contactBlueprint = {
        name: {
            type: 'string',
            required: true,
            minLength: 2,
            label: 'Full Name',
            formConfig: {
                tooltip: 'Enter your first and last name'
            }
        },
        email: {
            type: 'email',
            required: true,
            label: 'Email',
            formConfig: {
                tooltip: 'We\'ll never share your email with anyone'
            }
        },
        message: {
            type: 'textarea',
            required: true,
            minLength: 10,
            rows: 4,
            label: 'Message',
            formConfig: {
                tooltip: 'Let us know how we can help you'
            }
        }
    };
    F.render('#contact-form', contactBlueprint, {}, {
        layout: 'stacked',
        submitText: 'Send Message',
        onSubmit: (data) => {
            E.toast('Message sent!', { type: 'success' });
            console.log('Form submitted:', data);
        },
        onValidationError: (errors) => {
            E.toast('Please fix validation errors', { type: 'error' });
            console.error('Validation errors:', errors);
        }
    });
}

Blueprint → Reactive Model

Create reactive data models with automatic validation and change tracking.

Blueprint → Reactive Model

Code

const user = M.create(userBlueprint, {
            name: 'Alice',
            email: 'alice@example.com',
            age: 30
            });

            // Get values
            user.get('name');  // 'Alice'

            // Set values
            user.set('age', 31);

            // Validate
            const errors = user.validate();

            // Listen for changes
            user.onChange((event) => {
            console.log(event);
            });
        
Try It

Model State

Current Data:

{}

Change Log:

No changes yet
<div class="grid grid-cols-1 grid-cols-md-2 gap-4"><div>
        <h4 class="font-semibold mb-2">Code</h4>
        <pre class="code-block language-javascript">const user = M.create(userBlueprint, {
            name: 'Alice',
            email: 'alice@example.com',
            age: 30
            });

            // Get values
            user.get('name');  // 'Alice'

            // Set values
            user.set('age', 31);

            // Validate
            const errors = user.validate();

            // Listen for changes
            user.onChange((event) =&gt; {
            console.log(event);
            });
        </pre>

        <div class="mt-3">
            <h5 class="font-semibold mb-2">Try It</h5>
            <div class="form-group">
                <label class="form-label">Name</label>
                <input type="text" id="model-name" class="form-input" value="Alice">
            </div>
            <div class="form-group">
                <label class="form-label">Email</label>
                <input type="email" id="model-email" class="form-input" value="alice@example.com">
            </div>
            <div class="form-group">
                <label class="form-label">Age</label>
                <input type="number" id="model-age" class="form-input" value="30">
            </div>
            <button type="button" class="btn btn-primary btn-sm" id="validate-model">Validate</button>
            <button type="button" class="btn btn-secondary btn-sm" id="reset-model">Reset</button>
        </div>
    </div>
    <div>
        <h4 class="font-semibold mb-2">Model State</h4>
        <div class="model-state">
            <h4>Current Data:</h4>
            <pre id="model-state-display">{}</pre>
        </div>
        <div class="model-state mt-3" id="validation-result" style="display: none;">
            <h4>Validation Result:</h4>
            <pre id="validation-display"></pre>
        </div>
        <div class="model-state mt-3">
            <h4>Change Log:</h4>
            <pre id="model-change-log">No changes yet</pre>
        </div>
    </div>
</div>
/**
 * Blueprint → Reactive Model - from public/showcase/blueprints.
 */
export function mount(root) {
    // Reactive Model Demo
    const userBlueprint = {
        name: { type: 'string', required: true, minLength: 2 },
        email: { type: 'email', required: true },
        age: { type: 'number', min: 0, max: 120 }
    };
    const userModel = M.create(userBlueprint, {
        name: 'Alice',
        email: 'alice@example.com',
        age: 30
    });
    let changeLog = [];
    // Update state display
    function updateModelState() {
        $(root).find('#model-state-display').text(JSON.stringify(userModel.toJSON(), null, 2));
    }
    // Manual binding - M.bind() doesn't work with standard HTML inputs
    $(root).find('#model-name').on('input', function() {
        try {
            userModel.set('name', $(this).val());
        } catch (error) {
            console.warn('Validation error (name):', error.message);
        }
    });
    $(root).find('#model-email').on('input', function() {
        try {
            userModel.set('email', $(this).val());
        } catch (error) {
            console.warn('Validation error (email):', error.message);
        }
    });
    $(root).find('#model-age').on('input', function() {
        try {
            const value = $(this).val();
            userModel.set('age', value === '' ? null : parseInt(value, 10));
        } catch (error) {
            console.warn('Validation error (age):', error.message);
        }
    });
    // Listen for changes
    userModel.onChange((event) => {
        changeLog.push(`${event.field}: ${event.oldValue} → ${event.newValue}`);
        $(root).find('#model-change-log').text(changeLog.join('\n'));
        updateModelState();

        // Update input if changed programmatically
        if (event.field === 'name') $(root).find('#model-name').val(event.newValue);
        if (event.field === 'email') $(root).find('#model-email').val(event.newValue);
        if (event.field === 'age') $(root).find('#model-age').val(event.newValue);
    });
    updateModelState();
    // Validate button
    $(root).find('#validate-model').on('click', () => {
        const errors = userModel.validate();

        // Display validation result
        if (errors && errors.length > 0) {
            $(root).find('#validation-display').text(JSON.stringify(errors, null, 2));
            $(root).find('#validation-result').show();
            E.toast('Validation errors found', { type: 'error' });
        } else {
            $(root).find('#validation-display').text('✓ All fields are valid');
            $(root).find('#validation-result').show();
            E.toast('All fields valid!', { type: 'success' });
        }
    });
    // Reset button
    $(root).find('#reset-model').on('click', () => {
        userModel.reset();
        changeLog = [];
        $(root).find('#model-change-log').text('No changes yet');
        $(root).find('#validation-result').hide();
        updateModelState();
    });
}

Blueprint Composition

Combine, extend, and modify blueprints with composition methods.

B.extend() - Merge Blueprints
const base = {
            name: { type: 'string' },
            email: { type: 'email' }
            };

            const extended = {
            email: { required: true },
            age: { type: 'number' }
            };

            const result = B.extend(base, extended);
            // { name: {...}, email: {required: true}, age: {...} }
        
<div class="grid grid-cols-1 grid-cols-md-2 gap-4">
    <div>
        <pre class="code-block language-javascript">const base = {
            name: { type: 'string' },
            email: { type: 'email' }
            };

            const extended = {
            email: { required: true },
            age: { type: 'number' }
            };

            const result = B.extend(base, extended);
            // { name: {...}, email: {required: true}, age: {...} }
        </pre>
    </div>
    <div>
        <button type="button" class="btn btn-primary mb-2" id="extend-demo">Run Example</button>
        <div class="result-pane" id="extend-result" style="display: none;">
            <h5>Result:</h5>
            <pre id="extend-result-code"></pre>
        </div>
    </div>
</div>
/**
 * B.extend() - Merge Blueprints - from public/showcase/blueprints.
 */
export function mount(root) {
    // Composition demos
    $(root).find('#extend-demo').on('click', () => {
        const base = { name: { type: 'string' }, email: { type: 'email' } };
        const extended = { email: { required: true }, age: { type: 'number' } };
        const result = B.extend(base, extended);
        $(root).find('#extend-result-code').text(JSON.stringify(result, null, 2));
        $(root).find('#extend-result').show();
    });
}
B.pick() - Extract Fields
const full = {
            name: { type: 'string' },
            email: { type: 'email' },
            age: { type: 'number' },
            role: { type: 'string' }
            };

            const subset = B.pick(full, ['name', 'email']);
            // { name: {...}, email: {...} }
        
<div class="grid grid-cols-1 grid-cols-md-2 gap-4">
    <div>
        <pre class="code-block language-javascript">const full = {
            name: { type: 'string' },
            email: { type: 'email' },
            age: { type: 'number' },
            role: { type: 'string' }
            };

            const subset = B.pick(full, ['name', 'email']);
            // { name: {...}, email: {...} }
        </pre>
    </div>
    <div>
        <button type="button" class="btn btn-primary mb-2" id="pick-demo">Run Example</button>
        <div class="result-pane" id="pick-result" style="display: none;">
            <h5>Result:</h5>
            <pre id="pick-result-code"></pre>
        </div>
    </div>
</div>
/**
 * B.pick() - Extract Fields - from public/showcase/blueprints.
 */
export function mount(root) {
    $(root).find('#pick-demo').on('click', () => {
        const full = {
            name: { type: 'string' },
            email: { type: 'email' },
            age: { type: 'number' },
            role: { type: 'string' }
        };
        const result = B.pick(full, ['name', 'email']);
        $(root).find('#pick-result-code').text(JSON.stringify(result, null, 2));
        $(root).find('#pick-result').show();
    });
}
B.omit() - Remove Fields
const admin = {
            name: { type: 'string' },
            email: { type: 'email' },
            role: { type: 'string' },
            permissions: { type: 'array' }
            };

            const public = B.omit(admin, ['permissions']);
            // { name: {...}, email: {...}, role: {...} }
        
<div class="grid grid-cols-1 grid-cols-md-2 gap-4">
    <div>
        <pre class="code-block language-javascript">const admin = {
            name: { type: 'string' },
            email: { type: 'email' },
            role: { type: 'string' },
            permissions: { type: 'array' }
            };

            const public = B.omit(admin, ['permissions']);
            // { name: {...}, email: {...}, role: {...} }
        </pre>
    </div>
    <div>
        <button type="button" class="btn btn-primary mb-2" id="omit-demo">Run Example</button>
        <div class="result-pane" id="omit-result" style="display: none;">
            <h5>Result:</h5>
            <pre id="omit-result-code"></pre>
        </div>
    </div>
</div>
/**
 * B.omit() - Remove Fields - from public/showcase/blueprints.
 */
export function mount(root) {
    $(root).find('#omit-demo').on('click', () => {
        const admin = {
            name: { type: 'string' },
            email: { type: 'email' },
            role: { type: 'string' },
            permissions: { type: 'array' }
        };
        const result = B.omit(admin, ['permissions']);
        $(root).find('#omit-result-code').text(JSON.stringify(result, null, 2));
        $(root).find('#omit-result').show();
    });
}

Full CRUD System

Blueprints power complete CRUD interfaces with tables, forms, and API integration.

CRUD Examples: For complete CRUD demonstrations with blueprints, see the Forms Showcase which includes full CRUD functionality with API integration, table management, and modal forms.

A typical CRUD setup with blueprints includes:

  • Data Table - Display records with sorting, filtering, pagination
  • Create Form - Modal form generated from blueprint
  • Edit Form - Pre-populated form for updating records
  • Delete Confirmation - Safe deletion with confirmation
  • Validation - Automatic validation from blueprint rules
  • API Integration - RESTful API calls or localStorage persistence

See It In Action: Visit the Forms Showcase → CRUD Section for live interactive examples.