Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 59 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
# Sola ☀️

Sola is a full-stack *solar site intelligence platform* for small and mid-size solar EPCs, developers, and commercial rooftop sales teams.
Sola is an AI-powered solar decision-intelligence platform for solar EPCs, rooftop sales teams, sustainability managers, and public-sector planners.

The product helps teams find rooftops and land parcels with the most usable solar area and strongest project viability, then rank them quickly enough to turn GIS data into qualified pipeline.
It helps a real user decide which rooftops or parcels are worth a site visit by turning messy geospatial data into a ranked shortlist, a map view, and exportable recommendations in seconds instead of manual map trawling.

## Submission Snapshot

- **Problem:** solar site screening is slow, manual, and hard to compare across many rooftops and parcels.
- **User:** EPC pre-sales teams, rooftop developers, and city sustainability analysts.
- **Decision:** which sites deserve a survey, feasibility review, or budget allocation first.
- **Pipeline:** site data is ingested into PostGIS, scored, ranked, filtered, and rendered as GeoJSON for the frontend.
- **Output:** a ranked shortlist, interactive map, score breakdowns, and CSV/GeoJSON export.
- **Acceleration story:** the shortlist updates instantly as the user changes filters, reducing time-to-insight versus manual map review.
- **Cloud/GPU narrative:** the repo is structured to map cleanly onto Cloud Storage, BigQuery, GKE, and RAPIDS if the team wants to scale the demo beyond the local MVP.

## Real-World User and Decision

- **User:** solar EPC pre-sales teams, commercial rooftop developers, and city sustainability analysts.
- **Decision:** which sites deserve a site survey, feasibility review, or engineering budget first.
- **Bottleneck:** manual GIS review across many polygons, distance checks, and risk factors is slow and hard to compare consistently.
- **Outcome:** Sola ranks candidate sites by solar irradiance first, then maximum usable solar space, then flood risk and grid proximity so the best options can be acted on faster.

## MVP

Expand All @@ -29,11 +46,40 @@ The product helps teams find rooftops and land parcels with the most usable sola
## Customer Value

- Find high-potential commercial rooftops and sites without manual map trawling.
- Prioritize leads by usable area, irradiance, flood risk, and grid proximity.
- Prioritize leads by solar irradiance first, then usable solar space, flood risk, and grid proximity.
- Return ranked polygons as GeoJSON for map workflows and downstream analysis.
- Keep the data model ready for AI roof detection, shading analysis, and grid hosting layers.
- Give sales and development teams a shared source of truth for early site screening.

## Submission Fit

This repository is positioned to satisfy the hackathon brief as a practical data intelligence tool:

- **Data pipeline:** sample and PostGIS-backed geospatial site data is ingested, cleaned, scored, ranked, and rendered as GeoJSON for a map-first workflow.
- **Useful output:** ranked recommendations, interactive filtering, suitability scoring, and CSV/GeoJSON export.
- **Acceleration story:** the app collapses what is usually a manual screening workflow into an interactive shortlist that can be refreshed and re-ranked instantly as filters change.
- **Community value:** the same pattern applies to solar planning, public asset optimization, and other city-scale sustainability decisions.

## Judge Checklist

- A real-world user and problem are named.
- The decision bottleneck is explicit.
- The data pipeline is visible end to end.
- The output is useful for actual planning work.
- The acceleration claim is tied to faster shortlist generation.
- The cloud and GPU layer are described honestly as the scale-up path, not as a fake implementation claim.

## Google Cloud and NVIDIA Alignment

The current implementation is a local-first MVP, but the architecture is compatible with the required stack for a submission narrative or deployment path:

- **Cloud Storage:** store source rasters, parcel feeds, and cleaned GeoJSON layers.
- **BigQuery:** host large tabular site inventories, risk tables, and feature engineering outputs.
- **Google Kubernetes Engine:** run the API, frontend, and scheduled workers as scalable services.
- **NVIDIA acceleration layer:** use RAPIDS, cuDF, or Spark RAPIDS to accelerate large-scale geospatial joins, scoring, and ranking when the dataset grows.

In the current repo, PostGIS and the FastAPI scoring service provide the same product behavior locally; the cloud and GPU layers are the natural scale-up path for the submission.

## Current Stack

- Backend: Python 3.11, FastAPI async, SQLAlchemy 2.0, GeoAlchemy2.
Expand Down Expand Up @@ -123,6 +169,16 @@ NEXT_PUBLIC_API_URL=http://localhost:8000 npm run dev

