Skip to main content

HTML/CSS/JavaScript Implementation

This example demonstrates how to implement the ZeroinAI Chat Service API using plain HTML, CSS, and JavaScript without any frameworks or build tools.

Project Structure

Create a simple project structure with the following files:

zeroinai-chat-simple/
├── index.html
├── styles.css
├── script.js
└── config.js

Implementation

Configuration (config.js)

Create a config.js file to store your API key and base URL:

// IMPORTANT: In a production environment, never expose your API key in client-side code
// This is for demonstration purposes only. In production, use a backend proxy.
const CONFIG = {
API_URL: 'https://api.zeroinai.com/micro-apps/for-api-providers/chat-service',
API_KEY: 'YOUR_API_KEY_HERE'
};

HTML (index.html)

Create the basic HTML structure for the chat interface:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ZeroinAI Chat Example</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="chat-container">
<div class="chat-header">
<h1>ZeroinAI Chat</h1>
<div class="token-info" id="token-info">Tokens: 0 / 1000</div>
</div>

<div class="chat-messages" id="chat-messages">
<!-- Messages will be added here dynamically -->
</div>

<div class="chat-input">
<input type="text" id="message-input" placeholder="Type your message..." disabled>
<button id="send-button" disabled>Send</button>
</div>

<div class="chat-controls">
<button id="add-tokens-button">Add Tokens</button>
<button id="new-chat-button">New Chat</button>
</div>
</div>

<script src="config.js"></script>
<script src="script.js"></script>
</body>
</html>

CSS (styles.css)

Style the chat interface with CSS:

* {
box-sizing: border-box;
margin: 0;
padding: 0;
}

body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}

.chat-container {
width: 100%;
max-width: 600px;
background-color: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
height: 80vh;
}

.chat-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background-color: #007BFF;
color: white;
}

.chat-header h1 {
font-size: 20px;
font-weight: normal;
}

.token-info {
font-size: 14px;
background-color: rgba(255, 255, 255, 0.2);
padding: 5px 10px;
border-radius: 15px;
}

.chat-messages {
flex: 1;
padding: 20px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 10px;
}

.message {
padding: 10px 15px;
border-radius: 18px;
max-width: 80%;
word-wrap: break-word;
}

.user-message {
align-self: flex-end;
background-color: #007BFF;
color: white;
}

.ai-message {
align-self: flex-start;
background-color: #f0f0f0;
color: #333;
}

.system-message {
align-self: center;
background-color: #f8d7da;
color: #721c24;
font-size: 14px;
padding: 8px 12px;
border-radius: 10px;
text-align: center;
max-width: 90%;
}

.chat-input {
display: flex;
padding: 15px;
border-top: 1px solid #eee;
}

#message-input {
flex: 1;
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 20px;
outline: none;
font-size: 16px;
}

#message-input:focus {
border-color: #007BFF;
}

#message-input:disabled {
background-color: #f9f9f9;
cursor: not-allowed;
}

#send-button {
margin-left: 10px;
padding: 10px 15px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 20px;
cursor: pointer;
}

#send-button:hover {
background-color: #0069d9;
}

#send-button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}

.chat-controls {
display: flex;
justify-content: space-between;
padding: 10px 15px;
background-color: #f8f9fa;
border-top: 1px solid #eee;
}

.chat-controls button {
padding: 8px 12px;
background-color: #f8f9fa;
color: #495057;
border: 1px solid #ddd;
border-radius: 5px;
cursor: pointer;
}

.chat-controls button:hover {
background-color: #e9ecef;
}

.chat-controls button:disabled {
opacity: 0.6;
cursor: not-allowed;
}

JavaScript (script.js)

Implement the chat functionality with JavaScript:

// Chat state
let chatId = null;
let tokenLimit = 1000;
let tokenUsed = 0;
let isLoading = false;

// DOM elements
const chatMessages = document.getElementById('chat-messages');
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');
const tokenInfo = document.getElementById('token-info');
const addTokensButton = document.getElementById('add-tokens-button');
const newChatButton = document.getElementById('new-chat-button');

// Initialize when the page loads
document.addEventListener('DOMContentLoaded', () => {
// Check if we have a stored chat ID
const storedChatId = localStorage.getItem('zeroinai_chat_id');

if (storedChatId) {
chatId = storedChatId;
loadChatHistory(chatId);
} else {
createNewChat();
}

// Set up event listeners
sendButton.addEventListener('click', sendMessage);
messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
sendMessage();
}
});
addTokensButton.addEventListener('click', addMoreTokens);
newChatButton.addEventListener('click', createNewChat);
});

