Quick start (60 seconds)
Drop the SDK into the page, give your inputs the
kuyels class, and you're done. Below is a copy-pasteable
minimal HTML page — open it in a browser and it works.
<!DOCTYPE html> <html lang="en"> <body> <!-- 1. Add class="kuyels" to any input or textarea --> <input class="kuyels" placeholder="Type here…"> <textarea class="kuyels"></textarea> <!-- 2. Set your API key BEFORE loading the SDK --> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "YOUR_API_KEY_HERE" }); </script> <!-- 3. Load the SDK --> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> </body> </html>
kuyels
field. Press Tab to accept a suggestion.
Get your API key
Every project uses one api_key. You can get yours from
the Connection Plus dashboard, or contact us at
business-connectionplusuat.24livehost.com
to start a trial.
There are two key types — pick the one that matches your stage:
- Production — paid, no daily cap, full personalization.
- Development — free tier with a daily character quota.
Origin in the dashboard. Server-to-server traffic should
use a separate, unrestricted key.
Add the SDK script
The SDK is a single JavaScript file with no external dependencies.
Add it right before </body>:
<script> // Must be defined BEFORE kuyels.js loads. // Object.freeze() locks the config so nothing else on the page can mutate it. window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" // the only field you need }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script>
Supported languages
The SDK defaults to American English. To use a different language
on a specific input, set data-kuyels-language on the
element (see Step 3). Supported values:
en-US— American English (default)en-GB— British Englishen-AU— Australian Englishen-NZ— New Zealand Englishen-ZA— South African Englishfr-FR— French (France)
<script> tags at
the bottom of <body> — that way the SDK only
starts after your inputs are in the DOM.
Mark your inputs
Add class="kuyels" to any <input>,
<textarea>, or contenteditable
element you want to enhance. The SDK auto-attaches on page load
and also watches the DOM for new kuyels elements added
later.
You can freely mix kuyels with your own styling classes
— they don't conflict:
<!-- Brand class + your own design-system class --> <input type="text" id="short-description" name="short_description" class="kuyels demo-input" > <textarea id="long-description" name="long_description" class="kuyels demo-textarea" rows="8" ></textarea>
<input type="text" class="kuyels" name="title" placeholder="Post title…" >
<textarea class="kuyels" name="body" data-kuyels-language="en-GB" rows="6" ></textarea>
<div class="kuyels" contenteditable="true" role="textbox" aria-label="Editor" ></div>
Per-element options (HTML data attributes)
data-kuyels-id— stable id used aseditor_id(otherwise auto-generated).data-kuyels-language— language for this input only (e.g."en-GB","fr-FR"). Default:"en-US".
Framework examples
The SDK is framework-agnostic — it works with any HTML input. Below are minimal copy-paste snippets for the most common stacks.
<!DOCTYPE html> <html> <body> <textarea class="kuyels"></textarea> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> </body> </html>
<!-- inside public/index.html, before </body> --> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "%REACT_APP_CP_KEY%" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js" defer></script>
import { useEffect, useRef } from "react"; export default function CommentBox() { const ref = useRef(null); useEffect(() => { // Wait until SDK script has loaded on the page if (window.ConnectionPlusEditor && ref.current) { window.ConnectionPlusEditor.enhance(ref.current); } }, []); return <textarea ref={ref} className="kuyels" />; }
import Script from "next/script"; export default function RootLayout({ children }) { return ( <html> <body> <Script id="cp-cfg" strategy="beforeInteractive">{` window.CONNECTION_PLUS = Object.freeze({ API_KEY: "${process.env.NEXT_PUBLIC_CP_KEY}" }); `}</Script> <Script src="https://nlp.fixbien.com:19476/static/kuyels.js" strategy="afterInteractive" /> {children} </body> </html> ); }
<!-- add to your Vite index.html before </body> --> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script>
<template> <textarea ref="box" class="kuyels"/> </template> <script setup> import { ref, onMounted } from "vue"; const box = ref(null); onMounted(() => { window.ConnectionPlusEditor?.enhance(box.value); }); </script>
export default defineNuxtConfig({ app: { head: { script: [ { innerHTML: ` window.CONNECTION_PLUS = Object.freeze({ API_KEY: "${process.env.NUXT_PUBLIC_CP_KEY}" }); ` }, { src: "https://nlp.fixbien.com:19476/static/kuyels.js", defer: true } ] } } });
<body> <app-root></app-root> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> </body>
import { Component, ElementRef, AfterViewInit, ViewChild } from "@angular/core"; @Component({ selector: "app-editor", template: `<textarea #box class="kuyels"></textarea>` }) export class EditorComponent implements AfterViewInit { @ViewChild("box") box!: ElementRef<HTMLTextAreaElement>; ngAfterViewInit() { (window as any).ConnectionPlusEditor?.enhance(this.box.nativeElement); } }
<svelte:head> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> </svelte:head>
<script> import { onMount } from "svelte"; let box; onMount(() => { window.ConnectionPlusEditor?.enhance(box); }); </script> <textarea bind:this={box} class="kuyels"/>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <textarea id="editor" class="kuyels"></textarea> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> <script> // For inputs you inject dynamically with jQuery: $(function () { $("#dynamicForm").append('<textarea class="kuyels"></textarea>'); // Auto-attach via MutationObserver — no extra call needed. }); </script>
// Add to your theme's functions.php or a custom plugin. add_action('wp_enqueue_scripts', function () { // 1. Inline the config BEFORE kuyels.js loads. wp_register_script('connection-plus-config', '', [], null, true); wp_enqueue_script('connection-plus-config'); wp_add_inline_script('connection-plus-config', ' window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); '); // 2. Load the SDK after the config. wp_enqueue_script( 'connection-plus-sdk', 'https://nlp.fixbien.com:19476/static/kuyels.js', ['connection-plus-config'], null, true ); });
Then in any post / page / Gutenberg HTML block, just write
<textarea class="kuyels"></textarea> —
it works on the front-end and inside Contact Form 7, WPForms, etc.
<script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script>
In Webflow Designer, select any form field → Settings panel →
scroll to Custom Attributes → add
class = kuyels (or add it to the field's
existing class in the Styles panel).
{%- comment -%} Paste just before </body> in layout/theme.liquid {%- endcomment -%} <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "fxb_live_xxx" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> <!-- example: a product-review textarea --> <textarea name="review[body]" class="kuyels"></textarea>
{% verbatim %}<body>
{% block content %}{% endblock %}
<script>
window.CONNECTION_PLUS = Object.freeze({
API_KEY: "{{ CP_API_KEY }}"
});
</script>
<script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script>
</body>{% endverbatim %}
# In your form template:
{% verbatim %}{{ form.body|add_class:"kuyels" }}{% endverbatim %}
<body> @yield('content') <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "{{ config('services.connection_plus.key') }}" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> </body> {{-- in a blade form --}} <textarea name="body" class="kuyels form-control"></textarea>
<body> <%= yield %> <script> window.CONNECTION_PLUS = Object.freeze({ API_KEY: "<%= ENV['CP_API_KEY'] %>" }); </script> <script src="https://nlp.fixbien.com:19476/static/kuyels.js"></script> </body> <%# in a form_with view %> <%= form.text_area :body, class: "kuyels" %>
Dynamic elements & SPA navigation
The SDK auto-enhances every .kuyels element it finds on
page load and watches the DOM for new ones added later via
a MutationObserver — so most SPA work needs zero extra
code.
If you want to enhance an element manually (for example, right after
your framework mounts it), call enhance():
// Enhance one specific element const editor = window.ConnectionPlusEditor.enhance(myTextarea); // Or scan a subtree for every .kuyels element inside it window.ConnectionPlusEditor.enhanceAll(document.getElementById("modal-root")); // Tear down a single editor when its container is removed editor.destroy();
editor_id — up to 32 per connection.
Server API at a glance
The SDK talks to these endpoints for you. Most teams never need to call them directly, but if you're building a custom client, here's the surface in one place.
/dictionary
List personal-dictionary words for the current language.
/dictionary/{word}
Remove a word from the personal dictionary.
Authentication
- GET / DELETE /dictionary — send header
x-api-key: KEY.
Curl examples
# 1. List personal dictionary curl 'https://nlp.fixbien.com:19476/dictionary?language=en-US' \ -H 'x-api-key: YOUR_KEY' # 2. Remove a word curl -X DELETE \ 'https://nlp.fixbien.com:19476/dictionary/hovercraft?language=en-US' \ -H 'x-api-key: YOUR_KEY'
Troubleshooting
Nothing happens when I type
- Check that
window.CONNECTION_PLUS.API_KEYis defined beforekuyels.jsloads. - Open DevTools console and look for
4401or4403WS close codes — those mean bad key or wrong origin. - Confirm your input has the literal class
kuyels(lowercase, no prefix). It can be combined with other classes. - If you serve the page over HTTPS, the SDK must come from HTTPS and connect over WSS. Mixed-content is blocked by the browser.
WebSocket close codes
4401— missing or invalidapi_key.4403— key inactive, wrong type, blocked origin, or your balance is 0.1011— server storage temporarily down; SDK reconnects automatically with exponential backoff.
"Package exhausted" banner
Your key ran out of characters. The socket stays open (typing still
works), but no NLP responses are returned. Top up in the dashboard
— the server will push a package_replenished frame as
soon as the balance is back above 0.