Skip to content

JavaScript Examples

JavaScript/TypeScript examples for browser and Node.js environments.

Browser (Fetch API)

/**
 * Tessellate Renewables API Client
 */
class TessellateClient {
  constructor(apiKey = null) {
    this.baseUrl = 'https://api.tessellaterenewables.com';
    this.headers = {
      'Content-Type': 'application/json',
    };
    if (apiKey) {
      this.headers['X-API-Key'] = apiKey;
    }
  }

  async request(endpoint, method = 'GET', body = null) {
    const options = {
      method,
      headers: this.headers,
    };
    if (body) {
      options.body = JSON.stringify(body);
    }

    const response = await fetch(`${this.baseUrl}${endpoint}`, options);

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || 'API request failed');
    }

    return response.json();
  }

  async getSolarResource(latitude, longitude) {
    return this.request('/solar/resource', 'POST', { latitude, longitude });
  }

  async quickOptimize(latitude, longitude, capacityKw, objective = 'energy') {
    return this.request('/solar/optimization/quick', 'POST', {
      site: { latitude, longitude, capacity_kw: capacityKw },
      objective,
    });
  }

  async fullOptimize(latitude, longitude, capacityKw, options = {}) {
    const { objective = 'energy', maxIterations = 50, bounds = null } = options;

    // Submit job
    const job = await this.request('/solar/optimization/run', 'POST', {
      site: { latitude, longitude, capacity_kw: capacityKw },
      objective,
      max_iterations: maxIterations,
      bounds,
    });

    // Poll for results
    return this.pollJob(job.job_id);
  }

  async pollJob(jobId, intervalMs = 2000) {
    while (true) {
      const result = await this.request(`/solar/optimization/${jobId}`);

      if (result.status === 'completed') {
        return result;
      } else if (result.status === 'failed') {
        throw new Error(result.error_message || 'Job failed');
      }

      await new Promise((resolve) => setTimeout(resolve, intervalMs));
    }
  }

  async predict(latitude, longitude, capacityKw, params = {}) {
    const {
      tilt = 30,
      azimuth = 180,
      dcAcRatio = 1.2,
      gcr = 0.4,
    } = params;

    return this.request('/solar/predict', 'POST', {
      latitude,
      longitude,
      capacity_kw: capacityKw,
      tilt,
      azimuth,
      dc_ac_ratio: dcAcRatio,
      gcr,
    });
  }
}

// Usage
const client = new TessellateClient();

async function optimizeSite() {
  try {
    const result = await client.quickOptimize(35.0, -110.0, 1000, 'energy');

    console.log('Optimal Parameters:');
    console.log(`  Tilt: ${result.optimal_parameters.tilt}°`);
    console.log(`  Azimuth: ${result.optimal_parameters.azimuth}°`);

    console.log('Energy Performance:');
    console.log(`  Annual Energy: ${result.energy_metrics.annual_energy_mwh.toLocaleString()} MWh`);
    console.log(`  Capacity Factor: ${(result.energy_metrics.capacity_factor * 100).toFixed(1)}%`);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

optimizeSite();

Node.js with Axios

const axios = require('axios');

class TessellateClient {
  constructor(apiKey = null) {
    this.client = axios.create({
      baseURL: 'https://api.tessellaterenewables.com',
      headers: {
        'Content-Type': 'application/json',
        ...(apiKey && { 'X-API-Key': apiKey }),
      },
    });
  }

  async quickOptimize(latitude, longitude, capacityKw, objective = 'energy') {
    const { data } = await this.client.post('/solar/optimization/quick', {
      site: { latitude, longitude, capacity_kw: capacityKw },
      objective,
    });
    return data;
  }

  // ... other methods
}

module.exports = TessellateClient;

TypeScript

interface Site {
  latitude: number;
  longitude: number;
  capacity_kw: number;
}

interface OptimalParameters {
  tilt: number;
  azimuth: number;
  dc_ac_ratio: number;
  gcr: number;
}

interface EnergyMetrics {
  annual_energy_mwh: number;
  capacity_factor: number;
  specific_yield: number;
  performance_ratio: number;
}

interface FinancialMetrics {
  lcoe_cents_per_kwh: number;
  npv_dollars: number;
  irr_percent: number;
  payback_years: number;
}

interface OptimizationResult {
  optimal_parameters: OptimalParameters;
  energy_metrics: EnergyMetrics;
  financial_metrics: FinancialMetrics;
}

class TessellateClient {
  private baseUrl: string;
  private headers: Record<string, string>;

  constructor(apiKey?: string) {
    this.baseUrl = 'https://api.tessellaterenewables.com';
    this.headers = {
      'Content-Type': 'application/json',
    };
    if (apiKey) {
      this.headers['X-API-Key'] = apiKey;
    }
  }

  async quickOptimize(
    latitude: number,
    longitude: number,
    capacityKw: number,
    objective: 'energy' | 'lcoe' | 'npv' | 'irr' = 'energy'
  ): Promise<OptimizationResult> {
    const response = await fetch(`${this.baseUrl}/solar/optimization/quick`, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({
        site: { latitude, longitude, capacity_kw: capacityKw },
        objective,
      }),
    });

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

    return response.json();
  }
}

// Usage
const client = new TessellateClient();

async function main() {
  const result = await client.quickOptimize(35.0, -110.0, 1000, 'energy');
  console.log(`Tilt: ${result.optimal_parameters.tilt}°`);
}

main();

React Hook Example

import { useState, useCallback } from 'react';

function useSolarOptimization() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [result, setResult] = useState(null);

  const optimize = useCallback(async (latitude, longitude, capacityKw, objective = 'energy') => {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch(
        'https://api.tessellaterenewables.com/solar/optimization/quick',
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            site: { latitude, longitude, capacity_kw: capacityKw },
            objective,
          }),
        }
      );

      if (!response.ok) {
        throw new Error('Optimization failed');
      }

      const data = await response.json();
      setResult(data);
      return data;
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setLoading(false);
    }
  }, []);

  return { optimize, loading, error, result };
}

// Usage in component
function SolarOptimizer() {
  const { optimize, loading, error, result } = useSolarOptimization();

  const handleSubmit = async (e) => {
    e.preventDefault();
    await optimize(35.0, -110.0, 1000, 'energy');
  };

  return (
    <div>
      <button onClick={handleSubmit} disabled={loading}>
        {loading ? 'Optimizing...' : 'Optimize'}
      </button>

      {error && <p className="error">{error}</p>}

      {result && (
        <div>
          <p>Optimal Tilt: {result.optimal_parameters.tilt}°</p>
          <p>Annual Energy: {result.energy_metrics.annual_energy_mwh.toLocaleString()} MWh</p>
        </div>
      )}
    </div>
  );
}

Error Handling

async function safeOptimize(client, latitude, longitude, capacityKw) {
  try {
    const result = await client.quickOptimize(latitude, longitude, capacityKw);
    return { success: true, data: result };
  } catch (error) {
    if (error.response) {
      // Server responded with error
      return {
        success: false,
        error: error.response.data.message || 'Server error',
        status: error.response.status,
      };
    } else if (error.request) {
      // No response received
      return {
        success: false,
        error: 'Network error - no response received',
      };
    } else {
      // Request setup error
      return {
        success: false,
        error: error.message,
      };
    }
  }
}