diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index c2ca8e4bd..03d0a5a47 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -43,13 +43,9 @@ jobs:
             packages/${{ matrix.package }}/dist/*.whl
           name: dist-${{ matrix.package }}
 
-  build_basemap:
-    name: Build basemap package (${{ matrix.os }})
-    needs: [build_data]
-    strategy:
-      matrix:
-        os: [ubuntu-22.04, windows-2019, macos-13, macos-14]
-    runs-on: ${{ matrix.os }}
+  build_sdist:
+    name: Build basemap sdist
+    runs-on: ubuntu-22.04
     steps:
       - uses: actions/checkout@v4
 
@@ -59,13 +55,127 @@ jobs:
           python-version: "3.9"
 
       - name: Build sdist
-        if: matrix.os == 'ubuntu-22.04'
         run: |
           cd packages/basemap
           python -m pip install build
           python -m build --sdist
 
-      - name: Build wheels
+      - uses: actions/upload-artifact@v4
+        with:
+          path: packages/basemap/dist/*.tar.gz
+          name: basemap-sdist
+
+  build_wheels:
+    name: Build wheels on ${{ matrix.os }}
+    needs: [build_data, build_sdist]
+    strategy:
+      matrix:
+        os: [ubuntu-22.04, windows-2019, macos-13, macos-14]
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.9"
+
+      - name: Download basemap sdist
+        uses: actions/download-artifact@v4
+        with:
+          name: basemap-sdist
+          path: ./sdist/
+
+      - name: Download data packages
+        uses: actions/download-artifact@v4
+        with:
+          pattern: dist-basemap_data*
+          path: ./data_packages/
+          merge-multiple: true
+
+      - name: Install data packages (Linux/macOS)
+        if: runner.os != 'Windows'
+        shell: bash
+        run: |
+          # Debug - show what we downloaded
+          ls -la ./data_packages/
+
+          # Install the data packages
+          python -m pip install ./data_packages/*.whl
+
+          # Verify they're installed
+          python -c "import mpl_toolkits.basemap_data; print('Data package installed')"
+
+      # Install the data packages (Windows)
+      - name: Install data packages (Windows)
+        if: runner.os == 'Windows'
+        shell: pwsh
+        run: |
+          # Debug - show what we downloaded
+          Get-ChildItem -Path "./data_packages" -Recurse
+
+          # Find all wheel files
+          $wheels = Get-ChildItem -Path "./data_packages" -Filter "*.whl" -Recurse
+
+          # Install each wheel file
+          foreach ($wheel in $wheels) {
+            Write-Host "Installing $($wheel.FullName)"
+            python -m pip install $wheel.FullName
+          }
+
+          # Show installed packages
+          python -m pip list | Select-String "mpl_toolkits.basemap"
+
+          # Try different import paths
+          Write-Host "Trying to import basemap_data..."
+          python -c "import mpl_toolkits.basemap_data; print('mpl_toolkits.basemap_data imported successfully')"
+
+      - name: Extract sdist (Linux/macOS)
+        if: runner.os != 'Windows'
+        shell: bash
+        run: |
+          # Create extraction directory in the workspace
+          mkdir -p ./sdist_extract
+
+          # Extract using tar (Unix-style)
+          tar -xvf ./sdist/*.tar.gz -C ./sdist_extract
+
+          # Get the extracted directory name
+          EXTRACTED_DIR=$(ls -d ./sdist_extract/*/ | head -1)
+          echo "SDIST_DIR=$(pwd)/${EXTRACTED_DIR}" >> $GITHUB_ENV
+
+          # Verify contents
+          ls -la ${EXTRACTED_DIR}
+
+      - name: Extract sdist (Windows)
+        if: runner.os == 'Windows'
+        shell: pwsh
+        run: |
+          # Create extraction directory
+          New-Item -ItemType Directory -Force -Path "sdist_extract"
+
+          # Find the tarball file (without using wildcards)
+          $tarball = Get-ChildItem -Path "sdist" -Filter "*.tar.gz" | Select-Object -First 1
+
+          # Debug - show what we found
+          Write-Host "Found tarball: $($tarball.FullName)"
+
+          # Extract using the specific file path (not wildcard)
+          tar -xvf $tarball.FullName -C "sdist_extract"
+
+          # Get the extracted directory name
+          $extractedDir = (Get-ChildItem -Path "sdist_extract" -Directory | Select-Object -First 1).FullName
+
+          # Debug - show what we found
+          Write-Host "Extracted directory: $extractedDir"
+
+          # Set the environment variable
+          echo "SDIST_DIR=$extractedDir" | Out-File -FilePath $env:GITHUB_ENV -Append
+
+          # Verify contents
+          Get-ChildItem $extractedDir
+
+      - name: Build wheels from sdist
         uses: pypa/cibuildwheel@v2.22.0
         env:
           CIBW_ARCHS: "native"
@@ -85,19 +195,17 @@ jobs:
           # LD_LIBRARY_PATH in environment is needed by
           # auditwheel (Linux) and delocate (MacOS).
         with:
