diff --git a/API_UPLOAD_FEATURES.md b/API_UPLOAD_FEATURES.md
new file mode 100644
index 00000000..6b318c16
--- /dev/null
+++ b/API_UPLOAD_FEATURES.md
@@ -0,0 +1,161 @@
+# API Upload Features
+
+This document describes the new API upload functionality added to the Accord Protocol Template Playground.
+
+## Overview
+
+The template playground now includes comprehensive support for uploading templates and creating agreements using the Accord Protocol API format as defined in the [OpenAPI specification](https://raw.githubusercontent.com/accordproject/apap/refs/heads/main/openapi.json).
+
+## New Components
+
+### 1. Template Metadata Editor
+
+**Location**: `src/editors/editorsContainer/TemplateMetadata.tsx`
+
+A form-based editor that allows users to configure all template metadata fields required by the API:
+
+- **Basic Properties**:
+  - Author
+  - Display Name
+  - Version
+  - Description
+  - License (dropdown with common licenses)
+  - Keywords (tag-based input)
+
+- **Runtime Metadata**:
+  - Runtime (TypeScript/JavaScript/ES2015)
+  - Template Type (Clause/Contract/Template)
+  - Cicero Version
+
+### 2. Template Logic Editor
+
+**Location**: `src/editors/editorsContainer/TemplateLogic.tsx`
+
+A large text area editor for writing TypeScript/JavaScript logic code with:
+- Syntax highlighting
+- Undo/Redo functionality
+- Monospace font for code readability
+
+### 3. API Upload Component
+
+**Location**: `src/components/ApiUpload.tsx`
+
+A comprehensive upload interface that provides:
+
+- **API Configuration**: Configurable API base URL
+- **Template Upload**: Upload template to API with validation
+- **Agreement Creation**: Create agreements from uploaded templates
+- **Template Download**: Download template as JSON file
+- **Preview Modal**: View formatted template JSON before upload
+
+## API Integration
+
+### Template Format
+
+The system automatically formats templates according to the Accord Protocol API specification:
+
+```json
+{
+  "uri": "resource:org.accordproject.protocol@1.0.0.Template#template-name",
+  "author": "Author Name",
+  "displayName": "Template Display Name",
+  "version": "1.0.0",
+  "description": "Template description",
+  "license": "Apache-2",
+  "keywords": ["keyword1", "keyword2"],
+  "metadata": {
+    "$class": "org.accordproject.protocol@1.0.0.TemplateMetadata",
+    "runtime": "typescript",
+    "template": "clause",
+    "cicero": "0.25.x"
+  },
+  "logo": null,
+  "templateModel": {
+    "$class": "org.accordproject.protocol@1.0.0.TemplateModel",
+    "typeName": "templatename",
+    "model": {
+      "$class": "org.accordproject.protocol@1.0.0.CtoModel",
+      "ctoFiles": [
+        {
+          "contents": "// Concerto model content",
+          "filename": "model.cto"
+        }
+      ]
+    }
+  },
+  "text": {
+    "$class": "org.accordproject.protocol@1.0.0.Text",
+    "templateText": "TemplateMark content"
+  },
+  "logic": "// Template logic code",
+  "sampleRequest": null
+}
+```
+
+### API Endpoints
+
+The system integrates with the following API endpoints:
+
+- `POST /templates` - Upload template
+- `POST /agreements` - Create agreement from template
+- `GET /templates` - List templates
+- `GET /agreements` - List agreements
+
+## Usage
+
+### 1. Configure Template Metadata
+
+1. Open the "Template Metadata" panel
+2. Fill in required fields (Author and Display Name are mandatory)
+3. Configure runtime settings as needed
+
+### 2. Write Template Logic (Optional)
+
+1. Open the "Template Logic" panel
+2. Write TypeScript/JavaScript code for template execution
+3. Use undo/redo for code editing
+
+### 3. Upload to API
+
+1. Open the "API Upload" panel
+2. Configure the API base URL
+3. Click "Upload Template to API"
+4. Review the generated JSON in the preview modal
+5. Optionally create agreements from the uploaded template
+
+### 4. Download Template
+
+- Use the "Download Template JSON" button to save the template locally
+
+## State Management
+
+The new features are integrated into the existing Zustand store with:
+
+- `templateMetadata`: Template metadata state
+- `templateLogic`: Template logic code
+- `setTemplateMetadata()`: Update metadata
+- `setTemplateLogic()`: Update logic code
+
+## Data Persistence
+
+Template metadata and logic are included in:
+- Shareable links (compressed data)
+- Sample loading
+- State restoration
+
+## Error Handling
+
+The system includes comprehensive error handling:
+- Validation of required fields
+- API error responses
+- Network connectivity issues
+- JSON parsing errors
+
+## Future Enhancements
+
+Potential improvements:
+- Template versioning
+- Batch upload capabilities
+- Template marketplace integration
+- Advanced validation rules
+- Template testing framework 
\ No newline at end of file
diff --git a/README.md b/README.md
index 0cbfda66..162431bf 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,30 @@ The Accord Project Playground is an open-source project, welcoming contributions
 
 The Template Playground is deployed at: [https://playground.accordproject.org](https://playground.accordproject.org)
 
+## API Configuration
+
+The playground can connect to an Accord Protocol API server for template and agreement management. To configure the API server URL:
+
+### Environment Variable Configuration
+
+Create a `.env` file in the project root with:
+
+```bash
+# Accord Protocol API Server URL
+VITE_API_SERVER_URL=http://your-accord-server:port
+```
+
+### Default Configuration
+
+If no environment variable is set, the playground defaults to:
+```
+http://ec2-3-80-94-40.compute-1.amazonaws.com:9000
+```
+
+### Development Proxy
+
+In development mode, the playground automatically proxies `/api/*` requests to the configured server to avoid CORS issues.
+
 ---
 
 
diff --git a/package-lock.json b/package-lock.json
index 72ba3214..40f0bd80 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,7 @@
         "@types/styled-components": "^5.1.34",
         "antd": "^5.7.2",
         "core-js": "^3.37.1",
+        "for-each": "^0.3.5",
         "highlight.js": "^11.10.0",
         "immer": "^10.1.1",
         "jest-canvas-mock": "^2.5.2",
@@ -12274,11 +12275,18 @@
       }
     },
     "node_modules/for-each": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
