
How to Build an AI Prompt Using CFML and/or cfScript (Part 1)
If you’re a ColdFusion developer curious about integrating AI into your projects, this quick-start guide is for you. In this first post of the series, we’ll show how to create a basic AI prompt using CFML and the OpenAI REST API. This version uses the gpt-4
model, styled with Bootstrap 5, and is designed as a simple web form that sends a user prompt and displays the AI’s response.
We’re keeping it lightweight and easy to understand, with no database or persistent storage involved. Just a single index.cfm
file that includes both the form and the logic for making the API call. Later parts of this series will expand the features—but for now, this is your foundational example.
Full Code Example
<!--- index.cfm --->
<cfoutput>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tica AI Demo</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
<style>
body { padding-top: 4rem; }
pre { background-color: #f8f9fa; padding: 1rem; border-radius: 6px; }
.btn-primary { background-color: #e25425; border: 5px solid #e25425; }
.btn-primary:hover { background-color: #f68924; border: 5px solid #f68924; }
.bg-primary { background-color: #272c69 !important; }
</style>
</head>
<body>
<div class="container px-5" style="max-width: 800px">
<h1 class="mb-4 text-center">Tica AI <sup class="badge text-bg-warning text-light fs-6">BETA</sup></h1>
<form method="post" class="mb-4">
<div class="mb-3">
<label for="userPrompt" class="form-label">What can I help you with?</label>
<textarea name="userPrompt" id="userPrompt" rows="4" class="form-control" required>#htmlEditFormat(form.userPrompt ?: '')#</textarea>
</div>
<button type="submit" class="btn btn-primary">Ask Tica <i class="bi bi-send-fill"></i></button>
</form>
<cfif structKeyExists(form, "userPrompt")>
<cfset apiKey = "sk-xxxxxxxx" />
<cfset userPrompt = trim(form.userPrompt)>
<div id="spinner" class="text-center mb-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="mt-2">Thinking...</p>
</div>
<cfscript>
requestBody = {
"model": "gpt-4",
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": userPrompt }
]
};
cfhttp(
url = "https://api.openai.com/v1/chat/completions",
method = "post",
result = "openaiResponse"
) {
cfhttpparam(type="header", name="Content-Type", value="application/json");
cfhttpparam(type="header", name="Authorization", value="Bearer " & apiKey);
cfhttpparam(type="body", value=serializeJSON(requestBody));
}
</cfscript>
<div class="card mb-5">
<div class="card-header bg-primary text-white">Tica Says</div>
<div class="card-body">
<cfif openaiResponse.statusCode is '200 OK'>
<cfset jsonResponse = deserializeJSON(openaiResponse.fileContent)>
<cfset reply = jsonResponse.choices[1].message.content>
<pre>#htmlEditFormat(reply)#</pre>
<cfelse>
<div class="alert alert-danger">
<strong>Error:</strong> #openaiResponse.statusCode#<br>
<pre>#htmlEditFormat(openaiResponse.fileContent)#</pre>
</div>
</cfif>
</div>
</div>
<script>
document.getElementById("spinner")?.remove();
</script>
</cfif>
</div>
</body>
</html>
</cfoutput>
What’s Next?
This is just the beginning. In Part 2, we’ll add features like persistent chat history, model switching, and maybe even voice input. You’ll see how powerful and flexible CFML can be when combined with modern APIs like OpenAI’s. Stay tuned—and feel free to adapt this code for your own experiments!
About the Author


If you’re a ColdFusion developer curious about integrating AI into your projects, this quick-start guide is for you. In this first post of the series, we’ll show how to create a basic AI prompt using CFML and the OpenAI REST API. This version uses the gpt-4
model, styled with Bootstrap 5, and is designed as a simple web form that sends a user prompt and displays the AI’s response.
We’re keeping it lightweight and easy to understand, with no database or persistent storage involved. Just a single index.cfm
file that includes both the form and the logic for making the API call. Later parts of this series will expand the features—but for now, this is your foundational example.
Full Code Example
<!--- index.cfm --->
<cfoutput>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tica AI Demo</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
<style>
body { padding-top: 4rem; }
pre { background-color: #f8f9fa; padding: 1rem; border-radius: 6px; }
.btn-primary { background-color: #e25425; border: 5px solid #e25425; }
.btn-primary:hover { background-color: #f68924; border: 5px solid #f68924; }
.bg-primary { background-color: #272c69 !important; }
</style>
</head>
<body>
<div class="container px-5" style="max-width: 800px">
<h1 class="mb-4 text-center">Tica AI <sup class="badge text-bg-warning text-light fs-6">BETA</sup></h1>
<form method="post" class="mb-4">
<div class="mb-3">
<label for="userPrompt" class="form-label">What can I help you with?</label>
<textarea name="userPrompt" id="userPrompt" rows="4" class="form-control" required>#htmlEditFormat(form.userPrompt ?: '')#</textarea>
</div>
<button type="submit" class="btn btn-primary">Ask Tica <i class="bi bi-send-fill"></i></button>
</form>
<cfif structKeyExists(form, "userPrompt")>
<cfset apiKey = "sk-xxxxxxxx" />
<cfset userPrompt = trim(form.userPrompt)>
<div id="spinner" class="text-center mb-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="mt-2">Thinking...</p>
</div>
<cfscript>
requestBody = {
"model": "gpt-4",
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": userPrompt }
]
};
cfhttp(
url = "https://api.openai.com/v1/chat/completions",
method = "post",
result = "openaiResponse"
) {
cfhttpparam(type="header", name="Content-Type", value="application/json");
cfhttpparam(type="header", name="Authorization", value="Bearer " & apiKey);
cfhttpparam(type="body", value=serializeJSON(requestBody));
}
</cfscript>
<div class="card mb-5">
<div class="card-header bg-primary text-white">Tica Says</div>
<div class="card-body">
<cfif openaiResponse.statusCode is '200 OK'>
<cfset jsonResponse = deserializeJSON(openaiResponse.fileContent)>
<cfset reply = jsonResponse.choices[1].message.content>
<pre>#htmlEditFormat(reply)#</pre>
<cfelse>
<div class="alert alert-danger">
<strong>Error:</strong> #openaiResponse.statusCode#<br>
<pre>#htmlEditFormat(openaiResponse.fileContent)#</pre>
</div>
</cfif>
</div>
</div>
<script>
document.getElementById("spinner")?.remove();
</script>
</cfif>
</div>
</body>
</html>
</cfoutput>
What’s Next?
This is just the beginning. In Part 2, we’ll add features like persistent chat history, model switching, and maybe even voice input. You’ll see how powerful and flexible CFML can be when combined with modern APIs like OpenAI’s. Stay tuned—and feel free to adapt this code for your own experiments!
About the Author

