Developer Documentation

Everything you need to build powerful AI-powered applications for the Gridlight platform.

Getting Started

Gridlight apps are web applications that run inside the Gridlight desktop shell. They can be as simple as a single HTML file or as complex as a full-stack app with a backend server. The Gridlight platform gives your app instant access to local AI capabilities — LLMs, image generation, RAG, and memory — without any cloud dependencies.

You have three ways to build apps:

  • App Builder — A visual, no-code builder for creating apps by dragging and dropping components
  • New Dev App — Scaffold a new app from templates directly inside Gridlight
  • Manual — Write your app from scratch using HTML, CSS, and JavaScript

Architecture Overview

Here's how the pieces fit together:

  • Gridlight Desktop (Tauri) — The native shell that loads and displays your apps
  • Gateway (Rust/Axum) — REST API on port 8080 that orchestrates all AI requests
  • Agents — Specialized workers for inference, embeddings, reranking, and verification
  • Your App — A web app (HTML/CSS/JS) rendered in a Tauri webview, calling the Gateway API
Gridlight Desktop (Tauri)Your AppHTML / CSS / JSWebviewHTTPGatewayRust / Axum — :8080REST API + OrchestrationAgentsInference Agent (LLM)Embedding AgentReranking AgentAI Models (Local)LLMsEmbeddingRerankingImage GenLoRAVerificationPostgreSQLApp data, users, memoryQdrantVector search (RAG)Neo4jKnowledge graph
Your app talks to the Gateway, which orchestrates AI agents and models.
📝Note

Apps don't need to bundle any AI models or ML libraries. They simply make HTTP calls to the local Gateway API, which handles all the heavy lifting.

Prerequisites

  • Gridlight desktop app installed and running
  • At least one AI model downloaded (for testing AI features)
Verify your setup
# Check Node.js
node --version

# Check that Gridlight Gateway is running
curl http://localhost:8080/health

App Builder (No-Code)

The fastest way to build a Gridlight app is with the visual App Builder. Open it in your browser, choose a layout, drag components onto the canvas, configure their properties, and export a ready-to-run app — no code required.

  1. 1

    Open App Builder

    Launch App Builder from within Gridlight — find it in your apps library and click to open.

  2. 2

    Choose a layout

    Pick a layout that matches your app's purpose:

    • Chat — Messages panel, input area, sidebar
    • Dashboard — Metrics, charts, data tables
    • Sidebar — Navigation sidebar with main content area
    • Split — Two-panel side-by-side layout
    • Full Canvas — Freeform, flexible layout
  3. 3

    Add components

    Browse the component panel on the left. Drag components into the canvas zones. There are 56+ components across categories: forms, display, data visualization, AI-powered, navigation, and more.

  4. 4

    Configure properties

    Click any component to open its configuration panel on the right. Set labels, placeholder text, colors, data sources, and AI settings.

  5. 5

    Preview and export

    Preview your app in real time, then export it as a standalone HTML file or a .glapp package for distribution.

Screenshot: App Builder visual interface with component panel and canvas
The App Builder — drag, drop, configure, and export.

AI-Powered Building

The App Builder includes an AI assistant. Click "Build with AI" and describe what you want in plain language:

Example prompt
"Create a customer feedback form with a star rating,
comment box, email field, and a submit button that
saves responses to Gridlight."

The AI generates the full page layout with configured components. You can accept it as-is, regenerate, or fine-tune individual components.

Creating a New Dev App

The quickest way to scaffold a new app is right inside Gridlight. Click the "New Dev App" button in the Apps tab and Gridlight will generate a complete project template for you — ready to customize.

  1. 1

    Open the Apps tab

    In the Gridlight desktop app, navigate to the Apps tab.

  2. 2

    Click "New Dev App"

    You'll see a button to create a new developer app. Click it and give your app a name.

  3. 3

    Choose a template

    Pick a starting template that matches your app's purpose:

    • Default — Basic starter with a heading and text
    • Chat — Chat interface with messages panel and input
    • Dashboard — Metrics, cards, and data display
  4. 4

    Select a theme and layout

    Customize the look and structure:

    OptionChoices
    ThemeGridlight (dark), Midnight (deep purple), Modern (light), Minimal (B&W)
    LayoutChat, Dashboard, Sidebar, Split, Full Canvas
  5. 5

    Start building

    Gridlight creates the project with the right file structure and opens it for you. You'll get a gridlight.json manifest, an app.json configuration, and an HTML entry point — everything you need to start customizing.