-      "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+      "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+      "license": "MIT",
       "dependencies": {
-        "is-callable": "^1.1.3"
+        "is-callable": "^1.2.7"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/for-in": {
diff --git a/package.json b/package.json
index 5254fa79..8b6ceb4d 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
     "@types/styled-components": "^5.1.34",
     "antd": "^5.7.2",
     "core-js": "^3.37.1",
+    "for-each": "^0.3.5",
     "highlight.js": "^11.10.0",
     "immer": "^10.1.1",
     "jest-canvas-mock": "^2.5.2",
diff --git a/src/App.tsx b/src/App.tsx
index 2b8f93e0..12d77953 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -11,6 +11,9 @@ import AgreementHtml from "./AgreementHtml";
 import Errors from "./utils/helpers/Errors";
 import TemplateMarkdown from "./editors/editorsContainer/TemplateMarkdown";
 import TemplateModel from "./editors/editorsContainer/TemplateModel";
+import TemplateMetadata from "./editors/editorsContainer/TemplateMetadata";
+import TemplateLogic from "./editors/editorsContainer/TemplateLogic";
+import ApiUpload from "./components/ApiUpload";
 import useAppStore from "./store/store";
 import SampleDropdown from "./components/SampleDropdown";
 import UseShare from "./components/UseShare";
@@ -115,6 +118,21 @@ const App = () => {
       label: "Concerto Model",
       children:  ,
     },
+    {
+      key: "metadata",
+      label: "Template Metadata",
+      children:  ,
+    },
+    {
+      key: "logic",
+      label: "Template Logic",
+      children:  ,
+    },
+    {
+      key: "api",
+      label: "API Upload",
+      children:  ,
+    },
     {
       key: "data",
       label: "Preview Data",
diff --git a/src/components/ApiUpload.tsx b/src/components/ApiUpload.tsx
new file mode 100644
index 00000000..d0147200
--- /dev/null
+++ b/src/components/ApiUpload.tsx
@@ -0,0 +1,175 @@
+import { useState } from 'react';
+import { Button, Input, Modal, message, Space, Card, Typography } from 'antd';
+import { UploadOutlined, CloudUploadOutlined, FileTextOutlined } from '@ant-design/icons';
+import { formatTemplateForApi, uploadTemplateToApi, createAgreementFromTemplate } from '../utils/templateApi';
+import useAppStore from '../store/store';
+
+const { TextArea } = Input;
+const { Text } = Typography;
+
+function ApiUpload() {
+  const textColor = useAppStore((state) => state.textColor);
+  const backgroundColor = useAppStore((state) => state.backgroundColor);
+  const templateMetadata = useAppStore((state) => state.templateMetadata);
+  const data = useAppStore((state) => state.data);
+  
+  const [apiUrl, setApiUrl] = useState('http://localhost:5175/api');
+  const [isModalVisible, setIsModalVisible] = useState(false);
+  const [isUploading, setIsUploading] = useState(false);
+  const [uploadedTemplateId, setUploadedTemplateId] = useState(null);
+  const [templateJson, setTemplateJson] = useState('');
+
+  const handleUploadTemplate = async () => {
+    if (!templateMetadata.displayName || !templateMetadata.author) {
+      message.error('Please fill in the template metadata (Display Name and Author are required)');
+      return;
+    }
+
+    setIsUploading(true);
+    try {
+      const template = formatTemplateForApi();
+      setTemplateJson(JSON.stringify(template, null, 2));
+      
+      const response = await uploadTemplateToApi(apiUrl, template);
+      
+      if (response.ok) {
+        const result = await response.json();
+        setUploadedTemplateId(result.uri || result.id);
+        message.success('Template uploaded successfully!');
+        setIsModalVisible(true);
+      } else {
+        const errorText = await response.text();
+        message.error(`Upload failed: ${response.status} - ${errorText}`);
+      }
+    } catch (error) {
+      message.error(`Upload failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
+    } finally {
+      setIsUploading(false);
+    }
+  };
+
+  const handleCreateAgreement = async () => {
+    if (!uploadedTemplateId) {
+      message.error('No template uploaded yet');
+      return;
+    }
+
+    setIsUploading(true);
+    try {
+      const agreementData = JSON.parse(data);
+      const response = await createAgreementFromTemplate(apiUrl, uploadedTemplateId, agreementData);
+      
+      if (response.ok) {
+        const result = await response.json();
+        message.success('Agreement created successfully!');
+        console.log('Created agreement:', result);
+      } else {
+        const errorText = await response.text();
+        message.error(`Agreement creation failed: ${response.status} - ${errorText}`);
+      }
+    } catch (error) {
+      message.error(`Agreement creation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
+    } finally {
+      setIsUploading(false);
+    }
+  };
+
+  const handleDownloadTemplate = () => {
+    const template = formatTemplateForApi();
+    const blob = new Blob([JSON.stringify(template, null, 2)], { type: 'application/json' });
+    const url = URL.createObjectURL(blob);
+    const a = document.createElement('a');
+    a.href = url;
+    a.download = `${templateMetadata.displayName || 'template'}.json`;
+    document.body.appendChild(a);
+    a.click();
+    document.body.removeChild(a);
+    URL.revokeObjectURL(url);
+  };
+
+  return (
+    
+      
+             
+            API Upload 
+          
+        }
+        style={{ backgroundColor, borderColor: '#d9d9d9' }}
+        headStyle={{ color: textColor, backgroundColor }}
+        bodyStyle={{ color: textColor, backgroundColor }}
+      >
+        
+          API Base URL: 
+           ) => setApiUrl(e.target.value)}
+            placeholder="http://localhost:3000"
+            style={{ marginTop: '8px', backgroundColor, color: textColor, borderColor: '#d9d9d9' }}
+          />
+        
+
+        
+           }
+            onClick={handleUploadTemplate}
+            loading={isUploading}
+            style={{ width: '100%' }}
+          >
+            Upload Template to API
+          
+
+           }
+            onClick={handleDownloadTemplate}
+            style={{ width: '100%' }}
+          >
+            Download Template JSON
+          
+
+          {uploadedTemplateId && (
+            
+              Create Agreement from Template
+             
+          )}
+         
+
+        {uploadedTemplateId && (
+          
+            
+              Template uploaded successfully! ID: {uploadedTemplateId}
+             
+          
+        )}
+       
+
+      
 setIsModalVisible(false)}
