Project Details

Dashboard: San Diego County Beach Conditions
Topic: Beach & ocean conditions, daily water quality
Beaches: covered 24 San Diego County beaches
Data sources: CDIP, Open-Meteo, NOAA, County of San Diego
Update frequency: Daily at 9:00 AM Pacific
Data range: Current day only
Tools: Python, Playwright, Docker, Google Cloud Run, Google Cloud Scheduler, BigQuery, Google Sheets, Tableau
Published: San Diego County Beach Conditions


Need a Custom Dashboard?

I build executive dashboards like this for businesses.

Clair Wyant Header Image

Clair Wyant

BI and Data Architecture Consultant


San Diego Beach Conditions, Updated Every Morning

This is a daily San Diego beach conditions dashboard: one place to check current surf, water temperature, UV, wind & water-quality closures before you go. Because it refreshes every morning and shows the current day only, it reads as a San Diego surf report today, not a forecast. It covers the whole coastline, so you can pull a North County surf report for Oceanside, Carlsbad & Encinitas, or check the South Bay beaches near the border, in the same view. No account and no app: open it, scan the table or map, and go.

Dashboard: San Diego County Beach Conditions

Topic: Beach & ocean conditions, daily water quality

Beaches Covered: 24 San Diego County beaches

Data Sources: CDIP, Open-Meteo, NOAA, County of San Diego

Update Frequency: Daily at 9:00 AM Pacific

Data Range: Current day only

Tools: Python, Playwright, Docker, Google Cloud Run, Google Cloud Scheduler, BigQuery, Google Sheets, Tableau

Published: San Diego County Beach Conditions

Project Motivation

I live in San Diego & am a beachgoer. I'm picky about when I go solely based on water & weather conditions. This reason for no forecast is due to the massive changes that can happen based on the forecast, what actually happens that day & the forecast on the day. Also, some data points don't have forecasts. All of these reasons make it the most logical for the current day only. This dashboard provides a cumulative view of all relevant data points in one place. Bacteria data point exists due to the off & on issue of high bacteria levels in the ocean water due to sewage from the Tijuana, Mexico River plus the impact from storms.

Dashboard Features

The dashboard has two linked views: a data table & a geographic map, both sharing the same bacteria status color scale, green (OK), yellow (Advisory), red (Closure), blue (No Report).

The table lists all 24 beaches sorted north to south down the coastline, not alphabetically. Each row shows the beach name, its city, & every data column in a single view: surf height, wave period with a plain-language quality label, swell direction, water temperature, air temperature, UV index with an exposure label, wind, & bacteria status.

The map plots each beach as a color-coded point on a San Diego County map. Hovering over any point shows a tooltip with all metrics for that location. The color of each point reflects bacteria status, so closures & advisories are visible across the entire county at a glance without scanning down the table.

The two views are linked by a click action. Clicking a beach in the table highlights it on the map. Clicking a point on the map highlights that beach in the table. This makes it easy to scan the full data picture in one view & locate the beach geographically in the other.

Units & plain-language labels are built into the values in the underlying data, not applied as Tableau formatting. A wave period reads "16.7s (Powerful / Excellent)." A UV reading reads "8.5 (Very High)." No legend lookup required.

Beaches Covered

All 24 beaches are listed north to south, first by city, then by beach within each city. Coverage runs from the North County San Diego breaks in Oceanside, Carlsbad & Encinitas down to the South Bay, so a North County surf report sits in the same view as the rest of the county.

San Clemente: Trestles, San Onofre

Oceanside: Oceanside Harbor, Oceanside Pier

Carlsbad: Tamarack, Batiquitos Lagoon

Encinitas: Moonlight Beach, Swamis, Cardiff Reef

Solana Beach: Fletcher Cove

Del Mar: 13th Street, 15th Street

La Jolla: Torrey Pines, Blacks Beach, Scripps Pier, La Jolla Shores, Windansea

San Diego: Crystal Pier, Mission Bay Entrance, Sunset Cliffs, Point Loma

Coronado: Coronado Beach

Imperial Beach: Imperial Beach Pier, Border Field

What Each Data Point Means

Surf is the wave height range at each beach in feet, sourced from CDIP's nearshore wave model. This is estimated height offshore of the break, not the face height a surfer sees after the wave shoals and steepens. It reads lower than what's actually breaking at the sand. See Known Limits in the build section below.

Wave Period (Power / Surf Quality) is the time in seconds between waves, with a plain-language quality label. Longer periods (14+ seconds) mean more organized swell with more energy. Shorter periods (under 8 seconds) mean wind-driven chop with less power & predictability. The label translates the number so no surf knowledge is required.