Your new app will have this structure:

my-app/
├── gridlight.json       # App manifest (name, version, entry point)
├── src/
│   ├── app.json         # App configuration (layout, components, zones)
│   └── index.html       # Entry point
└── README.md
Screenshot: New Dev App creation dialog in Gridlight
Create new apps directly inside Gridlight — no terminal needed.

Building Apps with Code

For maximum control, build your app from scratch. You just need two files: agridlight.json manifest and an HTML entry point.

gridlight.json
{
  "name": "My Custom App",
  "version": "1.0.0",
  "short_description": "A custom AI-powered application",
  "detailed_description": "A full description of what this app does and its features.",
  "usage_instructions": "Describe how to use the app here.",
  "author": "Your Name",
  "icon": "src/assets/icon.webp",
  "entry": "src/index.html",
  "runtime": "1.0",
  "type": "standalone",
  "gridlight_version_required": "0.6.0",
  "permissions": ["network", "storage"],
  "dependencies": {
    "components": [],
    "themes": []
  },
  "build": {
    "target": "single-html",
    "minify": true
  },
  "window": {
    "width": 1200,
    "height": 800
  }
}
src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My Custom App</title>
  <style>
    body { font-family: system-ui; background: #0f0f23; color: #fff; }
  </style>
</head>
<body>
  <h1>Hello, Gridlight!</h1>
  <button onclick="askAI()">Ask AI</button>
  <div id="response"></div>

  <script>
    async function askAI() {
      const res = await fetch('http://localhost:8080/neon', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer dev-token'
        },
        body: JSON.stringify({
          question: 'What is Gridlight?',
          stream: false
        })
      });
      const data = await res.json();
      document.getElementById('response').textContent = data.answer;
    }
  </script>
</body>
</html>
💡Tip

You can use any frontend framework you like — React, Vue, Svelte, or vanilla JS. As long as you have a gridlight.json and an HTML entry point, Gridlight will load it.

For hybrid apps with a backend server, add a backend section to your manifest:

Hybrid app manifest
{
  "name": "My Hybrid App",
  "version": "1.0.0",
  "short_description": "An app with a backend server",
  "author": "Your Name",
  "icon": "frontend/assets/icon.webp",
  "entry": "frontend/index.html",
  "runtime": "1.0",
  "type": "hybrid",
  "gridlight_version_required": "0.6.0",
  "backend": {
    "entry": "backend/server.js",
    "port": 3002,
    "install": "npm install",
    "healthCheck": "/api/health"
  },
  "permissions": ["network", "storage"],
  "dependencies": {
    "components": [],
    "themes": []
  },
  "build": {
    "target": "hybrid-app",
    "minify": true
  },
  "window": {
    "width": 1200,
    "height": 800
  }
}

Manifest Field Reference

FieldRequiredTypeDescription
nameYesstringDisplay name shown in the app launcher and marketplace. Keep it short and descriptive.
versionYesstringSemantic version (e.g. "1.0.0"). Bump this each time you publish an update.
short_descriptionYes*string1-2 sentence summary displayed on the app card in the marketplace. Required for publishing.
detailed_descriptionNostringFull description shown on the app details page. List features and capabilities here.
usage_instructionsNostringStep-by-step instructions for using the app. Shown in the help/info panel.
authorYes*stringAuthor or organization name. Displayed on the app card. Required for publishing.
iconYes*stringRelative path to the app icon (SVG or PNG). Used in the launcher and marketplace. Required for publishing.
entryYesstringRelative path to the HTML entry point. For standalone apps use src/index.html, for hybrid apps use frontend/index.html.
runtimeYesstringGridlight runtime version. Use "1.0" for all current apps.
typeYesstring"standalone" for frontend-only apps. "hybrid" for apps that include a backend server.
gridlight_version_requiredNostringMinimum Gridlight desktop version needed to run the app (e.g. "0.6.0"). Users on older versions will see an upgrade prompt.
permissionsNoarraySystem capabilities the app needs. Values: "network", "storage", "clipboard", "filesystem", "camera", "location", "notifications", "shell".
dependenciesNoobjectDeclares component, theme, and external library dependencies. Keys: components (array), themes (array), external (array of library names, e.g. "chart.js", "fflate@0.8.2").
buildNoobjectBuild configuration. target: "single-html", "hybrid-app", "pwa", or "docker". minify: boolean to minify output.
windowNoobjectWindow size and behavior. Keys: width, height (pixels), minWidth, minHeight, maxWidth, maxHeight, resizable (boolean), maximized (boolean), fullscreen (boolean).
backendHybrid onlyobjectBackend server config. entry: JS file to run with Node. port (required): port to listen on. install: dependency install command. healthCheck: health endpoint path.
connectionsNoarrayMCP connections the app uses. Each entry has id ("filesystem", "fetch-web", "github") and required (boolean).
💡Tip

