Home / guides / README-CONFIG

LARC Configuration System

Centralized path management for the LARC monorepo, eliminating hardcoded relative paths and enabling easy switching between development and production environments.

๐ŸŽฏ Why Use This?

Before:
// โŒ Hardcoded, breaks when file moves
import { PanClient } from '../../../../core/pan-client.mjs';
import '../../../components/pan-card.mjs';
After:
// โœ… Clean, portable, environment-aware
import { paths } from '/larc-config.mjs';
const PanClient = await import(paths.resolve('@larc/core', 'components/pan-client.mjs'));

// Or even simpler with autoload
<pan-card></pan-card>  <!-- Automatically resolves and loads -->

๐Ÿ“ฆ Setup

Option 1: Manual Import (In Your Scripts)

<script type="module">
  import { paths } from '/larc-config.mjs';

  // Use paths to resolve imports
  const { PanClient } = await import(paths.resolve('@larc/core', 'components/pan-client.mjs'));
  const client = new PanClient();
</script>

Option 2: With Autoloader (Automatic)

<!DOCTYPE html>
<html>
<head>
  <title>My LARC App</title>
</head>
<body>
  <!-- 1. Load config first -->
  <script type="module" src="/larc-config.mjs"></script>

  <!-- 2. Load autoloader (it will use the config) -->
  <script type="module" src="/core/pan.mjs"></script>

  <!-- 3. Use components - they load automatically! -->
  <pan-bus></pan-bus>
  <pan-card>
    <h2>Hello World</h2>
  </pan-card>

  <script type="module">
    // Config is available globally
    const resolved = window.larcResolve('@larc/core', 'components/pan-client.mjs');
    console.log(resolved);
  </script>
</body>
</html>

Option 3: Import Map (Modern Browsers)

<script type="importmap">
{
  "imports": {
    "@larc/core/": "./core/",
    "@larc/components/": "./components/",
    "pan-bus": "./core/pan-bus.mjs",
    "pan-client": "./core/pan-client.mjs"
  }
}
</script>

<script type="module">
  // Now you can use clean imports!
  import { PanClient } from 'pan-client';
  import '@larc/core/pan-bus.mjs';
</script>

๐Ÿ”ง Configuration

The larc-config.mjs file defines:

Aliases

Aliases map short names to actual paths, automatically switching between dev and production:

export const aliases = {
  '@larc/core': isDevelopment
    ? './core/src'                                    // Local dev
    : 'https://unpkg.com/@larcjs/core@3.0.1/src',    // Production CDN

  '@larc/components': isDevelopment
    ? './components/src'
    : 'https://unpkg.com/@larcjs/ui@3.0.1/src',
};

Component Mappings

Explicit mappings for components used by the autoloader:

export const componentPaths = {
  'pan-bus': '@larc/core/pan-bus.mjs',
  'pan-card': '@larc/components/pan-card.mjs',
  'pan-data-table': '@larc/components/pan-data-table.mjs',
  // ... more components
};

Path Resolver

The paths utility provides methods for resolving paths:

// Resolve an alias
paths.resolve('@larc/core', 'components/pan-bus.mjs');
// Dev:  => './core/pan-bus.mjs'
// Prod: => 'https://unpkg.com/@larcjs/core@3.0.1/pan-bus.mjs'

// Get a component path
paths.component('pan-card');
// => './components/pan-card.mjs' (dev)

// Join paths
paths.join('./base/', 'subpath/file.mjs');
// => './base/subpath/file.mjs'

๐Ÿ“ Usage Examples

Example 1: Dynamic Import with Path Resolution

import { paths } from '/larc-config.mjs';

// Resolve and import
const panClientPath = paths.resolve('@larc/core', 'components/pan-client.mjs');
const { PanClient } = await import(panClientPath);

const client = new PanClient();
client.publish('app.ready', { timestamp: Date.now() });

Example 2: Building Import URLs

<script type="module">
  import { paths } from '/larc-config.mjs';

  // Build imports dynamically
  const components = ['pan-card', 'pan-modal', 'pan-tabs'];

  for (const comp of components) {
    const path = paths.component(comp);
    await import(path);
  }
</script>

Example 3: Using Global Helper

<script type="module" src="/larc-config.mjs"></script>
<script type="module">
  // After loading config, use the global helper
  const corePath = window.larcResolve('@larc/core');
  console.log('Core is at:', corePath);

  // Load a specific file
  const clientPath = window.larcResolve('@larc/core', 'components/pan-client.mjs');
  const { PanClient } = await import(clientPath);
</script>

Example 4: Component with Auto-Loading

<!-- No imports needed! Config + autoloader handles it -->
<script type="module" src="/larc-config.mjs"></script>
<script type="module" src="/core/pan.mjs"></script>