Swell is the direction the swell is coming from. Combined with a beach's orientation to the coast, this determines how directly the energy is hitting each spot.

Water is current ocean water temperature in °F from Open-Meteo.

Air Temp is current air temperature at each beach location in °F.

UV Index (Exposure Risk) is the UV Index with a plain-language exposure label. San Diego's UV is consistently high year-round, so this column helps with sun-protection planning regardless of cloud cover.

Wind shows current wind speed & direction. Offshore wind (land to ocean) cleans up surf & improves conditions. Onshore wind (ocean to land) chops it up.

Bacteria Status is the county's current water-quality posting for that beach: OK, Advisory, Closure, or No Report. See the section below for background on why this column is here.

Bacteria Status & the Tijuana River

San Diego's southernmost beaches face an ongoing water-quality issue tied to the Tijuana River. The river flows north across the US-Mexico border & empties into the Pacific Ocean near Border Field State Park, carrying sewage, storm runoff & untreated wastewater from Tijuana, Mexico. After rain events, bacteria levels spike, triggering closures that can extend as far north as Coronado & sometimes beyond.

This is not a new problem & not a fully resolved one. The International Boundary & Water Commission (IBWC) has worked on infrastructure improvements for years, but post-storm closures remain frequent. Affected beaches can stay closed for days after rain even after skies clear, depending on how long bacteria levels take to drop back to safe levels.

This dashboard pulls live closure & advisory data from the County of San Diego's beach monitoring program (sdbeachinfo.com), which is the official source for water-quality postings in the county. The color scale in the map view makes the status of every beach visible at a glance: green is OK, yellow is Advisory, red is Closure, & blue means no status report has been issued for that beach. For anyone planning to swim at or near the US-Mexico border, checking this column first is the most important step.

How This Dashboard Was Built

A daily dashboard covering 24 San Diego County beaches, answering one question: should I go today, and where? It pulls surf, water and air temperature, UV, wind, and live water-quality closures into a single table and map.

Where the Data Comes From

Surf height, wave period, swell direction: CDIP MOP, Scripps Institution of Oceanography's nearshore wave model

Water & air temp, UV, wind: Open-Meteo

Rip current risk, high surf advisories: NOAA / National Weather Service San Diego

Advisories, warnings, closures: County of San Diego (sdbeachinfo.com)

All four are free and require no API keys.

The important choice was CDIP over a global weather model. Global models flatten all of San Diego to one number; tested side by side, they overestimated nearshore wave height by about 1.8× and missed the roughly 4× variation between beaches on the same day. CDIP models the coast at ~100-meter resolution and publishes named surf spots, which is why the dashboard can say Windansea and Scripps Pier are different.

How the Data Is Pulled

A single Python script does the whole job, and each source needs a different technique:

CDIP, requested through the THREDDS NetCDF Subset Service, which returns CSV directly, so no scientific data libraries are needed.

Open-Meteo and NWS, plain JSON over HTTPS via Python's standard library.

The county water-quality feed, the hard one. It's an internal web app protected by session tokens that can't be replicated with a normal HTTP request; direct calls return "Invalid Login." The script uses Playwright to drive a headless Chrome browser, load the page like a person would, and read the data the app fetches for itself.

The script then reshapes everything into one row per beach and writes it to a Google Sheet (via gspread) and to BigQuery for history.

It's packaged in a Docker container so the browser and all dependencies travel with it.

How It Stays Current

Google Cloud Scheduler triggers a Cloud Run job every morning at 9:00 AM Pacific. The job runs the Python script, overwrites the Google Sheet, and appends a copy to BigQuery for history. Tableau reads the sheet and refreshes.

Code lives in GitHub; pushing a change automatically rebuilds and redeploys the container.

Mid-morning timing is deliberate, CDIP blends live buoy readings into the current day, so a 9 AM run reflects real measured conditions rather than pure model output.

Running cost is under $1/month.

The Dashboard

Built in Tableau: a table of all 24 beaches plus a map, sharing a color scale for water-quality status.

Presentation was pushed into the data rather than handled with Tableau calculations, units live in the values (4.1-5.3 ft), and technical numbers carry plain-language meaning (16.7s (Powerful / Excellent), 8.5 (Very High)). Sort columns order beaches north to south down the coastline instead of alphabetically.

Who Did What