Fields marked Yes* are technically optional for local development, but required when publishing to the Gridlight Marketplace. Fill them in before exporting your .glapp package.

Recommended Project Structure

Follow these conventions to keep your project clean and ready for marketplace publishing.

Standalone App

Standalone app layout
my-app/
├── gridlight.json          # App manifest
├── src/
│   ├── index.html          # Entry point
│   ├── app.json            # App config (settings, theme, layout)
│   ├── assets/
│   │   ├── icon.svg        # App icon (SVG recommended)
│   │   └── logo.webp        # Logo or branding assets
│   ├── css/
│   │   └── styles.css      # Stylesheets
│   └── js/
│       └── app.js          # Application logic
├── scripts/
│   └── package-glapp.js    # Build script for .glapp export
├── dist/                   # Build output
│   └── my-app-1.0.0.glapp  # Packaged app for marketplace
└── tests/                  # Test files
  • Keep gridlight.json at the project root — Gridlight looks for it there.
  • Use src/ for all source files to keep the root directory clean.
  • Use SVG for your app icon — it scales to any size in the marketplace and app launcher.
  • Build output goes to dist/. Your .glapp package is generated there.

Hybrid App (with Backend)

Hybrid app layout
my-hybrid-app/
├── gridlight.json          # App manifest (type: "hybrid")
├── frontend/
│   ├── index.html          # Frontend entry point
│   ├── assets/
│   │   └── icon.svg
│   ├── css/
│   │   └── theme.css
│   └── js/
│       └── app.js
├── backend/
│   ├── server.js           # Backend entry point (Express, etc.)
│   ├── package.json        # Backend dependencies
│   ├── routes/             # API route handlers
│   │   ├── health.js
│   │   └── api.js
│   ├── services/           # Business logic
│   │   └── myService.js
│   └── db/                 # Database files (if using SQLite)
│       ├── schema.sql
│       └── init.js
├── dist/                   # Build output
│   └── my-hybrid-app-1.0.0.glapp
└── tests/
  • Separate frontend/ and backend/ directories clearly.
  • Your backend server.js should listen on the port specified in gridlight.json.
  • Always provide a health check endpoint (e.g. /api/health) so Gridlight can verify the backend is running.
  • Put package.json in the backend directory and set "install": "npm install" in the manifest so dependencies are installed automatically.
  • Use routes/ for API endpoints and services/ for business logic.
  • For SQLite databases, store files in backend/db/.

Enabling Dragging App Window

For app developers building Gridlight marketplace apps, the only thing needed is to add data-tauri-drag-region to your header element:

Drag region example
<header class="header" data-tauri-drag-region>
    <span>My App Name</span>
    <button>Settings</button>  <!-- buttons still work normally -->
</header>

That's it. Gridlight automatically detects:

  • Any element with data-tauri-drag-region attribute
  • Any <header> element
  • Any element with class header

So if your app already has a <header> tag or a .header class on your top bar, dragging works automatically with no changes.

Interactive children (buttons, inputs, links, selects) are automatically excluded from the drag behavior.

Iframe-based hybrid apps: The drag detection only works in the outer document, not inside iframes. Add a thin header bar in the outer wrapper HTML above the iframe.

Component Library

Gridlight provides 56 modular UI components you can use in your apps. Each component has configurable properties, built-in styling, and JavaScript logic. When using the App Builder or the app.json configuration, you reference these by type name.

Endpoint Components

These components connect directly to Gridlight's AI APIs:

