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
});
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
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:
- Load your application with network enabled
- Switch to airplane mode or disable network
- Verify strings still display from cache
- Test language switching while offline
Test Language Switching
Verify all strings update when changing languages:
- Load your application
- Change language using your language selector
- Verify all visible strings update correctly
- Check console for any errors
Production Checklist
Before deploying to production, verify:
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?