The data pipeline and its cloud automation, the Python script, the container, the scheduled job, the connection into Google Sheets, were set up by Claude (Anthropic's AI assistant), working from my direction.

Everything else is mine: the concept, the requirements, all decisions about what data mattered and how it should read, the entire Tableau buildout, publishing, and the dashboard refresh automation. Claude contributed some ideas along the way; the design & development is mine.

Known Limits

Surf heights are estimates. The model reports wave height offshore of the break; converting that to the height a surfer sees uses an approximation that hasn't been formally calibrated.

Water quality mirrors the county's postings and can go stale if the source changes. sdbeachinfo.com remains the official word.

The county feed is an undocumented internal endpoint and may break without notice.

Who This Dashboard Is For

Beachgoers choosing where to go today based on conditions rather than habit or proximity.

Surfers checking wave height, period & swell direction before heading out, with the added context of seeing how every other San Diego County spot compares on the same morning.

Swimmers & families who want water temperature & bacteria status before committing to a specific beach, especially anyone going south toward Imperial Beach or Coronado after recent rain.

UV-sensitive visitors who want exposure risk before spending hours in the sun.

South San Diego County residents keeping track of Tijuana River water-quality closures, which can move quickly after storms & affect multiple beaches at once.

Anyone who has driven to a beach only to find it choppy, closed, or colder than expected will find this useful. The point is to answer the question before the drive, not after it.

FAQ

Why doesn't the dashboard show a forecast? Several reasons. Bacteria status has no forecast, county postings reflect current tested conditions, not projected ones. Surf & weather forecasts exist, but the variation between what any forecast says & what's actually happening at the water on a given morning is large enough to make current readings more useful. The decision to go to a beach today is best made with today's data.

How often does the dashboard update & at what time? The data pipeline runs every morning at 9:00 AM Pacific via Google Cloud Scheduler. Mid-morning timing is deliberate: CDIP blends live buoy readings into its model throughout the morning, so a 9:00 AM run captures real measured conditions rather than pure overnight model output.

What does each bacteria status mean? Green (OK) means the county has not issued any advisory or closure for that beach. Yellow (Advisory) means bacteria levels are elevated but the beach is technically open. Red (Closure) means the beach is closed due to bacteria levels exceeding safe limits. Blue (No Report) means the county has not issued a current status for that beach.

What is the Tijuana River issue? The Tijuana River carries untreated sewage & storm runoff from Tijuana, Mexico, across the US-Mexico border & into the Pacific Ocean near Border Field. After rain events, bacteria levels spike & closures can extend to Imperial Beach & occasionally Coronado. The issue is long-standing. For anyone visiting southern San Diego County beaches after rain, checking bacteria status is the first step.

Why are surf heights listed as estimates? The model reports wave height offshore of the break. The actual wave face a surfer sees is taller, because the wave shoals as it moves into shallower water near shore. Converting offshore model height to breaking face height uses an approximation that varies by beach geometry & has not been calibrated spot by spot. The numbers are most useful as relative comparisons between beaches on the same day rather than absolute measurements.

Is this affiliated with the County of San Diego, CDIP, NOAA or any official agency? No. This is an independent project. Data is pulled from official public sources, & sdbeachinfo.com remains the authoritative source for water-quality decisions. This dashboard is a convenience tool, not an official resource.

Does the dashboard show tides? No. The dashboard focuses on current surf conditions, water temperature, UV, wind & water-quality status, so it does not include tide data. For tide times, a source like NOAA Tides & Currents is the place to check, then use this dashboard for everything else before you head out.

Can I use this as a North County San Diego surf report? Yes. The North County San Diego beaches, Oceanside, Carlsbad & Encinitas, are included alongside every other San Diego County spot, so you can read a North County surf report and compare it with the rest of the coastline in one view.


Want a dashboard like this for your business?

This San Diego surf and beach conditions dashboard is a personal project, but the work behind it is exactly what I do professionally: turning raw, messy source data into a clear, interactive view your team can actually use. If you need something similar, see my data visualization and Tableau consulting services.

You’ll be talking to me, not a sales team

Clair Wyant, BI and Data Architecture Consultant

Clair Wyant

BI & Data Architecture Consultant, San Diego + remote

7+ years building executive reporting · $800M+ in decisions the dashboards supported · Salesforce Certified Tableau Desktop Foundations · You work directly with me, start to finish.

Hi, I’m Clair. Let’s find your fastest reporting wins.

Tell me where the reporting hurts. The first call is a relaxed intro call: what's getting in the way, how I might help, and whether we're a fit. Nothing to share to start, nothing to prepare. You work directly with me, the same senior consultant leadership has trusted on decisions worth more than $800 million. No junior handoffs, no sales reps, and no pressure.

Book your free intro call