ComponentDescriptionHow to Use
Neon QuerySend RAG-powered queries to the /neon endpoint with streaming supportSet type: "neon-query". Configure domain to filter by knowledge base and limit for max results. Bind a text input to feed the query.
Intelligent ChatMulti-turn conversational AI via /chat/intelligentSet type: "intelligent-mode". Pair with a Chat Messages display component to show the conversation thread. Supports streaming responses.
Image GenerationGenerate images from text prompts, transform existing images, or inpaint regions via /imageSet type: "image-gen". Configure width, height, steps, and cfg_scale. Supports text-to-image, image-to-image, and inpainting modes.
File UploadUpload documents for training and indexing via /training/uploadSet type: "file-upload". Supports Excel parsing out of the box. Uploaded files are indexed into the knowledge base automatically.
Text TrainSend raw text for training via /training/textSet type: "train". Connect a textarea or text block as the input source. Use this to add custom knowledge without file uploads.

Display Components

Components for rendering content and showing status:

ComponentDescriptionHow to Use
Response DisplayRenders AI responses with markdown formatting, source citations, and a copy buttonSet type: "response-display". Includes a built-in thinking indicator while waiting for responses. Bind to a Neon Query or Intelligent Chat component.
Chat MessagesConversation thread with user/AI message bubbles and streaming supportSet type: "chat-messages". Configure userBubbleColor to match your theme. Supports timestamps and streaming token display.
Status BadgeConnection and system status pill indicatorSet type: "status-badge". Automatically shows connected, error, or pending states based on the gateway connection.
ListCustomizable list with icons and CSV import supportSet type: "list-component". Configure items with icons and labels. Supports importing data from CSV files.
Card GridGrid of customizable cards with images, icons, and configurable fieldsSet type: "card-grid". Configure columns, showImage, showIcon, and define custom fields as a JSON array. Supports CSV import.

Form Components

Input components for collecting user data. All form components support storageKey for persisting values across sessions.

ComponentDescriptionHow to Use
Auto TextareaExpanding text input that grows with contentSet type: "auto-textarea". Configure minHeight and maxHeight to control sizing. Enable submitOnEnter to trigger actions on Enter key.
Input + SendText input with an action button for submitting queriesSet type: "input-send". Configure placeholder and buttonText. Add customJs to run logic on submit.
DropdownSelect from a list of optionsSet type: "dropdown-select". Provide options as a JSON array. Set a label and placeholder for context.
Checkbox GroupMulti-select checkboxes in a grid layoutSet type: "checkbox-group". Provide options as a JSON array. Use columns to control the grid layout (e.g., 2 or 3 columns).
Chip ButtonsClickable tag buttons for quick selectionsSet type: "chip-buttons". Provide chips as a JSON array. Enable multiSelect to allow selecting more than one chip.
Quick ActionsPreset prompt buttons arranged in a gridSet type: "quick-actions". Define buttons as a JSON array with labels and prompts. Set columns for grid layout.
Search with FiltersSearch input with filter chips and Gridlight integrationSet type: "search-filters". Configure filters as JSON, set domain and limit to control search scope.
Login FormEmail/password login with optional OAuth buttonsSet type: "login-form". Enable showOAuth and provide oauthProviders as JSON. Set loginEndpoint for your backend.
Signup FormUser registration with configurable password rulesSet type: "signup-form". Configure password requirements: minPasswordLength, requireUppercase, requireNumber, requireSpecial.
Password ResetPassword reset request formSet type: "password-reset". Customize title, subtitle, and buttonText to match your app's branding.

AI-Powered Components

Specialized AI components that add intelligence to your apps with zero configuration:

ComponentDescriptionHow to Use
AI Content GeneratorGenerate text content with customizable tone and styleSet type: "ai-content-generator". Provide a prompt template and configure output tone. Useful for generating descriptions, summaries, or marketing copy.
AI Chat WidgetFloating chat bubble for any page — like an AI support agentSet type: "ai-chat-widget". Drop it onto any page for an instant AI assistant. It floats in the corner and expands on click.
Smart SearchSemantic search with relevance scoring and source citationsSet type: "smart-search". Returns results ranked by semantic relevance rather than keyword matching. Shows source citations for transparency.
AI Summary CardAutomatically summarize documents or long textSet type: "ai-summary-card". Bind it to a data source or document upload. Generates concise summaries automatically.
Document Q&AUpload a document and ask questions about itSet type: "document-qa". Combines a file upload zone with a query input. Users upload a document, then ask natural-language questions about its content.
AI Form FillerExtract structured data from unstructured documentsSet type: "ai-form-filler". Define the target fields and the AI will parse uploaded documents to fill them automatically.
AI Data InsightsAuto-analyze datasets, detect trends, and generate visualizationsSet type: "ai-data-insights". Point it at a data source and it will identify patterns, anomalies, and trends — then render charts automatically.

