dmtdura / chatlink
Full chatbot backend and embeddable widget: native Laravel, or standalone PHP without Laravel. You do not need a separate service.
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.8|^8.0
- illuminate/console: ^11.0|^12.0|^13.0
- illuminate/database: ^11.0|^12.0|^13.0
- illuminate/filesystem: ^11.0|^12.0|^13.0
- illuminate/http: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- symfony/finder: ^7.0|^8.0
Requires (Dev)
- orchestra/testbench: 11.0
- phpunit/phpunit: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Embeddable side-panel chat widget. Each package is a full backend; Python, PHP, or Node is enough.
Contributions are welcome. See CONTRIBUTING.md.
Packages
| Package | Install | What it does |
|---|---|---|
packages/pip |
pip install dmtdura-chatlink |
FastAPI backend, CLI, vector store |
packages/composer |
composer require dmtdura/chatlink |
Native Laravel backend and @chatbot, or a standalone PHP server without Laravel |
packages/node |
npm install dmtdura-chatlink |
Standalone server, Express, or Next.js |
packages/composer ships two modes in one package: if Laravel is present, ChatbotServiceProvider loads automatically; if not, vendor/bin/chatbot serve starts the same API with PHP's built-in server. Assistant, knowledge, and OpenAI logic (src/Core/) are the same classes in both modes — only the config source (Laravel config / .env) and storage (Eloquent / SQLite) differ.
Not published yet. The release procedure is documented (releasing.md), but the commands above will not work until the first
v*tag. Until then, install from git: usage.md.
All three implement the spec/api.md contract. widget.js lives in shared/; python scripts/sync_assets.py copies it into the packages.
Repository layout
.
├── packages/
│ ├── pip/ Python / FastAPI backend
│ ├── composer/ PHP backend: Laravel adapter + standalone mode
│ │ ├── src/Core/ framework-agnostic core (both modes)
│ │ ├── src/Laravel/ Laravel-only bindings
│ │ ├── src/Plain/ standalone PHP bindings
│ │ ├── public/index.php standalone front controller
│ │ └── bin/chatbot standalone CLI (init | serve | vectors)
│ └── node/ Node backend
├── shared/ widget.js and knowledge stubs (single source)
├── spec/ shared API contract
├── scripts/ asset sync
├── composer.json dmtdura/chatlink manifest (Packagist looks at the root)
├── phpunit.xml PHP package test config
├── usage.md install and usage
├── CITATION.cff citation (v1.0.0)
├── LICENSE CC BY 4.0
├── CC-BY-4.0 full license text
└── .env.example environment template
The Composer manifest is at the root, with sources under packages/composer/: Packagist reads a repository directly and looks for composer.json only at the root. export-ignore rules in .gitattributes keep npm and Python sources out of the Composer archive.
Quick start
Laravel:
composer require dmtdura/chatlink php artisan chatbot:install php artisan migrate
Add @chatbot before </body> in your layout.
Plain PHP (no Laravel — installing the package does not pull in any Illuminate/Laravel dependency):
composer require dmtdura/chatlink vendor/bin/chatbot init vendor/bin/chatbot serve
<script src="http://127.0.0.1:8000/chatbot/widget.js"></script>
The widget infers its API base from the script's own src, so no data-api attribute is needed.
Python:
pip install dmtdura-chatlink dmtdura-chatlink init dmtdura-chatlink serve
<script src="http://127.0.0.1:8000/widget.js"></script>
Node:
npm install dmtdura-chatlink npx dmtdura-chatlink init npx dmtdura-chatlink serve
How knowledge works
Packages do not ship your live content. The starter files are a fictional sample brand (Akne Lab). Replace them with your own; use *.local.txt for private notes (gitignored).
init / chatbot:install scaffolds that folder in your project. It never overwrites files that already exist there; to start a separate, custom-named folder instead, pass --knowledge-dir <name> (pip / node / plain PHP):
your-project/
├── .env
├── data/
│ ├── prompts/assistant_instructions.txt
│ └── knowledge/
│ ├── README.md
│ ├── about/
│ ├── faq/
│ └── topics/
└── chatbot.db # created after pip/node serve
The layout is domain-agnostic: nest as many folders as you want under topics/.
The file name is passed to the assistant as a heading.
If you use a vector store, re-upload after you change files:
dmtdura-chatlink vectors upload # pip / node vendor/bin/chatbot vectors upload # composer, plain PHP php artisan chatbot:vector-upload # composer, Laravel
Running with your own values
.env variables control all behaviour. Do not commit keys.
OPENAI_API_KEY= OPENAI_MODEL=gpt-4.1-mini OPENAI_VECTOR_STORE_ID= CHATBOT_PROMPT_PATH=data/prompts/assistant_instructions.txt CHATBOT_KNOWLEDGE_DIR=data/knowledge CHATBOT_WIDGET_TITLE=Your company CHATBOT_WIDGET_ACCENT="#0f6b5c" CHATBOT_WIDGET_POSITION=bottom-right CHATBOT_HISTORY_MESSAGES=10 CHATBOT_RATE_LIMIT_PER_MINUTE=20
Every visible widget string comes from .env; you do not need to change code
to ship in another language.
All variables and API endpoints: usage.md · spec/api.md
Development
pip install -e "packages/pip[dev]" pytest packages/pip composer install && vendor/bin/phpunit # composer package (Laravel + Plain), from the root cd packages/node && npm test python scripts/sync_assets.py # after widget.js or stubs change
packages/composer/tests/Plain/* is plain PHPUnit and never boots Laravel — proof that standalone mode is framework-agnostic.
Releases: releasing.md.
Community
Contributions are welcome.
License and citation
Software is distributed under CC BY 4.0. Cite with CITATION.cff (v1.0.0). Details: NOTICE.