-          package-dir: "packages/basemap"
-          output-dir: "packages/basemap/dist"
+          package-dir: ${{ env.SDIST_DIR }} # Use extracted sdist
+          output-dir: "dist"
 
       - uses: actions/upload-artifact@v4
         with:
-          path: |
-            packages/basemap/dist/*.tar.gz
-            packages/basemap/dist/*.whl
-          name: dist-basemap-${{ matrix.os }}
+          path: dist/*.whl
+          name: dist-basemap-wheels-${{ matrix.os }}
 
   check:
     name: Check packages
-    needs: [build_data, build_basemap]
+    needs: [build_data, build_sdist, build_wheels]
     runs-on: ubuntu-22.04
     steps:
       - uses: actions/download-artifact@v4
@@ -106,6 +214,11 @@ jobs:
           pattern: "dist-*"
           merge-multiple: true
 
+      - uses: actions/download-artifact@v4
+        with:
+          path: dist
+          name: basemap-sdist
+
       - name: Set up Python
         uses: actions/setup-python@v5
         with:
@@ -117,9 +230,121 @@ jobs:
           python -m twine check dist/*.tar.gz
           python -m twine check dist/*.whl
 
+      - name: Verify sdist content
+        run: |
+          mkdir -p /tmp/sdist_test
+
+          # Find and extract basemap sdist
+          BASEMAP_SDIST=$(ls dist/basemap-*.tar.gz 2>/dev/null || ls dist/*basemap*.tar.gz 2>/dev/null | head -1)
+          tar -xvf "$BASEMAP_SDIST" -C /tmp/sdist_test
+
+          # Verify contents
+          echo "Files in extracted sdist:"
+          find /tmp/sdist_test -type f | grep -v "__pycache__" | sort
+
+          # Check for critical files
+          if [ -f "$(find /tmp/sdist_test -name "_geoslib.pyx")" ]; then
+            echo "✓ Source files verified in sdist"
+          else
+            echo "✗ Missing critical source files in sdist"
+            exit 1
+          fi
+
+  docs:
+    name: Build documentation
+    needs: [build_wheels]
+    runs-on: ubuntu-22.04
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.9"
+
+      - name: Download basemap wheel for Linux
+        uses: actions/download-artifact@v4
+        with:
+          name: dist-basemap-wheels-ubuntu-22.04
+          path: ./wheels/
+
+      - name: Download data packages
+        uses: actions/download-artifact@v4
+        with:
+          pattern: dist-basemap_data*
+          path: ./data_packages/
+          merge-multiple: true
+
+      - name: Install packages
+        run: |
+          # Get Python version
+          PY_VER=$(python -c "import sys; print(f'{sys.version_info.major}{sys.version_info.minor}')")
+          echo "Using Python $PY_VER"
+
+          # List available wheels
+          echo "Available wheels:"
+          ls -la ./wheels/
+
+          # Find wheel matching current Python version
+          MATCHING_WHEEL=$(find ./wheels -name "*-cp${PY_VER}-cp${PY_VER}*" | head -1)
+
+          if [ -n "$MATCHING_WHEEL" ]; then
+            echo "Installing matching wheel: $MATCHING_WHEEL"
+            python -m pip install "$MATCHING_WHEEL"
+          else
+            echo "No matching wheel found for Python $PY_VER. Installing any available wheel..."
+            python -m pip install ./wheels/*.whl
+          fi
+
+          # Install data packages
+          echo "Installing data packages:"
+          ls -la ./data_packages/
+          python -m pip install ./data_packages/*.whl
+
+          # Verify installation
+          python -c "import mpl_toolkits.basemap; print('Basemap version:', mpl_toolkits.basemap.__version__)"
+
+      - name: Install documentation requirements
+        run: |
+          cd packages/basemap
+          python -m pip install -r requirements-doc.txt
+
+      - name: Build documentation
+        run: |
+          cd packages/basemap
+          python -m sphinx doc/source public
+
+      - name: Upload docs artifacts
+        uses: actions/upload-artifact@v4
+        with:
+          name: docs-artifact
+          path: packages/basemap/public
+
+      - name: Upload github-pages artifact
+        uses: actions/upload-pages-artifact@v3
+        with:
+          name: github-pages
+          path: packages/basemap/public
+
+  pages:
+    name: Deploy documentation
+    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
+    needs: [docs, check]
+    runs-on: ubuntu-22.04
+    environment:
+      name: github-pages
+      url: ${{ steps.deployment.outputs.page_url }}
+    permissions:
+      pages: write
+      id-token: write
+    steps:
+      - name: Deploy github-pages
+        uses: actions/deploy-pages@v3
+        id: deployment
+
   upload:
     name: Upload packages
-    needs: [build_data, build_basemap, check]
+    needs: [build_data, build_sdist, build_wheels, check]
     runs-on: ubuntu-22.04
     environment: PyPI
     if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
@@ -130,6 +355,11 @@ jobs:
           pattern: "dist-*"
           merge-multiple: true
 
+      - uses: actions/download-artifact@v4
+        with:
+          path: dist
+          name: basemap-sdist
+
       - name: Publish to PyPI
         uses: pypa/gh-action-pypi-publish@release/v1
         with: