WordPress REST API: Talking to a Weather API for Daily Surf Condition Stats

By Jonathan Aquarone

NY SURF CONDITIONS

Only Ten API calls a day - Check Early Morning

The surf application tracks multiple surf locations along New York’s coastline, including Rockaway Beach, Long Beach, Lido Beach, Gilgo Beach, and Southampton. Each location is defined with precise latitude and longitude coordinates, enabling us to fetch specific oceanic and weather data from the StormGlass API. When a user checks conditions, the app makes parallel API requests for all locations, ensuring comprehensive coverage of the NY surfing scene.

A parallel API request refers to making multiple API calls at the same time (simultaneously) rather than making them one after the other (sequentially)

This multi-location approach allows surfers to quickly compare conditions across different spots and choose the best location for their surf session.

Intelligent Surf Condition Rating Algorithm

Our custom rating algorithm evaluates multiple factors to generate an easy-to-understand 5-point rating scale for each location. The algorithm considers wave height (scoring 0-3 points, with 1.5-3ft being ideal), wave period (0-3 points, with periods over 10 seconds scoring highest), and wind speed (0-4 points, with speeds under 10mph being optimal).

These factors are weighted and combined to create a final surf score from 1 to 5, where 5 represents perfect surfing conditions. This simplified rating system helps surfers quickly assess conditions without needing to interpret complex meteorological data.

Advanced Two-Layer Caching System

To manage API rate limits and improve performance, we implement a two-layer caching system. On the server side, WordPress transients store API responses for 24 hours, preventing unnecessary calls to the StormGlass API.

WordPress transients allow you to store data temporarily in the WordPress database rather than retrieving it each time from an external source or recalculating it. Transients have an expiration time, after which they are considered stale. Once expired, WordPress automatically deletes them from the database the next time they are accessed.

On the client side, localStorage tracks API usage and enforces a daily limit on condition checks. This caching strategy not only respects the StormGlass API’s rate limits but also significantly improves the app’s response time by serving cached data when available, while ensuring users still receive reasonably current conditions.

Project Structure

Before diving into the implementation, let’s understand the file structure and organization of our surf conditions app:

/wp-content/themes/your-theme/
├── functions.php                    # Main functionality and hooks
├── templates/
│   └── template-surf.php           # Main Surf App template
├── inc/
│   └── class-ny-surf-conditions-api.php  # API Controller class
├── js/
│   ├── surf-app.js                 # Main frontend logic
│   └── min/
│       └── surf-app.min.js         # Minified version
└── css/
    ├── surf-app.css                # Surf app styles
    └── min/
        ├── surf-blog-post.min.css  # Blog template styles
        └── single-blog.min.css     # Single post styles

Key Components and Their Roles

Template Layer (page-surf-app.php)

  • Base page structure with WordPress header/footer
  • Button/timer container layout
  • Dynamic surf results grid area
  • Base styling containers

API Layer (class-ny-surf-conditions-api.php)

  • WordPress REST API endpoint setup
  • StormGlass API integration and data fetching
  • Transient caching implementation (24-hour cache)
  • Error handling and logging
  • Environment-specific API key management

Frontend Layer (surf-app.js)

  • Surf spot location definitions and coordinates
  • API request handling and rate limiting
  • Surf condition calculations and rating system
  • UI rendering and updates
  • Local storage for API call tracking

Integration Layer (functions.php)

  • REST API Controller Integration
    • Load controller class
    • Register API routes
    • Set up nonce security
    • Configure response formats
  • StormGlass API Setup
    • API key management
    • Environment detection
    • Authentication handling
    • Asset loading and localization

Building the WordPress Surf Conditions App Step by Step

When building this small app, I would first create all of the files and then proceed to create a page or template. Since this is a one-off project and that I can display the page contents onto this post via a short code, I opted to create a page.

Set Up the StormGlass API in wp-config.php

  • Sign up at StormGlass.io
  • Get your API key
  • Add to wp-config.php:
define('STORMGLASS_API_KEY', 'your-api-key-here');

Create the API Handler in class-ny-surf-conditions-api.php

class NY_Surf_Conditions_API extends WP_REST_Controller {
    private $api_key;
    
    public function __construct() {
        $this->api_key = STORMGLASS_API_KEY;
        $this->namespace = 'surf-app/v1';
        $this->rest_base = 'conditions';
    }

    public function register_routes() {
        register_rest_route($this->namespace, '/' . $this->rest_base, [
            'methods' => 'GET',
            'callback' => [$this, 'get_conditions'],
            'permission_callback' => '__return_true'
        ]);
    }

    public function get_conditions($request) {
        $lat = $request->get_param('lat');
        $lng = $request->get_param('lng');
        
        // Make StormGlass API request
        $response = wp_remote_get("https://api.stormglass.io/v2/weather/point", [
            'headers' => ['Authorization' => $this->api_key],
            'body' => [
                'lat' => $lat,
                'lng' => $lng,
                'params' => 'waveHeight,wavePeriod,windSpeed,windDirection,waterTemperature'
            ]
        ]);

        return rest_ensure_response($response['body']);
    }
}

Create the Frontend JavaScript in surf-app.js

// Define surf spots
const SURF_SPOTS = {
    rockaway: {
        name: 'Rockaway Beach',
        lat: 40.5825,
        lng: -73.8358
    }
    // Add more spots as needed
};

// Check conditions button
document.getElementById('checkSurfBtn').addEventListener('click', async () => {
    const results = await Promise.all(
        Object.values(SURF_SPOTS).map(spot => 
            fetch(`/wp-json/surf-app/v1/conditions?lat=${spot.lat}&lng=${spot.lng}`)
            .then(res => res.json())
        )
    );
    
    displayResults(results);
});

// Display results function
function displayResults(results) {
    const html = results.map(result => `
        <div class="surf-card">
            <h3>${result.location}</h3>
            <p>Wave Height: ${result.waveHeight}ft</p>
            <p>Wind: ${result.windSpeed}mph</p>
        </div>
    `).join('');
    
    document.getElementById('surfResults').innerHTML = html;
}

Hook Everything Together in functions.php

// Load the API controller
require_once get_template_directory() . '/inc/class-ny-surf-conditions-api.php';

// Initialize REST API
add_action('rest_api_init', function() {
    $controller = new NY_Surf_Conditions_API();
    $controller->register_routes();
});

// Enqueue assets
function enqueue_surf_app_assets() {
    wp_enqueue_style('surf-app', get_template_directory_uri() . '/css/surf-app.css');
    wp_enqueue_script('surf-app', get_template_directory_uri() . '/js/surf-app.js', [], '1.0', true);
}
add_action('wp_enqueue_scripts', 'enqueue_surf_app_assets');

Conclusion

This implementation creates a fully functional surf conditions checker that:

  • Integrates seamlessly with WordPress
  • Provides real-time surf conditions
  • Implements proper data caching
  • Manages API rate limits
  • Presents data in a user-friendly format

The app can be easily embedded on any page using the [/*surf_conditions*/] shortcode, and the modular structure allows for easy maintenance and updates.