// Create a new chat session
async function createNewChat() {
try {
setLoading(true);
addSystemMessage('Creating new chat session...');

const response = await fetch(`${CONFIG.API_URL}/chats/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': CONFIG.API_KEY
},
body: JSON.stringify({
token_limit: tokenLimit
})
});

if (!response.ok) {
throw new Error(`Error: ${response.status} ${response.statusText}`);
}

const data = await response.json();

// Update chat state
chatId = data.chat_id;
tokenLimit = data.token_limit;
tokenUsed = data.token_used;

// Save chat ID to localStorage
localStorage.setItem('zeroinai_chat_id', chatId);

// Update UI
updateTokenInfo();
clearMessages();
addSystemMessage('Chat session created. You can start chatting!');
enableInput();
} catch (error) {
console.error('Error creating chat:', error);
addSystemMessage('Error creating chat session. Please try again.');
} finally {
setLoading(false);
}
}

// Load chat history
async function loadChatHistory(chatId) {
try {
setLoading(true);
addSystemMessage('Loading chat history...');

const response = await fetch(`${CONFIG.API_URL}/chats/${chatId}/messages/?limit=50&offset=0`, {
method: 'GET',
headers: {
'X-API-Key': CONFIG.API_KEY
}
});

if (!response.ok) {
if (response.status === 404) {
// Chat not found, create a new one
localStorage.removeItem('zeroinai_chat_id');
createNewChat();
return;
}
throw new Error(`Error: ${response.status} ${response.statusText}`);
}

const data = await response.json();

// Clear existing messages
clearMessages();

// Display messages
if (data.items.length === 0) {
addSystemMessage('No messages found. Start a new conversation!');
} else {
data.items.forEach(message => {
addMessage(message.content, message.is_user);
});

// Set token usage (simplified - in a real app you'd get this from the API)
tokenUsed = 100; // Placeholder value
updateTokenInfo();
}

enableInput();
} catch (error) {
console.error('Error loading chat history:', error);
addSystemMessage('Error loading chat history. Please try again.');
} finally {
setLoading(false);
}
}

// Send a message and get AI response
async function sendMessage() {
const content = messageInput.value.trim();

if (!content || !chatId || isLoading) return;

try {
setLoading(true);

// Add user message to UI immediately
addMessage(content, true);
messageInput.value = '';

// Send message to API
const response = await fetch(`${CONFIG.API_URL}/chats/messages/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': CONFIG.API_KEY
},
body: JSON.stringify({
chat_id: chatId,
content: content
})
});

if (response.status === 402) {
// Token limit reached
addSystemMessage('Token limit reached. Adding more tokens...');
await addMoreTokens();
// Retry sending the message
sendMessage();
return;
}

if (!response.ok) {
throw new Error(`Error: ${response.status} ${response.statusText}`);
}

const data = await response.json();

// Add AI response to UI
addMessage(data.content, false);

// Update token usage (simplified)
tokenUsed += 20; // Simplified token counting
updateTokenInfo();
} catch (error) {
console.error('Error sending message:', error);
addSystemMessage('Error sending message. Please try again.');
} finally {
setLoading(false);
}
}

// Add more tokens to the chat
async function addMoreTokens() {
try {
setLoading(true);

const response = await fetch(`${CONFIG.API_URL}/chats/${chatId}/tokens/`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-API-Key': CONFIG.API_KEY
},
body: JSON.stringify({
additional_tokens: 500
})
});

if (!response.ok) {
throw new Error(`Error: ${response.status} ${response.statusText}`);
}

const data = await response.json();

// Update token info
tokenLimit = data.token_limit;
tokenUsed = data.token_used;
updateTokenInfo();

addSystemMessage('Added 500 more tokens to the conversation.');
return true;
} catch (error) {
console.error('Error adding tokens:', error);
addSystemMessage('Error adding tokens. Please try again.');
return false;
} finally {
setLoading(false);
}
}

// Helper functions
function addMessage(content, isUser) {
const messageElement = document.createElement('div');
messageElement.className = `message ${isUser ? 'user-message' : 'ai-message'}`;
messageElement.textContent = content;

chatMessages.appendChild(messageElement);
scrollToBottom();
}

function addSystemMessage(content) {
const messageElement = document.createElement('div');
messageElement.className = 'message system-message';
messageElement.textContent = content;

chatMessages.appendChild(messageElement);
scrollToBottom();
}

function clearMessages() {
chatMessages.innerHTML = '';
}

function scrollToBottom() {
chatMessages.scrollTop = chatMessages.scrollHeight;
}

function updateTokenInfo() {
tokenInfo.textContent = `Tokens: ${tokenUsed} / ${tokenLimit}`;
}

function enableInput() {
messageInput.disabled = false;
sendButton.disabled = false;
messageInput.focus();
}

function setLoading(loading) {
isLoading = loading;
sendButton.disabled = loading;
messageInput.disabled = loading;
addTokensButton.disabled = loading;
newChatButton.disabled = loading;

if (loading) {
sendButton.textContent = 'Sending...';
} else {
sendButton.textContent = 'Send';
}
}

Security Considerations

caution

This example exposes your API key in client-side code, which is not secure for production use. In a real application, you should:

  1. Create a backend proxy server that securely stores your API key
  2. Have your frontend code communicate with your proxy server instead of directly with the ZeroinAI API
  3. Implement proper authentication and authorization in your proxy server

Running the Example

To run this example:

  1. Create the four files (index.html, styles.css, script.js, and config.js) with the code provided above
  2. Replace YOUR_API_KEY_HERE in config.js with your actual ZeroinAI API key
  3. Open index.html in a web browser

Key Features

  • Simple implementation using only HTML, CSS, and vanilla JavaScript
  • No dependencies or build tools required
  • Persistent chat sessions using localStorage
  • Token management with automatic top-up
  • Responsive design that works on mobile and desktop

Limitations

This simple implementation has some limitations:

  1. API key is exposed in client-side code (not secure for production)
  2. Limited error handling and retry logic
  3. Simplified token usage tracking
  4. No offline support or message queuing

For a production application, consider using a framework like React, Vue, or Angular, and implementing a secure backend proxy server.