Common Mistakes
Quick reference of frequent integration issues and how to fix them.
Each section shows a Wrong vs Correct pattern.
1. Styles Not Applying
If components look unstyled or spacing is off, Tailwind probably never scanned the UI source. Add the @source
directive to globals.css
.
1/* globals.css */
2/* Forgot @source so utility classes used inside UI bundle are purged */
See Installation.
2. Using Components Outside Provider
HeylockInput
, HeylockMessages
, and HeylockExpandingChat
expect an initialized provider ancestor. Mount the provider once at the root.
1// Component.jsx
2import { HeylockInput } from '@heylock-dev/ui';
3export function Chat() {
4 return <HeylockInput />; // Throws: used outside provider
5}
See Components.
3. Incorrect Agent Key Usage
In Next.js app router, vars without NEXT_PUBLIC_
prefix are not exposed to the client. Passing an undefined key causes an early provider error. Keep the real secret server-side if you proxy calls; otherwise expose a public-scoped key intentionally.
1// Key undefined at runtime on client (no NEXT_PUBLIC_)
2<HeylockProvider agentKey={process.env.HEYLOCK_AGENT_KEY} />
4. Calling Agent Before Initialization
Immediately calling methods can race with async initialization. Wait until the provider finishes or inspect agent.isInitialized
. For streaming, abort early if not ready.
1const agent = useAgent();
2const reply = await agent.message('Hi'); // Might run before initialization
See Hook.
5. Overwriting Streamed Chunks
When handling messageStream()
, append each chunk. Overwriting the state each loop iteration loses previously received content.
1let text = '';
2for await (const chunk of agent.messageStream('Explain streams')) {
3 text = chunk; // Overwrites previous partial
4}
6. Ignoring Balance
Not checking agent.balance
results in disabled-looking UI with confusing failures. Gate send actions and surface upgrade messaging.
1async function send(){
2 await agent.message('Hello'); // Might already be out of funds
3}
7. Re-Creating Agent on Every Render
Instantiating the core SDK inside component bodies causes multiple parallel initializations and lost callbacks. Let the provider own the lifecycle; downstream components consume the stable instance.
1// Every render constructs a new instance
2function Widget(){
3 const agent = new Heylock(process.env.NEXT_PUBLIC_HEYLOCK_AGENT_KEY);
4 return <button onClick={() => agent.message('Hi')}>Ask</button>;
5}
8. Custom Messages List Without Auto-Scroll
If you replace HeylockMessages
with a custom list, forgetting to scroll to the bottom hides new content. Maintain a ref and set scrollTop
after updates.
1// Custom list without auto-scroll
2useEffect(() => {
3 // render messages but never adjust scroll
4}, [messages]);
9. Hardcoding Agent Key in Source
Use an environment variable and pass it through build-time exposure intentionally.
1// Hardcoded secret (risks commit)
2<HeylockProvider agentKey="sk_live_really_secret" />
Debugging Checklist
- Console warningsInvalid theme, missing placeholders or keys — fix component props first.
agent.isInitialized
false? Wait for initialization or subscribe before invoking methods.- NetworkCheck failed requests in DevTools (401 = auth, 429 = quota, 5xx = server).
agent.balanceRemaining
Inspect remaining balance and gate UI/actions when balance is exhausted.- Tailwind classesIf styles are missing, rebuild (fresh dev build) so internal UI classes aren’t purged.
- StreamingAppend incoming chunks (don’t overwrite) and preserve partial text on errors.