Data & Visualization Components

Components for building dashboards and displaying structured data:

ComponentDescriptionHow to Use
Data LoaderFetch structured data from Gridlight and store it in a variableSet type: "data-loader". Configure query, domain, and limit. Set variable_name to make the data available to other components via data binding.
Metric CardDisplay a single metric with a change indicatorSet type: "metric-card". Configure label, default_value, and change_type (positive, negative, or neutral). Bind to a data source with data_source and value_path.
Bar ChartInteractive bar chart for comparing categoriesSet type: "bar-chart". Configure data_source, label_key, and value_key to map your data fields. Set dataset_label for the legend.
Line ChartInteractive line chart for trend analysis over timeSet type: "line-chart". Same configuration as Bar Chart — set data_source, label_key, and value_key. Ideal for time-series data.
Pie ChartPie or doughnut chart for showing distributionSet type: "pie-chart". Configure data_source, label_key, and value_key. Colors are assigned automatically.
Data TableSortable table for displaying tabular dataSet type: "data-table". Set data_source to point at a Data Loader variable. Columns are generated automatically from the data structure.

Layout & Container Components

Structural components for organizing your app's interface:

ComponentDescriptionHow to Use
TabsContainer with switchable tab panelsSet type: "tabs-component". Define tabs as a JSON array with labels. Set defaultTab to control which tab opens first. Drop other components into each tab panel.
AccordionCollapsible sections for organizing contentSet type: "accordion-component". Define sections as a JSON array. Set allowMultiple: true to let users expand more than one section at a time.
ModalPopup dialog with a trigger button and droppable content areaSet type: "modal-dialog". Configure triggerText, title, and size (sm, md, or lg). Place other components inside the modal body.
Grid ContainerCSS Grid layout container for arranging componentsSet type: "grid-container". Configure columns, rows, and gap (0, 8, 16, 24, or 32px). Nest child components inside for structured layouts.

App Manifest Specification

Every Gridlight app needs a gridlight.json file at the project root. This is how Gridlight discovers and loads your app.

Required Fields

FieldTypeDescription
namestringDisplay name of your app
versionstringSemantic version (e.g. "1.0.0")
entrystringPath to the HTML entry point
runtimestringGridlight runtime version (use "1.0")
typestring"standalone" or "hybrid" (with backend)

Optional Fields

FieldTypeDescription
short_descriptionstring1-2 sentence summary for the app card
detailed_descriptionstringFull description for the app details page
usage_instructionsstringHow to use the app, shown in help/info panel
authorstringAuthor or organization name
iconstringPath to app icon (SVG or PNG recommended)
gridlight_version_requiredstringMinimum Gridlight version needed (e.g. "0.6.0")
app_typestringCategory: "tool", "viewer", "editor", or "dashboard"
permissionsarrayRequested permissions (see Permissions below)
dependenciesobjectComponent, theme, and external library dependencies
buildobjectBuild configuration (target and minify)
connectionsarrayMCP connection declarations
windowobjectWindow size and behavior settings
backendobjectBackend server config (required for hybrid apps)

Permissions

The permissions array declares what system capabilities your app needs.

PermissionDescription
"network"Make HTTP requests to external servers
"storage"Store data locally (IndexedDB / localStorage)
"clipboard"Read and write to the clipboard
"filesystem"Read/write local files (prompts the user for access)
"camera"Access camera or microphone
"location"Access geolocation
"notifications"Show system notifications
"shell"Execute system commands (prompts the user for access)

Window Object

Controls the initial window size and behavior when the app launches.

FieldTypeDefaultDescription
widthnumber1500Initial width in pixels
heightnumber875Initial height in pixels
minWidth / minHeightnumberMinimum dimensions
maxWidth / maxHeightnumberMaximum dimensions
resizablebooleantrueAllow the user to resize the window
maximizedbooleanfalseStart maximized (fills screen, keeps taskbar)
fullscreenbooleanfalseStart in true fullscreen (hides taskbar)
💡Tip

Priority: fullscreen > maximized > width/height. If maximized is true, explicit width/height are ignored.

Dependencies Object

dependencies
"dependencies": {
  "components": [],
  "themes": ["gridlight"],
  "external": ["chart.js", "katex"]
}
FieldTypeDescription
componentsarrayCustom component names your app depends on
themesarrayTheme names (e.g. "gridlight", "arcade")
externalarrayExternal libraries with optional versions (e.g. "fflate@0.8.2")