+        footer={[
+           setIsModalVisible(false)}>
+            Close
+           
+        ]}
+        width={800}
+      >
+        
+       
+    
 
+  );
+}
+
+export default ApiUpload; 
\ No newline at end of file
diff --git a/src/editors/editorsContainer/TemplateLogic.tsx b/src/editors/editorsContainer/TemplateLogic.tsx
new file mode 100644
index 00000000..e8f07c00
--- /dev/null
+++ b/src/editors/editorsContainer/TemplateLogic.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import { Input } from 'antd';
+import useAppStore from '../../store/store';
+import useUndoRedo from '../../components/useUndoRedo';
+import { FaUndo, FaRedo } from 'react-icons/fa';
+
+const { TextArea } = Input;
+
+function TemplateLogic() {
+  const textColor = useAppStore((state) => state.textColor);
+  const backgroundColor = useAppStore((state) => state.backgroundColor);
+  const templateLogic = useAppStore((state) => state.templateLogic);
+  const setTemplateLogic = useAppStore((state) => state.setTemplateLogic);
+  const { value, setValue, undo, redo } = useUndoRedo(
+    templateLogic,
+    setTemplateLogic,
+    setTemplateLogic
+  );
+
+  const handleChange = (value: string | undefined) => {
+    if (value !== undefined) {
+      setValue(value);
+    }
+  };
+
+  return (
+    
+      
+        
Template Logic 
+        
+           
+           
+        
+      
+      
+        TypeScript/JavaScript logic for template execution and business rules.
+      
+      
 
+  );
+}
+
+export default TemplateLogic; 
\ No newline at end of file
diff --git a/src/editors/editorsContainer/TemplateMetadata.tsx b/src/editors/editorsContainer/TemplateMetadata.tsx
new file mode 100644
index 00000000..beea1acb
--- /dev/null
+++ b/src/editors/editorsContainer/TemplateMetadata.tsx
@@ -0,0 +1,163 @@
+import React from 'react';
+import { Form, Input, Select } from 'antd';
+import useAppStore from '../../store/store';
+
+const { TextArea } = Input;
+const { Option } = Select;
+
+interface TemplateMetadata {
+  author: string;
+  displayName: string;
+  version: string;
+  description: string;
+  license: string;
+  keywords: string[];
+  metadata: {
+    runtime: string;
+    template: string;
+    cicero: string;
+  };
+}
+
+function TemplateMetadata() {
+  const textColor = useAppStore((state) => state.textColor);
+  const backgroundColor = useAppStore((state) => state.backgroundColor);
+  const templateMetadata = useAppStore((state) => state.templateMetadata);
+  const setTemplateMetadata = useAppStore((state) => state.setTemplateMetadata);
+
+  const handleMetadataChange = (field: keyof TemplateMetadata, value: any) => {
+    setTemplateMetadata({
+      ...templateMetadata,
+      [field]: value
+    });
+  };
+
+  const handleMetadataPropertyChange = (field: keyof TemplateMetadata['metadata'], value: string) => {
+    setTemplateMetadata({
+      ...templateMetadata,
+      metadata: {
+        ...templateMetadata.metadata,
+        [field]: value
+      }
+    });
+  };
+
+  const handleKeywordChange = (keywords: string[]) => {
+    setTemplateMetadata({
+      ...templateMetadata,
+      keywords
+    });
+  };
+
+  return (
+    
+      
Template Metadata 
+      
+        Configure template properties and metadata for API upload.
+      
+      
+      
+           ) => handleMetadataChange('author', e.target.value)}
+            placeholder="Template author"
+            style={{ backgroundColor, color: textColor, borderColor: '#d9d9d9' }}
+          />
+         
+
+        
+           ) => handleMetadataChange('displayName', e.target.value)}
+            placeholder="Template display name"
+            style={{ backgroundColor, color: textColor, borderColor: '#d9d9d9' }}
+          />
+         
+
+        
+           ) => handleMetadataChange('version', e.target.value)}
+            placeholder="1.0.0"
+            style={{ backgroundColor, color: textColor, borderColor: '#d9d9d9' }}
+          />
+         
+
+        
+           
+
+        
+           handleMetadataChange('license', value)}
+            placeholder="Select license"
+            style={{ backgroundColor, color: textColor }}
+          >
+            Apache-2 
+            MIT 
+            GPL-3.0 
+            BSD-3-Clause 
+            ISC 
+           
+         
+
+        
+           
+         
+
+        
Runtime Metadata 
+        
+        
+           handleMetadataPropertyChange('runtime', value)}
+            placeholder="Select runtime"
+            style={{ backgroundColor, color: textColor }}
+          >
+            TypeScript 
+            JavaScript 
+            ES2015 
+           
+         
+
+        
+           handleMetadataPropertyChange('template', value)}
+            placeholder="Select template type"
+            style={{ backgroundColor, color: textColor }}
+          >
+            Clause 
+            Contract 
+            Template 
+           
+         
+
+        
+           ) => handleMetadataPropertyChange('cicero', e.target.value)}
+            placeholder="0.25.x"
+            style={{ backgroundColor, color: textColor, borderColor: '#d9d9d9' }}
+          />
+         
+      
+    
 