Open [http://localhost:3000](http://localhost:3000).

The frontend is the primary demo surface for the hackathon story: it shows the user, the decision, the shortlist, and the acceleration effect in one screen.

## Demo Script

1. Open the map and explain the target user: solar EPC pre-sales teams and city planners.
2. Show the ranked list and explain the scoring order.
3. Change the district, score, or minimum area to demonstrate instant re-ranking.
4. Open a top site and point to the map, score, and export path.
5. Explain that Cloud Storage, BigQuery, GKE, and RAPIDS are the natural scale-up path for larger public or utility datasets.

## API Examples

List all top-ranked sites:
Expand Down
16 changes: 8 additions & 8 deletions app/scoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@
- structural_score : structural/land-use viability (0–1)

Default weights (sum to 1.0):
usable_area 0.30
irradiance 0.25
flood_risk 0.20
grid_proximity 0.15
structural 0.10
irradiance 0.40
usable_area 0.30
flood_risk 0.15
grid_proximity 0.10
structural 0.10
"""
from __future__ import annotations
import numpy as np
import pandas as pd

DEFAULT_WEIGHTS = {
"irradiance": 0.40,
"usable_area": 0.30,
"irradiance": 0.25,
"flood_risk": 0.20,
"grid_proximity": 0.15,
"flood_risk": 0.15,
"grid_proximity": 0.10,
"structural": 0.10,
}

Expand Down
6 changes: 3 additions & 3 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class Settings(BaseSettings):
default_srid: int = 4326
max_page_size: int = 500

score_usable_area_weight: float = 0.35
score_irradiance_weight: float = 0.30
score_flood_risk_weight: float = 0.20
score_irradiance_weight: float = 0.40
score_usable_area_weight: float = 0.30
score_flood_risk_weight: float = 0.15
score_grid_proximity_weight: float = 0.15

@computed_field # type: ignore[prop-decorator]
Expand Down
6 changes: 3 additions & 3 deletions backend/app/services/suitability_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ def __init__(self, settings: Settings | None = None) -> None:
self.settings = settings or get_settings()

def score(self, inputs: SuitabilityInputs) -> float:
area_score = self._clamp(inputs.usable_area_sqm / 10_000)
irradiance_score = self._clamp((inputs.annual_ghi_kwh_m2 - 1_300) / 800)
area_score = self._clamp(inputs.usable_area_sqm / 10_000)
flood_score = 1 - self._clamp(inputs.flood_risk_score)
grid_score = 1 - self._clamp(inputs.grid_distance_km / 10)

weighted_score = (
area_score * self.settings.score_usable_area_weight
+ irradiance_score * self.settings.score_irradiance_weight
irradiance_score * self.settings.score_irradiance_weight
+ area_score * self.settings.score_usable_area_weight
+ flood_score * self.settings.score_flood_risk_weight
+ grid_score * self.settings.score_grid_proximity_weight
)
Expand Down
16 changes: 16 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,28 @@

Sola is organized around a geospatial API, a map-first frontend, and offline GIS processing.

## System Overview

- **Ingest:** curated rooftop or parcel data enters the project as CSV or GeoJSON.
- **Store:** PostGIS holds the operational site inventory and spatial indexes.
- **Score:** the suitability service ranks each site using irradiance, usable area, flood risk, and grid proximity.
- **Serve:** FastAPI returns ranked GeoJSON to the frontend.
- **Visualize:** the Next.js app shows the ranked shortlist, filters, and site-level details.
- **Export:** users can download CSV and GeoJSON for GIS review or planning workflows.

- FastAPI serves scored candidate sites as GeoJSON.
- PostgreSQL 16 with PostGIS 3.4 stores polygons and spatial indexes.
- The suitability service keeps scoring logic independent from geometry extraction, which makes future AI roof detection a data enrichment step rather than an API rewrite.
- GIS processing scripts and notebooks handle heavy raster/vector work before curated outputs enter PostGIS.
- Grafana monitors data freshness, API health, and post-installation system performance.

## Scale-Up Path

- Cloud Storage can hold raw imagery, parcel layers, and processed exports.
- BigQuery can become the analytical store for large site inventories and feature tables.
- GKE can host the API and frontend when the demo needs a managed deployment.
- RAPIDS or cuDF can accelerate the batch scoring and join step when the dataset grows.

## Extension points

- AI roof detection can populate `ai_detection_status`, refined roof polygons, shading loss, and usable area.
Expand Down
6 changes: 6 additions & 0 deletions docs/public-demo.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Use this path when you want someone outside your network to open Sola in a browser.

The goal is not to deploy every internal service. The goal is to give judges a stable, fast map-first demo that explains the user, the decision, and the ranked output.

## Option A: Vercel Frontend Demo

This is the fastest public demo. It deploys the Next.js app and uses bundled sample data when no public API URL is configured.
Expand All @@ -13,6 +15,8 @@ This is the fastest public demo. It deploys the Next.js app and uses bundled sam
5. Leave `NEXT_PUBLIC_API_URL` unset for the public sample-data demo.
6. Deploy and share the generated `https://...vercel.app` URL.

This option is enough for a submission demo because the UI still shows the ranking, filters, score breakdown, and export flow without requiring a public backend.

## Option B: Hosted API Later

When the FastAPI backend is hosted publicly, set this frontend environment variable in Vercel:
Expand All @@ -27,6 +31,8 @@ Then redeploy the frontend. The app will fetch live GeoJSON from:
/api/v1/sites?limit=100
```

Use this when you want the submission to show a live backend instead of sample data.

## Local Preview Before Sharing

```bash
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { Metadata } from "next";
import "./globals.css";

export const metadata: Metadata = {
title: "Sola",
description: "Solar site intelligence for commercial rooftops and viable project discovery.",
title: "Sola | Solar Decision Intelligence",
description: "AI-powered solar site ranking and decision support for EPC teams, planners, and rooftop developers.",
};

export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
Expand Down
Loading