Build Object

build
"build": {
  "target": "single-html",
  "minify": true
}
FieldTypeDescription
targetstring"single-html", "hybrid-app", "pwa", or "docker"
minifybooleanWhether to minify the build output

Backend Object (Hybrid Apps)

Required when type is "hybrid". Configures the backend server that Gridlight starts alongside your frontend.

FieldTypeRequiredDescription
entrystring*JS file to run with Node (e.g. "backend/server.js")
commandstring*Shell command to start the backend (e.g. "npm start")
pathstringNoWorking directory for the command (relative to app root)
portnumberYesPort the backend listens on
installstringNoDependency install command (e.g. "npm install")
healthCheckstringNoHealth check endpoint path (e.g. "/api/health")
📝Note

Provide either entry or command, not both. With entry, Gridlight runs node <entry> from the app root. With command, Gridlight runs it as a shell process from the path directory.

Connections Array

Declare MCP (Model Context Protocol) connections your app can use.

connections
"connections": [
  { "id": "filesystem", "required": true },
  { "id": "fetch-web", "required": false },
  { "id": "github", "required": false }
]
Connection IDDescription
filesystemRead/write files on the local filesystem
fetch-webMake HTTP requests to external URLs
githubGitHub API access (repos, issues, PRs)

Data Binding & State

When building apps with the App Builder or app.json, you can connect components together using data bindings. Changes to one component automatically update any bound components.

Data binding in app.json
{
  "bindings": [
    {
      "source": "search-input",
      "sourceProperty": "value",
      "target": "results-display",
      "targetProperty": "query"
    }
  ]
}

In exported apps, you can use the runtime API:

Runtime API
// Set a value
window.AppBindings.setValue('global.username', 'Jane');

// Get a value
const name = window.AppBindings.getValue('global.username');

// React to changes
window.AppBindings.onChange('global.username', (newValue) => {
  console.log('Username changed to:', newValue);
});

Workflows & Automation

Workflows let you automate multi-step processes in your apps — from simple "on form submit, show notification" to complex chains with conditional branching and API calls.

App Builder Workflows

In the App Builder, workflows are defined visually. Define triggers (what starts the workflow) and actions (what happens):

TriggersActions
Form SubmittedShow Notification (toast message)
Button ClickedNavigate to URL
Page LoadedSet Value (update variable)
Data ChangedShow/Hide Component
Component Value ChangesCall API / Save to Gridlight
Webhook ReceivedRun Custom Code (JavaScript)
Scheduled (Cron)HTTP Request, If/Else, Loop, Wait/Delay
Workflow example in app.json
{
  "workflows": [
    {
      "name": "Submit Feedback",
      "trigger": { "type": "form_submitted", "source": "feedback-form" },
      "actions": [
        {
          "type": "api_call",
          "url": "http://localhost:8080/training/text",
          "method": "POST",
          "body": { "content": "{{feedback-form.value}}", "domain": "feedback" }
        },
        {
          "type": "show_notification",
          "message": "Thank you for your feedback!",
          "variant": "success"
        }
      ]
    }
  ]
}

Themes & Styling

Gridlight apps support built-in themes and fully custom styling. Themes control colors, fonts, spacing, and component appearance.

Built-in Themes

ThemeStyle
GridlightDark with pink/purple accents (default)
MidnightDeep blue-black with cool tones
ModernClean, minimal dark theme
MinimalLight theme with subtle colors
NeonVibrant neon colors on dark background
OceanBlue-green oceanic palette
ForestEarthy green tones
SunsetWarm orange and red gradient
ElegantSophisticated dark with gold accents
RoseSoft pink and rose tones

Custom Themes

Create your own theme by setting CSS custom properties:

Custom theme configuration
{
  "theme": {
    "preset": "custom",
    "primary": "#e91e63",
    "secondary": "#2196f3",
    "background": "#0f0f23",
    "surface": "rgba(26, 26, 46, 0.8)",
    "text": "#ffffff",
    "textMuted": "#888888",
    "accent": "#a855f7",
    "fontFamily": "Inter",
    "customFontUrl": "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700"
  }
}

Export & Publishing

Once your app is ready, export it in the format that fits your needs.

HTML Export

Export as a single HTML file — perfect for quick sharing or embedding. Everything (styles, scripts, components) is bundled into one file.