+  );
+}
+
+export default TemplateMetadata; 
\ No newline at end of file
diff --git a/src/store/store.ts b/src/store/store.ts
index c06ad9bd..c2707d26 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -29,12 +29,28 @@ interface AppState {
   chatState: ChatState;
   aiConfig: AIConfig | null;
   chatAbortController: AbortController | null;
+  templateMetadata: {
+    author: string;
+    displayName: string;
+    version: string;
+    description: string;
+    license: string;
+    keywords: string[];
+    metadata: {
+      runtime: string;
+      template: string;
+      cicero: string;
+    };
+  };
+  templateLogic: string;
   setTemplateMarkdown: (template: string) => Promise;
   setEditorValue: (value: string) => void;
   setModelCto: (model: string) => Promise;
   setEditorModelCto: (value: string) => void;
   setData: (data: string) => Promise;
   setEditorAgreementData: (value: string) => void;
+  setTemplateMetadata: (metadata: AppState['templateMetadata']) => void;
+  setTemplateLogic: (logic: string) => Promise;
   rebuild: () => Promise;
   init: () => Promise;
   loadSample: (name: string) => Promise;
@@ -55,6 +71,20 @@ export interface DecompressedData {
   modelCto: string;
   data: string;
   agreementHtml: string;
+  templateMetadata?: {
+    author: string;
+    displayName: string;
+    version: string;
+    description: string;
+    license: string;
+    keywords: string[];
+    metadata: {
+      runtime: string;
+      template: string;
+      cicero: string;
+    };
+  };
+  templateLogic?: string;
 }
 
 const rebuildDeBounce = debounce(rebuild, 500);
@@ -98,6 +128,20 @@ const useAppStore = create()(
       isAIConfigOpen: false,
       isAIChatOpen: false,
       error: undefined,
+      templateMetadata: {
+        author: "",
+        displayName: "",
+        version: "1.0.0",
+        description: "",
+        license: "Apache-2",
+        keywords: [],
+        metadata: {
+          runtime: "typescript",
+          template: "clause",
+          cicero: "0.25.x"
+        }
+      },
+      templateLogic: "",
       samples: SAMPLES,
       chatState: {
         messages: [],
@@ -128,6 +172,20 @@ const useAppStore = create()(
             editorModelCto: sample.MODEL,
             data: JSON.stringify(sample.DATA, null, 2),
             editorAgreementData: JSON.stringify(sample.DATA, null, 2),
+            templateMetadata: {
+              author: "",
+              displayName: sample.NAME,
+              version: "1.0.0",
+              description: `Sample template: ${sample.NAME}`,
+              license: "Apache-2",
+              keywords: [],
+              metadata: {
+                runtime: "typescript",
+                template: "clause",
+                cicero: "0.25.x"
+              }
+            },
+            templateLogic: "",
           }));
           await get().rebuild();
         }
