Skip to main content

Security

Use Environment Variables

Never hardcode API tokens in your source code. Always use environment variables:
// .env
VITE_STRINGBOOT_TOKEN=your_token_here

// main.js
await StringBoot.initialize({
  apiToken: import.meta.env.VITE_STRINGBOOT_TOKEN,
  baseUrl: 'https://api.stringboot.com',
  defaultLanguage: 'en',
  debug: import.meta.env.DEV
});
Add .env files to your .gitignore to prevent committing secrets to version control.

Disable Debug Mode in Production

Only enable debug logging during development:
await StringBoot.initialize({
  apiToken: import.meta.env.VITE_STRINGBOOT_TOKEN,
  baseUrl: 'https://api.stringboot.com',
  defaultLanguage: 'en',
  debug: import.meta.env.DEV // Only true in development
});

Performance

Initialize Early

Initialize the SDK as early as possible in your application:
// main.js - Initialize before rendering
import StringBoot from '@stringboot/web-sdk';

await StringBoot.initialize({
  apiToken: import.meta.env.VITE_STRINGBOOT_TOKEN,
  baseUrl: 'https://api.stringboot.com',
  defaultLanguage: 'en',
  debug: false
});

// Now render your app
import { createRoot } from 'react-dom/client';
import { App } from './App';

createRoot(document.getElementById('root')).render(<App />);

Batch String Fetching (React)

Use useStrings instead of multiple useString calls:
import { useStrings } from '@stringboot/web-sdk/react';

function ProductCard() {
  const strings = useStrings([
    'product_title',
    'product_description',
    'add_to_cart'
  ]);

  return (
    <div>
      <h3>{strings.product_title}</h3>
      <p>{strings.product_description}</p>
      <button>{strings.add_to_cart}</button>
    </div>
  );
}

Use Watchers (Vanilla JavaScript)

Set up watchers once during initialization for automatic UI updates:
import StringBoot from '@stringboot/web-sdk';

// Set up watchers once
StringBoot.watch('app_title', (value) => {
  document.getElementById('title').textContent = value;
});

StringBoot.watch('welcome_message', (value) => {
  document.getElementById('welcome').textContent = value;
});

// Language changes automatically update all watchers
await StringBoot.changeLanguage('es');

Error Handling

Always Use try/catch

Handle errors gracefully to prevent breaking your application:
import StringBoot from '@stringboot/web-sdk';

async function fetchStrings() {
  try {
    const message = await StringBoot.get('welcome_message');
    document.getElementById('welcome').textContent = message;
  } catch (error) {
    console.error('Failed to fetch string:', error);
    // Show fallback
    document.getElementById('welcome').textContent = 'Welcome';
  }
}

Handle Loading States (React)

Always check initialization state before rendering:
import { useStringBoot } from '@stringboot/web-sdk/react';

export function App() {
  const { initialized, error } = useStringBoot({
    apiToken: import.meta.env.VITE_STRINGBOOT_TOKEN,
    baseUrl: 'https://api.stringboot.com',
    defaultLanguage: 'en',
    debug: false
  });

  if (!initialized) return <LoadingSpinner />;
  if (error) return <ErrorMessage error={error} />;

  return <MainApp />;
}

Provide Fallback Values

Always provide defaults for critical strings:
import { useString } from '@stringboot/web-sdk/react';

function Header() {
  const title = useString('app_title') || 'My Application';
  return <h1>{title}</h1>;
}

User Experience

Disable Buttons During Operations

Prevent duplicate requests by disabling buttons:
const syncBtn = document.getElementById('syncBtn');

syncBtn.addEventListener('click', async () => {
  syncBtn.disabled = true;
  syncBtn.textContent = 'Syncing...';

  try {
    await StringBoot.syncNow();
    showSuccess('Sync completed!');
  } catch (error) {
    showError(error.message);
  } finally {
    syncBtn.disabled = false;
    syncBtn.textContent = 'Sync Now';
  }
});

Show Loading Indicators

Provide visual feedback during async operations:
import { useSync } from '@stringboot/web-sdk/react';

function SyncButton() {
  const { sync, syncing } = useSync();

  return (
    <button onClick={() => sync()} disabled={syncing}>
      {syncing ? (
        <>
          <Spinner /> Syncing...
        </>
      ) : (
        'Sync Strings'
      )}
    </button>
  );
}

React Patterns

Use Hooks Instead of Manual State

import { useString } from '@stringboot/web-sdk/react';

function Header() {
  const title = useString('app_title');
  return <h1>{title}</h1>;
}

Testing

Test Offline Behavior

Ensure your app works without an internet connection:
  1. Load your application with network enabled
  2. Switch to airplane mode or disable network
  3. Verify strings still display from cache
  4. Test language switching while offline

Test Language Switching

Verify all strings update when changing languages:
  1. Load your application
  2. Change language using your language selector
  3. Verify all visible strings update correctly
  4. Check console for any errors

Production Checklist

Before deploying to production, verify:
  • API token stored in environment variables
  • .env files added to .gitignore
  • Debug mode disabled in production
  • Loading states handled for initialization
  • Error states handled gracefully
  • Fallback values provided for critical strings
  • Buttons disabled during async operations
  • Offline behavior tested
  • Language switching tested
  • No console errors in production build

Common Patterns

Complete Vanilla JavaScript Setup

import StringBoot from '@stringboot/web-sdk';

async function initApp() {
  try {
    await StringBoot.initialize({
      apiToken: import.meta.env.VITE_STRINGBOOT_TOKEN,
      baseUrl: 'https://api.stringboot.com',
      defaultLanguage: 'en',
      debug: false
    });

    // Set up watchers
    StringBoot.watch('app_title', (value) => {
      document.getElementById('title').textContent = value;
    });

    // Set up language switcher
    document.getElementById('language').addEventListener('change', async (e) => {
      try {
        await StringBoot.changeLanguage(e.target.value);
      } catch (error) {
        console.error('Language change failed:', error);
      }
    });

  } catch (error) {
    console.error('Initialization failed:', error);
  }
}

initApp();

Complete React Setup

import { useStringBoot, useString, useLanguage, useActiveLanguages } from '@stringboot/web-sdk/react';

export function App() {
  const { initialized, error } = useStringBoot({
    apiToken: import.meta.env.VITE_STRINGBOOT_TOKEN,
    baseUrl: 'https://api.stringboot.com',
    defaultLanguage: 'en',
    debug: false
  });

  if (!initialized) return <LoadingScreen />;
  if (error) return <ErrorScreen error={error} />;

  return <MainApp />;
}

function MainApp() {
  const title = useString('app_title');
  const [currentLang, setLanguage] = useLanguage();
  const { languages } = useActiveLanguages();

  return (
    <div>
      <h1>{title}</h1>
      <select value={currentLang} onChange={(e) => setLanguage(e.target.value)}>
        {languages.map(lang => (
          <option key={lang.code} value={lang.code}>{lang.name}</option>
        ))}
      </select>
    </div>
  );
}

What’s Next?