.glapp Package

The native Gridlight package format for desktop distribution. This is what you need to publish to the marketplace.

Build and package
npm run build      # Compile your app
npm run package    # Create .glapp file

The .glapp file contains your manifest, compiled app, and runtime. Users install it by downloading and placing it in their ~/Gridlight/apps/ directory.

PWA Export

You can also export as a Progressive Web App with a manifest and service worker for installable, offline-capable deployments.

Publishing to Marketplace

  1. 1

    Build your .glapp package

    Run npm run package to create the distributable file.

  2. 2

    Create a marketplace listing

    Visit market.gridlight.ai, create an account, and submit your app with screenshots, description, pricing, and categories.

  3. 3

    Set pricing

    Choose free or paid distribution. Paid apps use Stripe for secure payments. Bundle discounts are automatically applied for multi-app purchases from the same seller.

  4. 4

    Publish

    Submit for review. Once approved, your app is live in the marketplace for all Gridlight users to discover.

💡Tip

Include clear usage instructions and screenshots in your listing. Apps with good documentation get significantly more downloads.

API Reference

All API requests go to the Gridlight Gateway at http://localhost:8080. Every request requires an Authorization: Bearer <token> header.

🔑Important

If you're building apps with App Builder, you don't need to call these APIs directly — the components handle all API communication automatically. This section is purely for reference if you prefer building your own custom application from scratch.

📝Note

The default development token is dev-token. Change this in production via the Settings tab.

RAG / Knowledge Query

The /neon endpoint is Gridlight's powerhouse. It combines vector search, keyword retrieval, entity recognition, reranking, and LLM generation into a single call.

POST /neon
{
  "question": "What is our vacation policy?",
  "domain": "HR",
  "stream": true,
  "limit": 10,
  "access_tier": "internal",
  "include_sources": true,
  "max_tokens": 4096
}

With stream: true, responses come as Server-Sent Events:

data: {"token": "Our"}
data: {"token": " vacation"}
data: {"token": " policy"}
data: [DONE]

Intelligent Chat

Multi-turn conversations with context awareness. The AI adapts to your expertise level and preferred response style.

POST /chat/intelligent
{
  "message": "Explain how embeddings work",
  "conversation_id": "conv-123",
  "history": [
    { "role": "user", "content": "What is RAG?" },
    { "role": "assistant", "content": "RAG stands for..." }
  ]
}

Image Generation

Generate images from text, transform existing images, or inpaint specific regions.

POST /image
{
  "prompt": "A cyberpunk cityscape at sunset, neon lights",
  "negative_prompt": "blurry, low quality",
  "width": 1024,
  "height": 1024,
  "steps": 30,
  "cfg_scale": 7.5,
  "seed": -1
}

Memory

Store and retrieve user-specific facts, preferences, and context.

POST /remember
{
  "content": "User prefers Python code examples",
  "memory_type": "preference",
  "expiration": "never"
}
GET /memories
// Response:
{
  "memories": [
    {
      "id": "mem-1",
      "content": "User prefers Python code examples",
      "type": "preference",
      "created_at": "2026-01-15T10:30:00Z"
    }
  ]
}

File Upload

Upload documents to the knowledge base for RAG indexing.

POST /training/upload
// Supported formats: .pdf, .docx, .txt, .md, .csv,
// .xlsx, .json, .xml, .py, .js, .ts, .rs, .go, .java

// Request: multipart/form-data
// - file: the document file
// - domain: "HR" (optional, for data isolation)
// - access_tier: "internal" (public/internal/restricted)

// Response:
{
  "status": "success",
  "chunks": 42,
  "message": "Document indexed successfully"
}

Best Practices

Building great Gridlight apps is about more than just wiring up components. These tips — drawn from our own apps like Gridlight Chat and the VS Code extension — will help you build apps that feel fast, responsive, and reliable.

Streaming Responses

Always use streaming when interacting with the LLM. Streaming lets your users see tokens appear in real-time instead of waiting for the full response. This single change has the biggest impact on perceived performance.