@@ -183,6 +241,12 @@ const useAppStore = create()(
       setEditorAgreementData: (value: string) => {
         set(() => ({ editorAgreementData: value }));
       },
+      setTemplateMetadata: (metadata: AppState['templateMetadata']) => {
+        set(() => ({ templateMetadata: metadata }));
+      },
+      setTemplateLogic: async (logic: string) => {
+        set(() => ({ templateLogic: logic }));
+      },
       generateShareableLink: () => {
         const state = get();
         const compressedData = compress({
@@ -190,12 +254,14 @@ const useAppStore = create()(
           modelCto: state.modelCto,
           data: state.data,
           agreementHtml: state.agreementHtml,
+          templateMetadata: state.templateMetadata,
+          templateLogic: state.templateLogic,
         });
         return `${window.location.origin}?data=${compressedData}`;
       },
       loadFromLink: async (compressedData: string) => {
         try {
-          const { templateMarkdown, modelCto, data, agreementHtml } = decompress(compressedData);
+          const { templateMarkdown, modelCto, data, agreementHtml, templateMetadata, templateLogic } = decompress(compressedData);
           if (!templateMarkdown || !modelCto || !data) {
             throw new Error("Invalid share link data");
           }
@@ -207,6 +273,20 @@ const useAppStore = create()(
             data,
             editorAgreementData: data,
             agreementHtml,
+            templateMetadata: templateMetadata || {
+              author: "",
+              displayName: "",
+              version: "1.0.0",
+              description: "",
+              license: "Apache-2",
+              keywords: [],
+              metadata: {
+                runtime: "typescript",
+                template: "clause",
+                cicero: "0.25.x"
+              }
+            },
+            templateLogic: templateLogic || "",
             error: undefined,
           }));
           await get().rebuild();
diff --git a/src/utils/templateApi.ts b/src/utils/templateApi.ts
new file mode 100644
index 00000000..dbe98b08
--- /dev/null
+++ b/src/utils/templateApi.ts
@@ -0,0 +1,122 @@
+import useAppStore from '../store/store';
+
+export interface TemplateApiFormat {
+  uri: string;
+  author: string;
+  displayName: string;
+  version: string;
+  description: string;
+  license: string;
+  keywords: string[];
+  metadata: {
+    $class: string;
+    runtime: string;
+    template: string;
+    cicero: string;
+  };
+  logo: null;
+  templateModel: {
+    $class: string;
+    typeName: string;
+    model: {
+      $class: string;
+      ctoFiles: Array<{
+        contents: string;
+        filename: string;
+      }>;
+    };
+  };
+  text: {
+    $class: string;
+    templateText: string;
+  };
+  logic: string | null;
+  sampleRequest: any | null;
+}
+
+export function formatTemplateForApi(): TemplateApiFormat {
+  const store = useAppStore.getState();
+  
+  // Generate a unique URI with timestamp to prevent duplicates
+  const timestamp = Date.now();
+  const baseName = store.templateMetadata.displayName.toLowerCase().replace(/\s+/g, '-') || 'template';
+  const uri = `resource:org.accordproject.protocol@1.0.0.Template#${baseName}-${timestamp}`;
+  
+  return {
+    uri,
+    author: store.templateMetadata.author,
+    displayName: store.templateMetadata.displayName,
+    version: store.templateMetadata.version,
+    description: store.templateMetadata.description,
+    license: store.templateMetadata.license,
+    keywords: store.templateMetadata.keywords,
+    metadata: {
+      $class: "org.accordproject.protocol@1.0.0.TemplateMetadata",
+      runtime: store.templateMetadata.metadata.runtime,
+      template: store.templateMetadata.metadata.template,
+      cicero: store.templateMetadata.metadata.cicero,
+    },
+    logo: null,
+    templateModel: {
+      $class: "org.accordproject.protocol@1.0.0.TemplateModel",
+      typeName: store.templateMetadata.displayName.toLowerCase().replace(/\s+/g, '') || 'template',
+      model: {
+        $class: "org.accordproject.protocol@1.0.0.CtoModel",
+        ctoFiles: [
+          {
+            contents: store.modelCto,
+            filename: "model.cto"
+          }
+        ]
+      }
+    },
+    text: {
+      $class: "org.accordproject.protocol@1.0.0.Text",
+      templateText: store.templateMarkdown
+    },
+    logic: store.templateLogic || null,
+    sampleRequest: null
+  };
+}
+
+export async function uploadTemplateToApi(apiUrl: string, template: TemplateApiFormat): Promise {
+  // Use the proxy path if the API URL contains localhost and /api
+  const baseUrl = apiUrl.includes('localhost') && apiUrl.includes('/api') ? '/api' : apiUrl;
+  return fetch(`${baseUrl}/templates`, {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    body: JSON.stringify(template),
+  });
+}
+
+export async function createAgreementFromTemplate(apiUrl: string, templateId: string, data: any): Promise {
+  // Use the proxy path if the API URL contains localhost and /api
+  const baseUrl = apiUrl.includes('localhost') && apiUrl.includes('/api') ? '/api' : apiUrl;
+  
+  // Generate a unique URI for the agreement (avoiding duplication)
+  const agreementUri = `resource:org.accordproject.protocol@1.0.0.Agreement#agreement-${Date.now()}`;
+  
+  // Construct the template URI from the template ID
+  const templateUri = `resource:org.accordproject.protocol@1.0.0.Template#${templateId}`;
+  
+  return fetch(`${baseUrl}/agreements`, {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    body: JSON.stringify({
+      uri: agreementUri,
+      templateId,
+      template: templateUri, // Use the template URI instead of template ID
+      data,
+      agreementStatus: 'DRAFT',
+      agreementParties: [],
+      signatures: [],
+      metadata: {
+        values: {} // Add the required values field
+      }
+    }),
+  });
+} 
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 6df154f8..4b2da0c1 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -3,25 +3,60 @@ import { defineConfig as defineVitestConfig } from "vitest/config";
 import react from "@vitejs/plugin-react";
 import nodePolyfills from "vite-plugin-node-stdlib-browser";
 import { visualizer } from "rollup-plugin-visualizer";
+
+// Get the API server URL from environment variable, with a fallback
+const API_SERVER_URL = process.env.VITE_API_SERVER_URL || 'http://ec2-3-80-94-40.compute-1.amazonaws.com:9000';
+
 // https://vitejs.dev/config/
 const viteConfig = defineViteConfig({
-  plugins: [nodePolyfills(), react(), visualizer({
+  plugins: [nodePolyfills(), visualizer({
     emitFile: true,
     filename: "stats.html",
   })],
   optimizeDeps: {
     include: ["immer"],
     needsInterop: ['@accordproject/template-engine'],
+    exclude: ['for-each']
+  },
+  server: {
+    proxy: {
+      '/api': {
+        target: API_SERVER_URL,
+        changeOrigin: true,
+        secure: false,
+        rewrite: (path) => path.replace(/^\/api/, ''),
+        configure: (proxy, _options) => {
+          proxy.on('error', (err, _req, _res) => {
+            console.log('proxy error', err);
+          });
+          proxy.on('proxyReq', (proxyReq, req, _res) => {
+            console.log('Sending Request to the Target:', req.method, req.url);
+          });
+          proxy.on('proxyRes', (proxyRes, req, _res) => {
+            console.log('Received Response from the Target:', proxyRes.statusCode, req.url);
+          });
+        },
+      }
+    }
+  },
+  build: {
+    rollupOptions: {
+      output: {
+        manualChunks: {
+          vendor: ['react', 'react-dom'],
+          accord: ['@accordproject/template-engine', '@accordproject/concerto-core'],
+        },
+      },
+    },
   },
 });
 
-
-// https://vitest.dev/config/
 const vitestConfig = defineVitestConfig({
+  plugins: [nodePolyfills(), react()],
   test: {
     globals: true,
     environment: "jsdom",
-    setupFiles: "./src/utils/testing/setup.ts",
+    setupFiles: ["./src/utils/testing/setup.ts"],
   },
 });