ViewComfy API Rules
You are an expert in Python, FastAPI integrations and web app development. You are tasked with helping integrate the ViewComfy API into web applications using Python.
The ViewComfy API is a serverless API built using the FastAPI framework that can run custom ComfyUI workflows. The Python version makes requests using the httpx library,
When implementing the API, remember that the first time you call it, you might experience a cold start. Moreover, generation times can vary between workflows; some might be less than 2 seconds, while some might take several minutes.
When calling the API, the params object can't be empty. If nothing else is specified, change the seed value.
The data comes back from the API with the following format: { "prompt_id": "string", # Unique identifier for the prompt "status": "string", # Current execution status "completed": bool, # Whether execution is complete "execution_time_seconds": float, # Time taken to execute "prompt": dict, # Original prompt configuration "outputs": [ # List of output files (optional) { "filename": "string", # Name of the output file "content_type": "string", # MIME type of the file "data": "string", # Base64 encoded file content "size": int # File size in bytes }, # ... potentially multiple output files ] }
ViewComfy documentation:
================================================
FILE: other_resources/guide_to_setting_up_and_using_ViewComfy_API.md
================================================
Deploying your workflow
The first thing you will need to do is to deploy your ComfyUI workflow on your ViewComfy dashboard using the workflow_api.json file.
Calling the workflow with the API
The ViewComfy API is a REST API that can be called with a standard POST request but also supports streaming responses via Server-Sent Events. This second option allows for real-time tracking of the ComfyUI logs.
Getting your API keys
In order to use your API endpoint, you will first need to create your API keys from the ViewComfy dashboard.
2. Extracting your workflow parameters
Before setting up the request is to identify the parameters in your workflow. This is done by using ViewComfy_API/Python/workflow_parameters_maker.py from the example API code to flatten your workflow_api.json.
The flattened json file should look like this:
{
"_3-node-class_type-info": "KSampler",
"3-inputs-cfg": 6,
…  
"_6-node-class_type-info": "CLIP Text Encode (Positive Prompt)",  
"6-inputs-clip": [  
    "38",  
    0  
],  
"6-inputs-text": "A woman raising her head with hair blowing in the wind",  
…  
"_52-node-class_type-info": "Load Image",  
"52-inputs-image": "<path_to_my_image>",  
…  
}
This dictionary contains all the parameters in your workflow. The key for each parameter contains the node id from your workflow_api.json file, whether it is an input, and the parameter’s input name. Keys that start with “_” are just there to give you context on the node corresponding to id, they are not parameters.
In this example, the first key-value pair shows that node 3 is the KSampler and that “3-inputs-cfg” sets its corresponding cfg value.
**3. Updating the script with your parameter**
First thing to do is to copy the ViewComfy endpoint from your dashboard and set it to view_comfy_api_url. You should also get the “Client ID” and “Client Secret” you made earlier, and set the client_id and client_secret values:
view_comfy_api_url = "<Your_ViewComfy_endpoint>"
client_id = "<Your_ViewComfy_client_id>"
client_secret = "<Your_ViewComfy_client_secret>"
You can then set the parameters using the keys from the json file you created in the previous step. In this example, we will change the prompt and the input image:
params = {}
params["6-inputs-text"] = "A flamingo dancing on top of a server in a pink universe, masterpiece, best quality, very aesthetic"
params["52-inputs-image"] = open("/home/gbieler/GitHub/API_tests/input_img.png", "rb")
**4. Calling the API**
Once you are done adding your parameters to ViewComfy_API/Python/main.py, you can call the API by running:
python main.py
This will send your parameters to ViewComfy_API/Python/api.py where all the functions to call the API and handle the outputs are stored.
By default the script runs the “infer_with_logs” function which returns the generation logs from ComfyUI via a streaming response. If you would rather call the API via a standard POST request, you can use “infer” instead.
The result object returned by the API will contain the workflow outputs as well as the generation details.
Your outputs will automatically be saved in your working directory.
================================================
FILE: ViewComfy_API/README.MD
================================================
# ViewComfy API Example
## API
All the functions to call the API and handle the responses are in the api file (api.py). The main file (main.py) takes in the parameters that are specific from your workflow and in most cases will be the only file you need to edit.
#### The API file has two endpoints:
- infer: classic request-response endpoint where you wait for your request to finish before getting results back. 
- infer_with_logs: receives real-time updates with the ComfyUI logs (eg. progress bar). To make use of this endpoint, you need to pass a function that will be called each time a log message is received.
The endpoints can also take a workflow_api.json as a parameter. This is useful if you want to run a different workflow than the one you used when deploying.
### Get your API parameters
To extract all the parameters from your workflow_api.json, you can run the workflow_api_parameter_creator function. This will create a dictionary with all of the parameters inside the workflow.
```python
python workflow_parameters_maker.py --workflow_api_path "<Path to your workflow_api.json file>"
Running the example
Install the dependencies:
pip install -r requirements.txt
Add your endpoint and set your API keys:
Change the view_comfy_api_url value inside main.py to the ViewComfy endpoint from your ViewComfy Dashboard. Do the same with the "client_id" and "client_secret" values using your API keys (you can also get them from your dashboard). If you want, you can change the parameters of the workflow inside main.py at the same time.
Call the API:
python main.py
Using the API with a different workflow
You can overwrite the default workflow_api.json when sending a request. Be careful if you need to install new node packs to run the new workflow. Having too many custom node packages can create some issues between the Python packages. This can increase ComfyUI start up time and in some cases break the ComfyUI installation.
To use an updated workflow (that works with your deployment) with the API, you can send the new workflow_api.json as a parameter by changing the override_workflow_api_path value. For example, using python:
override_workflow_api_path = "<path_to_your_new_workflow_api_file>"
================================================ FILE: ViewComfy_API/example_workflow/workflow_api(example).json
{ "3": { "inputs": { "seed": 268261030599666, "steps": 20, "cfg": 6, "sampler_name": "uni_pc", "scheduler": "simple", "denoise": 1, "model": [ "56", 0 ], "positive": [ "50", 0 ], "negative": [ "50", 1 ], "latent_image": [ "50", 2 ] }, "class_type": "KSampler", "_meta": { "title": "KSampler" } }, "6": { "inputs": { "text": "A flamingo dancing on top of a server in a pink universe, masterpiece, best quality, very aesthetic", "clip": [ "38", 0 ] }, "class_type": "CLIPTextEncode", "_meta": { "title": "CLIP Text Encode (Positive Prompt)" } }, "7": { "inputs": { "text": "Overexposure, static, blurred details, subtitles, paintings, pictures, still, overall gray, worst quality, low quality, JPEG compression residue, ugly, mutilated, redundant fingers, poorly painted hands, poorly painted faces, deformed, disfigured, deformed limbs, fused fingers, cluttered background, three legs, a lot of people in the background, upside down", "clip": [ "38", 0 ] }, "class_type": "CLIPTextEncode", "_meta": { "title": "CLIP Text Encode (Negative Prompt)" } },
...
"52": { "inputs": { "image": "SMT54Y6XHY1977QPBESY72WSR0.jpeg", "upload": "image" }, "class_type": "LoadImage", "_meta": { "title": "Load Image" } },
...
}
================================================ FILE: ViewComfy_API/Python/api.py
import json from io import BufferedReader from typing import Any, Callable, Dict, List import httpx
class FileOutput: """Represents a file output with its content encoded in base64"""
def __init__(self, filename: str, content_type: str, data: str, size: int):
    """
    Initialize a FileOutput object.
    Args:
        filename (str): Name of the output file
        content_type (str): MIME type of the file
        data (str): Base64 encoded file content
        size (int): Size of the file in bytes
    """
    self.filename = filename
    self.content_type = content_type
    self.data = data
    self.size = size
class PromptResult: def init( self, prompt_id: str, status: str, completed: bool, execution_time_seconds: float, prompt: Dict, outputs: List[Dict] | None = None, ): """ Initialize a PromptResult object.
    Args:
        prompt_id (str): Unique identifier for the prompt
        status (str): Current status of the prompt execution
        completed (bool): Whether the prompt execution is complete
        execution_time_seconds (float): Time taken to execute the prompt
        prompt (Dict): The original prompt configuration
        outputs (List[Dict], optional): List of output file data. Defaults to empty list.
    """
    self.prompt_id = prompt_id
    self.status = status
    self.completed = completed
    self.execution_time_seconds = execution_time_seconds
    self.prompt = prompt
    # Initialize outputs as FileOutput objects
    self.outputs = []
    if outputs:
        for output_data in outputs:
            self.outputs.append(
                FileOutput(
                    filename=output_data.get("filename", ""),
                    content_type=output_data.get("content_type", ""),
                    data=output_data.get("data", ""),
                    size=output_data.get("size", 0),
                )
            )
class ComfyAPIClient: def init( self, *, infer_url: str | None = None, client_id: str | None = None, client_secret: str | None = None, ): """ Initialize the ComfyAPI client with the server URL.
    Args:
        base_url (str): The base URL of the API server
    """
    if infer_url is None:
        raise Exception("infer_url is required")
    self.infer_url = infer_url
    if client_id is None:
        raise Exception("client_id is required")
    if client_secret is None:
        raise Exception("client_secret is required")
    self.client_id = client_id
    self.client_secret = client_secret
async def infer(
    self,
    *,
    data: Dict[str, Any],
    files: list[tuple[str, BufferedReader]] = [],
) -> Dict[str, Any]:
    """
    Make a POST request to the /api/infer-files endpoint with files encoded in form data.
    Args:
        data: Dictionary of form fields (logs, params, etc.)
        files: Dictionary mapping file keys to tuples of (filename, content, content_type)
               Example: {"composition_image": ("image.jpg", file_content, "image/jpeg")}
    Returns:
        Dict[str, Any]: Response from the server
    """
    async with httpx.AsyncClient() as client:
        try:
            response = await client.post(
                self.infer_url,
                data=data,
                files=files,
                timeout=httpx.Timeout(2400.0),
                follow_redirects=True,
                headers={
                    "client_id": self.client_id,
                    "client_secret": self.client_secret,
                },
            )
            if response.status_code == 201:
                return response.json()
            else:
                error_text = response.text
                raise Exception(
                    f"API request failed with status {response.status_code}: {error_text}"
                )
        except httpx.HTTPError as e:
            raise Exception(f"Connection error: {str(e)}")
        except Exception as e:
            raise Exception(f"Error during API call: {str(e)}")
async def consume_event_source(
    self, *, response, logging_callback: Callable[[str], None]
) -> Dict[str, Any] | None:
    """
    Process a streaming Server-Sent Events (SSE) response.
    Args:
        response: An active httpx streaming response object
    Returns:
        List of parsed event objects
    """
    current_data = ""
    current_event = "message"  # Default event type
    prompt_result = None
    # Process the response as it streams in
    async for line in response.aiter_lines():
        line = line.strip()
        if prompt_result:
            break
        # Empty line signals the end of an event
        if not line:
            if current_data:
                try:
                    if current_event in ["log_message", "error"]:
                        logging_callback(f"{current_event}: {current_data}")
                    elif current_event == "prompt_result":
                        prompt_result = json.loads(current_data)
                    else:
                        print(
                            f"Unknown event: {current_event}, data: {current_data}"
                        )
                except json.JSONDecodeError as e:
                    print("Invalid JSON: ...")
                    print(e)
                # Reset for next event
                current_data = ""
                current_event = "message"
            continue
        # Parse SSE fields
        if line.startswith("event:"):
            current_event = line[6:].strip()
        elif line.startswith("data:"):
            current_data = line[5:].strip()
        elif line.startswith("id:"):
            # Handle event ID if needed
            pass
        elif line.startswith("retry:"):
            # Handle retry directive if needed
            pass
    return prompt_result
async def infer_with_logs(
    self,
    *,
    data: Dict[str, Any],
    logging_callback: Callable[[str], None],
    files: list[tuple[str, BufferedReader]] = [],
) -> Dict[str, Any] | None:
    if data.get("logs") is not True:
        raise Exception("Set the logs to True for streaming the process logs")
    async with httpx.AsyncClient() as client:
        try:
            async with client.stream(
                "POST",
                self.infer_url,
                data=data,
                files=files,
                timeout=24000,
                follow_redirects=True,
                headers={
                    "client_id": self.client_id,
                    "client_secret": self.client_secret,
                },
            ) as response:
                if response.status_code == 201:
                    # Check if it's actually a server-sent event stream
                    if "text/event-stream" in response.headers.get(
                        "content-type", ""
                    ):
                        prompt_result = await self.consume_event_source(
                            response=response, logging_callback=logging_callback
                        )
                        return prompt_result
                    else:
                        # For non-SSE responses, read the content normally
                        raise Exception(
                            "Set the logs to True for streaming the process logs"
                        )
                else:
                    error_response = await response.aread()
                    error_data = json.loads(error_response)
                    raise Exception(
                        f"API request failed with status {response.status_code}: {error_data}"
                    )
        except Exception as e:
            raise Exception(f"Error with streaming request: {str(e)}")
def parse_parameters(params: dict): """ Parse parameters from a dictionary to a format suitable for the API call.
Args:
    params (dict): Dictionary of parameters
Returns:
    dict: Parsed parameters
"""
parsed_params = {}
files = []
for key, value in params.items():
    if isinstance(value, BufferedReader):
        files.append((key, value))
    else:
        parsed_params[key] = value
return parsed_params, files
async def infer( *, params: Dict[str, Any], api_url: str, override_workflow_api: Dict[str, Any] | None = None, client_id: str, client_secret: str, ): """ Make an inference with real-time logs from the execution prompt
Args:
    api_url (str): The URL to send the request to
    params (dict): The parameter to send to the workflow
    override_workflow_api (dict): Optional override the default workflow_api of the deployment
Returns:
    PromptResult: The result of the inference containing outputs and execution details
"""
client = ComfyAPIClient(
    infer_url=api_url,
    client_id=client_id,
    client_secret=client_secret,
)
params_parsed, files = parse_parameters(params)
data = {
    "logs": False,
    "params": json.dumps(params_parsed),
    "workflow_api": json.dumps(override_workflow_api)
    if override_workflow_api
    else None,
}
# Make the API call
result = await client.infer(data=data, files=files)
return PromptResult(**result)
async def infer_with_logs( *, params: Dict[str, Any], logging_callback: Callable[[str], None], api_url: str, override_workflow_api: Dict[str, Any] | None = None, client_id: str, client_secret: str, ): """ Make an inference with real-time logs from the execution prompt
Args:
    api_url (str): The URL to send the request to
    params (dict): The parameter to send to the workflow
    override_workflow_api (dict): Optional override the default workflow_api of the deployment
    logging_callback (Callable[[str], None]): The callback function to handle logging messages
Returns:
    PromptResult: The result of the inference containing outputs and execution details
"""
client = ComfyAPIClient(
    infer_url=api_url,
    client_id=client_id,
    client_secret=client_secret,
)
params_parsed, files = parse_parameters(params)
data = {
    "logs": True,
    "params": json.dumps(params_parsed),
    "workflow_api": json.dumps(override_workflow_api)
    if override_workflow_api
    else None,
}
# Make the API call
result = await client.infer_with_logs(
    data=data,
    files=files,
    logging_callback=logging_callback,
)
if result:
    return PromptResult(**result)
```
FILE: ViewComfy_API/Python/main.py
```python
import asyncio import base64 import json import os from api import infer, infer_with_logs
async def api_examples():
view_comfy_api_url = "<Your_ViewComfy_endpoint>"
client_id = "<Your_ViewComfy_client_id>"
client_secret = "<Your_ViewComfy_client_secret>"
override_workflow_api_path = None # Advanced feature: overwrite default workflow with a new one
# Set parameters
params = {}
params["6-inputs-text"] = "A cat sorcerer"
params["52-inputs-image"] = open("input_folder/input_img.png", "rb")
override_workflow_api = None
if  override_workflow_api_path:
    if os.path.exists(override_workflow_api_path):  
        with open(override_workflow_api_path, "r") as f:
            override_workflow_api = json.load(f)
    else:
        print(f"Error: {override_workflow_api_path} does not exist")
def logging_callback(log_message: str):
    print(log_message)
# Call the API and wait for the results
# try:
#     prompt_result = await infer(
#         api_url=view_comfy_api_url,
#         params=params,
#         client_id=client_id,
#         client_secret=client_secret,
#     )
# except Exception as e:
#     print("something went wrong calling the api")
#     print(f"Error: {e}")
#     return
# Call the API and get the logs of the execution in real time
# you can use any function that you want
try:
    prompt_result = await infer_with_logs(
        api_url=view_comfy_api_url,
        params=params,
        logging_callback=logging_callback,
        client_id=client_id,
        client_secret=client_secret,
        override_workflow_api=override_workflow_api,
    )
except Exception as e:
    print("something went wrong calling the api")
    print(f"Error: {e}")
    return
if not prompt_result:
    print("No prompt_result generated")
    return
for file in prompt_result.outputs:
    try:
        # Decode the base64 data before writing to file
        binary_data = base64.b64decode(file.data)
        with open(file.filename, "wb") as f:
            f.write(binary_data)
        print(f"Successfully saved {file.filename}")
    except Exception as e:
        print(f"Error saving {file.filename}: {str(e)}")
if name == "main": asyncio.run(api_examples())
```
================================================ 
FILE: ViewComfy_API/Python/requirements.txt
```
httpx==0.28.1
```
================================================ 
FILE: ViewComfy_API/Python/workflow_api_parameter_creator.py
```python
from typing import Dict, Any
def workflow_api_parameters_creator(workflow: Dict[str, Dict[str, Any]]) -> Dict[str, Any]: """ Flattens the workflow API JSON structure into a simple key-value object
Args:
    workflow: The workflow API JSON object
Returns:
    A flattened object with keys in the format "nodeId-inputs-paramName" or "nodeId-class_type-info"
"""
flattened: Dict[str, Any] = {}
# Iterate through each node in the workflow
for node_id, node in workflow.items():
    # Add the class_type-info key, preferring _meta.title if available
    class_type_info = node.get("_meta", {}).get("title") or node.get("class_type")
    flattened[f"_{node_id}-node-class_type-info"] = class_type_info
    
    # Process all inputs
    if "inputs" in node:
        for input_key, input_value in node["inputs"].items():
            flattened[f"{node_id}-inputs-{input_key}"] = input_value
return flattened
""" Example usage:
import json
with open('workflow_api.json', 'r') as f: workflow_json = json.load(f)
flattened = create_workflow_api_parameters(workflow_json) print(flattened) """
```
================================================ 
FILE: ViewComfy_API/Python/workflow_parameters_maker.py
```python
import json from workflow_api_parameter_creator import workflow_api_parameters_creator import argparse
parser = argparse.ArgumentParser(description='Process workflow API parameters') parser.add_argument('--workflow_api_path', type=str, required=True, help='Path to the workflow API JSON file')
Parse arguments
args = parser.parse_args()
with open(args.workflow_api_path, 'r') as f: workflow_json = json.load(f)
parameters = workflow_api_parameters_creator(workflow_json)
with open('workflow_api_parameters.json', 'w') as f: json.dump(parameters, f, indent=4)
```
Created: 6/16/2025
Keywords: text snippets, slack for ai prompts, slack for ai, AI consulting, AI Cheat Tool, AI Cheat Tool for developers, AI Cheat Tool for AI, AI Cheat Tool for ChatGPT, chatgpt prompt generator, AI Cheat Tool for email, AI Cheat Tool for text, AI Cheat Tool for keyboard shortcuts, AI Cheat Tool for text expansion, AI Cheat Tool for text snippets, AI Cheat Tool for text replacement, AI Cheating Tool, AI Cheating Tool for developers, AI Cheating Tool for AI, AI Cheating Tool for ChatGPT, AI Cheating Tool for email, AI Cheating Tool for text, AI Cheating Tool for keyboard shortcuts, prompt cheating, AI prompt engineering, AI context engineering, context engineering, ai prompt manager, AI prompt manager, AI prompt management, ai consulting, prompt engineering consulting, generative ai consulting, ai implementation services, llm integration consultants, ai strategy for enterprises, enterprise ai transformation, ai prompt optimization, large language model consulting, ai training for teams, ai workflow automation, build ai knowledge base, llm prompt management, ai prompt infrastructure, ai adoption consulting, enterprise ai onboarding, custom ai workflow design, ai integration for dev teams, ai productivity tools, team prompt collaboration, github gists, github snippets, github code snippets, github code snippets automation, github, text expansion, text automation, snippet manager, code snippets, team collaboration tools, shared snippets, snippet sharing, keyboard shortcuts, productivity tools, workflow automation, AI-powered productivity, snippet tool for teams, team knowledge base, AI text completion, text expander for teams, snippet collaboration, multi-platform productivity, custom keyboard shortcuts, snippet sharing platform, collaborative snippet management, knowledge base automation, team productivity software, business productivity tools, snippet management software, quick text input, macOS productivity apps, Windows productivity tools, Linux productivity tools, cloud-based snippets, cross-platform snippets, team workspace tools, workflow enhancement tools, automation tools for teams, text automation software, team knowledge sharing, task automation, integrated team tools, real-time collaboration, AI for team productivity, business text automation, time-saving tools, clipboard manager, multi-device clipboard, keyboard shortcut manager, team communication tools, project management integration, productivity boost AI, text snippet sharing, text replacement software, text management tools, efficient team collaboration, AI workspace tools, modern productivity apps, custom text automation, digital workspace tools, collaborative workspaces, cloud productivity tools, streamline team workflows, smart text management, snippets AI app, snippet management for teams, shared knowledge platforms, team-focused text automation, team productivity platform, AI text expansion tools, snippet taking app, note taking app, note taking software, note taking tools, note taking app for teams, note taking app for developers, note taking app for AI, note taking app for ChatGPT, snippet software, snippet tools, snippet app for teams, snippet app for developers, snippet app for AI, snippet app for ChatGPT, AI agent builder, AI agent snippets, AI agent prompts, prompt management, prompt engineering, ChatGPT snippets, ChatGPT prompts, AI prompt optimization, AI-powered prompts, prompt libraries for AI, prompt sharing for ChatGPT, GPT productivity tools, AI assistant snippets, ChatGPT integrations, custom AI prompts, AI agent workflows, machine learning snippets, automated AI prompts, AI workflow automation, collaborative AI prompts, personalized AI agents, text snippets for ChatGPT, AI prompt creation tools, AI code snippet manager, GPT-4 text automation, AI-powered writing assistants, AI tools for developers, AI agent integrations, developer prompt snippets, AI text generation workflows, AI-enhanced productivity, GPT prompt sharing tools, team collaboration for AI, openAI integrations, text automation for AI teams, AI-powered collaboration tools, GPT-4 team tools, AI-driven text expanders, AI-driven productivity solutions, AI agent for email writing, AI agent for text expansion, AI agent for text automation, AI agent for text snippets, AI agent for text replacement, AI agent for keyboard shortcuts, AI Agent Developer, Prompt engineering, Machine Learning Engineer, AI Engineer, Customer Support, Code snippets for developers, Recruiting, AI agent for automation, AI agent for AI automation, AI agent for ChatGPT automation, AI agent for email automation, electron app for snippets, desktop snippet manager, code snippet organization, AI prompt repository, intelligent text expansion, vibe coding, Claude cli ai prompts, prompt optimizer, buy prompts, sell prompts, snippets store, sell scripts, buy scripts, buy python scripts, scraping scripts, AI prompt marketplace, ChatGPT prompt marketplace, best AI prompts, best ChatGPT prompts, AI prompt database, AI prompt packs, AI prompt bundles, GPT prompt marketplace, prompt engineering masterclass, prompt engineering certification, prompt engineering course, ChatGPT prompt store, AI prompt store, prompt monetization, sell AI prompts, buy AI prompts, prompt marketplace platform, AI prompt plugins, Claude prompt marketplace, AI prompt subscription, Custom GPT, real-time prompt collaboration, developer workflow optimization, team prompt library, knowledge management for developers, code snippet search, searchable code library, reusable code blocks, prompt engineering tools, prompt template management, collaborative coding, cross-team knowledge sharing, code snippet versioning, AI prompt templates, technical documentation tools, developer productivity suite, team snippet repository, AI prompt history, snippet synchronization, cloud snippet backup, markdown snippet support, syntax highlighting for snippets, code categorization, programming language snippets, language-specific code templates, contextual code suggestions, snippets with AI integration, command palette for snippets, code snippet folder organization, team snippet discovery, private and public snippets, enterprise code management, team codebase documentation, prompt engineering best practices, Vibe Coding, Vibe Coding for developers, Vibe Coding for AI, Vibe Coding for ChatGPT, Vibe Coding for email, Vibe Coding for text, Vibe Coding for keyboard shortcuts, Vibe Coding for text expansion, Vibe Coding for text snippets, Vibe Coding for text replacement, free prompt generator, ai prompt generator, prompt generator, promptlayer, promptimize ai, langchain prompt management, lanhsmith prompt management, latitude, langchain, langgraph, langchain documentation, raycast, text expander, raycast snippets, raycast mac, cursor, cursro ai, cursor snippets, cursor rules, cursor ai rules, learn prompting, how to prompt, prompting guide, prompting tutorials, best prompting practices, ai prompt best practices, prompting techniques, prompting, flask, ios, go, graphql, rest, git, android, spa, api, react, performance, oauth, javascript, python, node, typescript, java, logging, pandas, express, php, electron, postgresql, aws, firebase, testing, seo, openai, gpt, c++, security, fastapi, mysql, redis, monitoring, lambda, dart, flutter, ci/cd, cdn, analytics, deployment, ssr, accessibility, matplotlib, kubernetes, serverless
AI Prompts, ChatGPT, Code Snippets, Prompt Engineering