Streaming with Server-Sent Events
const response = await fetch(`${gatewayUrl}/api/chat`, {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${apiToken}` },
  body: JSON.stringify({ question, stream: true })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const chunk = decoder.decode(value);
  // Parse SSE data fields
  for (const line of chunk.split('\n')) {
    if (line.startsWith('data: ')) {
      const data = JSON.parse(line.slice(6));
      appendToMessage(data.content);
    }
  }
}
💡Tip

Support multiple SSE field names (delta, content,text, chunk) for forward compatibility as the API evolves.

Efficient DOM Updates

When streaming tokens, avoid re-rendering your entire message list on every chunk. Instead, target just the active message element.

  • Batch updates with requestAnimationFrame — Instead of updating the DOM on every token, collect tokens and flush them at 60fps. This reduces DOM writes from 20+/sec to ~16/sec.
  • Update only the streaming message — Find the specific message element and update its content directly. Don't rebuild all messages.
  • Cache completed markdown — Once a message finishes streaming, cache its processed markdown. On re-renders, use the cached version instead of re-processing.
Token batching with requestAnimationFrame
let pendingTokens = '';
let rafId = null;

function onToken(token) {
  pendingTokens += token;
  if (!rafId) {
    rafId = requestAnimationFrame(() => {
      messageEl.textContent += pendingTokens;
      pendingTokens = '';
      rafId = null;
    });
  }
}

Caching & Pre-fetching

Smart caching can dramatically reduce latency, especially for context-heavy operations. Use tiered TTLs based on how frequently data changes.

Data TypeSuggested TTLInvalidation
File contents30 secondsOn file change (watch)
Processed context chunks1 minuteOn source file change
Workspace/project structure2 minutesOn file create/delete
Indexes and symbol tables24 hoursOn staleness check

For multi-step workflows, speculatively pre-fetch context for the next step while the current one is executing. This overlap hides latency and can reduce end-to-end time by 30–50%.

Error Handling & Retries

Network hiccups happen. A good retry strategy keeps your app resilient without overwhelming the server.

  • Exponential backoff with jitter — Start at 1 second, multiply by 2 on each retry, add ±10% random jitter to prevent thundering herd.
  • Categorize errors — Network errors, rate limits (429), and server errors (5xx) are retryable. Auth errors (401/403) and client errors (400) are not.
  • Cap retries — 3 retries with a 30-second maximum delay is a good default. For rate limits, respect the Retry-After header.
  • Don't retry streaming requests — If a streaming connection drops, start fresh rather than retrying mid-stream.
Retry with exponential backoff
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      if (response.ok) return response;

      // Don't retry client errors
      if (response.status >= 400 && response.status < 500) throw response;

      // Retry server errors
      if (attempt < maxRetries) {
        const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
        const jitter = delay * (0.9 + Math.random() * 0.2);
        await new Promise(r => setTimeout(r, jitter));
      }
    } catch (err) {
      if (attempt === maxRetries) throw err;
    }
  }
}

Resource-Aware Design

Gridlight runs on everything from laptops to enterprise workstations. Your app should adapt to the available resources.

  • Check TFLOP allocation — Use the gateway's system info to understand compute capacity and adjust batch sizes, concurrency, and timeouts accordingly.
  • Scale batch operations dynamically — On low-end systems (under 4 CPU cores), use smaller batches with longer delays. On high-end systems (16+ cores), increase concurrency.
  • Debounce file watchers — If your app watches files (for RAG indexing, auto-save, etc.), debounce updates by 2 seconds. Rapid changes like "save all" or git checkouts can trigger dozens of events.
  • Bound your caches — Set a max entry count (e.g., 50 files) and a max total size (e.g., 10MB). Use LRU eviction when limits are reached.

UX Patterns

The best Gridlight apps feel responsive even when the AI is thinking. Here are patterns that create that perception:

  • Show placeholder messages immediately — When a user sends a message, instantly create a placeholder response ("Looking into your documents...") before the API call even starts. Transition to "Thinking..." once the LLM begins processing.
  • Provide a stop button — Use an AbortController to let users cancel in-flight requests. Release reader locks and clean up state on cancellation.
  • Use fast-path checks — Before running expensive operations (like regex or markdown processing), do a quick check to see if it's needed. For example, skip stripThinkingTags() if the text doesn't contain <think>.
  • Parallelize read-only operations — If your app fetches multiple pieces of context (files, documents, embeddings), run them concurrently with Promise.all(). Only serialize write operations.
  • Handle large inputs gracefully — If user input exceeds your API's context limit, split it into conversation history chunks (~9K characters each) and pass them as prior turns. This preserves context without hitting limits.
💡The golden rule

Always give the user something to look at while the AI works. Instant visual feedback — even a loading state — makes everything feel twice as fast.