<pan-data-table resource="users"></pan-data-table>
<pan-form resource="users"></pan-form>

<!-- Components load automatically when they enter viewport -->

๐ŸŒ Environment Detection

The config automatically detects the environment:

const isDevelopment = window.location.hostname === 'localhost' ||
                      window.location.hostname === '127.0.0.1' ||
                      window.location.protocol === 'file:';
  • Development: Uses relative paths (./core/src, ./components/src)
  • Production: Uses CDN URLs (https://unpkg.com/@larcjs/...)

โš™๏ธ Customizing the Config

Per-Page Override

Override config before loading the main config:

<script>
  // Set custom paths before loading config
  window.panAutoload = {
    baseUrl: 'https://my-cdn.com/larc/',
    componentsPath: 'my-components/'
  };
</script>
<script type="module" src="/larc-config.mjs"></script>

Custom Component Paths

Add your own components to the mapping:

// In larc-config.mjs
export const componentPaths = {
  // ... existing mappings

  // Your custom components
  'my-widget': './my-app/components/my-widget.mjs',
  'my-dialog': '@larc/components/my-dialog.mjs',
};

Custom Resolver

Provide your own resolution logic:

export const autoloadConfig = {
  // ... other config

  resolveComponent(tagName) {
    // Custom logic for resolving component paths
    if (tagName.startsWith('my-')) {
      return `./custom/${tagName}.mjs`;
    }
    // Return null to fall back to default behavior
    return null;
  }
};

๐Ÿš€ Benefits

  • โœ… No Hardcoded Paths - All paths are configurable
  • โœ… Environment Aware - Auto-switches dev/prod
  • โœ… Centralized - One place to manage all paths
  • โœ… CDN Ready - Easy production deployment
  • โœ… Portable - Move files without breaking imports
  • โœ… Zero Build - Still no build step required
  • โœ… Backward Compatible - Existing code still works

  • ๐Ÿ“š API Reference

    paths.resolve(aliasOrPath, subpath?)

    Resolves an alias or path to an absolute URL.
    • Parameters:
    - aliasOrPath (string): Alias like '@larc/core' or a path - subpath (string, optional): Subpath to append
    • Returns: (string) Resolved URL

    paths.component(componentName)

    Gets the path for a specific component.
    • Parameters:
    - componentName (string): Component tag name (e.g., 'pan-card')
    • Returns: (string) Resolved component path

    paths.join(base, path)

    Joins two path segments correctly.
    • Parameters:
    - base (string): Base path - path (string): Path to append
    • Returns: (string) Joined path

    window.larcResolve(aliasOrPath, subpath?)

    Global helper function (same as paths.resolve).

    ๐Ÿ” Debugging

    Check the loaded configuration:

    // In browser console
    console.log(window.panAutoload);
    // Shows: { config, paths, aliases, componentPaths, ... }
    
    // Check a specific alias
    console.log(window.panAutoload.aliases['@larc/core']);
    
    // Test path resolution
    console.log(window.larcResolve('@larc/core', 'components/pan-bus.mjs'));

    ๐Ÿ“– Migration Guide

    To migrate existing code to use the config system:

    Step 1: Load the Config

    Add to your HTML:

    <script type="module" src="/larc-config.mjs"></script>

    Step 2: Option A - Keep Using Autoloader

    If you're using custom elements, no changes needed! The autoloader will use the config automatically.

    Step 3: Option B - Update Manual Imports

    Replace hardcoded paths:

    // Before
    import { PanClient } from '../../../core/pan-client.mjs';
    
    // After
    import { paths } from '/larc-config.mjs';
    const { PanClient } = await import(paths.resolve('@larc/core', 'components/pan-client.mjs'));
    
    // Or use window.larcResolve in non-module scripts
    const path = window.larcResolve('@larc/core', 'components/pan-client.mjs');
    const { PanClient } = await import(path);

    ๐Ÿ’ก Tips

  • Load config before autoloader - The autoloader will pick up the config automatically
  • Use aliases in new code - Makes it easier to refactor later
  • Test both environments - Make sure dev and prod paths work
  • Document custom components - Add them to componentPaths for clarity
  • Consider import maps - Modern browsers support them natively

  • ๐Ÿ› Troubleshooting

    Component not loading?

  • Check if it's in componentPaths mapping
  • Verify the path with paths.component('your-component')
  • Check browser console for autoloader warnings
  • Wrong path in production?

  • Check isDevelopment detection logic
  • Verify CDN URLs in aliases
  • Test with window.location.hostname
  • Config not loading?

  • Load config before other modules
  • Check for JavaScript errors
  • Verify larc-config.mjs is accessible

  • Need help? Open an issue on GitHub or check the examples in /examples/ directory.