Importing from Bolt.new - COEP and CORS policy management

Hi all

Have been struggling with this error and tried a few things. Hoping someone else already been through this.
After importing a project from Bolt.new where the graphics for the map were all displaying fine.

Once uploaded in Bolt.diy the map graphics along with some other images are blocked.

When checking the developer console I’m getting this…

ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep 200 (OK)

image

I was using Chrome and then tried Firefox also. Same result.

Seems I have to apply a CORS header manually because Bolt can’t handle the request (Google - Gemini 2.0 flash) and used other configs. Seems the CORS issue is too complex to be handled at this stage.

Any ideas on how to progress as it will be a persistent issue and I’m sure there’s a way to add this into the logic control in some way. Maybe I’m not ‘prompting’ as accurately as I should too.

This I’ve been trying to fix for 2 days and slowly losing my mind.

2 Likes

I just tried it myself with a simple OpenStreetmap app from bolt.new.

Got the same Error and told Gemini to fix it, and it did:

import { useState } from 'react';
    import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
    import { LatLngTuple } from 'leaflet';
    import 'leaflet/dist/leaflet.css';

    export default function Map() {
      const [address, setAddress] = useState('');
      const [position, setPosition] = useState<LatLngTuple | null>(null);
      const [error, setError] = useState<string>('');

      const handleAddressChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setAddress(event.target.value);
      };

      const handleSearch = async () => {
        try {
          const response = await fetch(
            `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(
              address
            )}&format=json`
          );
          if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
          }
          const data = await response.json();
          if (data && data.length > 0) {
            const { lat, lon } = data[0];
            setPosition([parseFloat(lat), parseFloat(lon)]);
            setError('');
          } else {
            setError('Address not found');
            setPosition(null);
          }
        } catch (err: any) {
          setError(`Error: ${err.message}`);
          setPosition(null);
        }
      };

      return (
        <div>
          <div className="flex mb-4">
            <input
              type="text"
              placeholder="Enter address"
              className="border p-2 mr-2 rounded flex-1"
              value={address}
              onChange={handleAddressChange}
            />
            <button
              className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
              onClick={handleSearch}
            >
              Search
            </button>
          </div>
          {error && (
            <div className="p-4 bg-red-100 border border-red-400 text-red-700 rounded mb-4">
              {error}
            </div>
          )}
          {position && (
            <MapContainer
              center={position}
              zoom={13}
              className="h-[500px] w-full rounded-lg shadow-lg"
            >
              <TileLayer
                attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                crossOrigin="anonymous"
              />
              <Marker position={position}>
                <Popup>Location</Popup>
              </Marker>
            </MapContainer>
          )}
        </div>
      );
    }

1 Like

Isn’t it funny how different our outcomes can be…?

And I get

Can you see my frustration - I’ve been around the block on this now for 3 days. Tried manually adding the crossorigin=“anonymous” attribute to the TileLayer and playing with CORS and COEP policies.

There has been a few docs I’ve read that it is because I’m hosted from github too. Haven’t been able to work that one out.

Maybe depends on the settings:

Testet it with this.

It could also be that your project history is very big and thats why you get other results. I´ve got the same for a project of mine and it does just crap at some point.
I think a good workaround here is to create a new project with just the feature you want to test. so a little PoC and let it resolve there. When you got the solution, you tell in the bigger project how to fix it in detail and it should work.

edit: @shawn see also if you oversaw it maybe cause we postet at the same time.

OK - these are my settings. I’ll try yours…

1 Like

Started fresh. Cleared out old prompt, reloaded project from folder and prompting as below… Getting a slightly different result as it doesn’t have the history of the other attempts.

Still fails. I’ll do some more homework on this. It doesn’t fail when I host on Localhost. Works fine.

@leex279 - do you still have the update it performed for you. I even got into a situation where it was doing ‘diffs’ between code yesterday and making changes. Just dumping the diffs in the file and on some occasions, not even updating the file. It would delete the file contents and leave three dots “…” as a placeholder.

When querying Bolt. It was very sorry and told me so many times - then proceeded to do it over and over again.

yeah got the same and other things like ```tsx or .

Already discussed with @thecodacus yesterday and he is searching for a solution. Think in this case the default prompt works better he said :slight_smile: (cause optimized is not that strict)

2 Likes

OK. This is weird but now I have something to reverse engineer how I got here. The initial page map doesn’t display the tiles but when moving to another page they display correctly after Bolt did some nice magic - which is exactly as I’d expect in the perfect world. I will keep working this and get back to you. Not sure if this was fixed before the ‘proxy’ upgrade - which is actually the clever way to handle this.

But then I navigate to another page…

image

image

Ta-da…

image

I’ll work it out and come back with the result. I know I won’t be the only one with this issue.

1 Like

OK. It’s fixed and here’s how. It did require a little patience and carefully using my words in the prompt. If I’d been reckless or lazy and not identified exactly what I wanted, I think I’d have been taken down the rabbit hole again with other circular fixes.

Beautiful…

image

@leex279 Thanks Thomas - I had given up.

Just to be clear for anyone coming here. This is how it was achieved…

Since we cannot control the headers of the external server, we need to use a proxy to fetch the tiles. This will make the browser think that the tiles are coming from the same origin as our application.

Here’s how I’ll modify the Vite configuration to set up a proxy for the OpenStreetMap tiles:

vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  optimizeDeps: {
    exclude: ['lucide-react'],
  },
  server: {
    headers: {
      "Cross-Origin-Embedder-Policy": "require-corp",
      "Cross-Origin-Opener-Policy": "same-origin",
    },
    proxy: {
      '/osm_tiles': {
        target: 'https://c.tile.openstreetmap.org',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/osm_tiles/, ''),
      },
    }
  }
})

MapDisplay.tsx

import React from 'react';
import { MapContainer, TileLayer, Circle, Marker, useMap } from 'react-leaflet';
import { LatLngTuple, LatLng } from 'leaflet';
import { LocationPicker } from '../provider/LocationPicker';
import 'leaflet/dist/leaflet.css';

// MapUpdater component to handle center updates
function MapUpdater({ center }: { center: LatLngTuple }) {
  const map = useMap();
  
  React.useEffect(() => {
    map.setView(center, map.getZoom());
  }, [center, map]);
  
  return null;
}

interface MapDisplayProps {
  location: LatLngTuple;
  isManualMode: boolean;
  onLocationSelect: (latlng: LatLng) => void;
}

export function MapDisplay({ location, isManualMode, onLocationSelect }: MapDisplayProps) {
  return (
    <div className="bg-white rounded-lg overflow-hidden shadow-lg">
      <div style={{ height: '400px' }}>
        <MapContainer
          center={location}
          zoom={13}
          style={{ height: '100%', width: '100%' }}
          className="z-0"
        >
          <TileLayer
            attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
            url="/osm_tiles/{z}/{x}/{y}.png"
          />
          
          <Circle
            center={location}
            radius={5000}
            pathOptions={{
              color: 'blue',
              fillColor: '#30f',
              fillOpacity: 0.1
            }}
          />

          <Marker position={location} />
          
          {!isManualMode && <LocationPicker onLocationSelect={onLocationSelect} />}
          
          <MapUpdater center={location} />
        </MapContainer>
      </div>
    </div>
  );
}

ServiceProviderMap.tsx

import React from 'react';
import { MapContainer, TileLayer, Circle, Marker, Popup } from 'react-leaflet';
import { LatLngTuple } from 'leaflet';
import { fetchProviders, type ServiceProvider } from '../../lib/firebase/providers';
import { toLatLngTuple } from '../../lib/location/types';
import { STANDARD_SEARCH_RADIUS_KM } from '../../constants/search';
import { MapUpdater } from './MapUpdater';
import { ProviderPopup } from './ProviderPopup';
import 'leaflet/dist/leaflet.css';

interface ServiceProviderMapProps {
  selectedService: string;
  userLocation: LatLngTuple;
  searchRadius?: number;
  isDevelopmentMode?: boolean;
  onlineOnly?: boolean;
  onRequestService?: (providerId: string) => void;
}

export function ServiceProviderMap({ 
  selectedService, 
  userLocation,
  searchRadius = STANDARD_SEARCH_RADIUS_KM,
  isDevelopmentMode = false,
  onlineOnly = false,
  onRequestService
}: ServiceProviderMapProps) {
  const [providers, setProviders] = React.useState<ServiceProvider[]>([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);

  React.useEffect(() => {
    const loadProviders = async () => {
      try {
        setLoading(true);
        setError(null);
        const providersData = await fetchProviders(
          selectedService, 
          userLocation, 
          searchRadius,
          isDevelopmentMode,
          onlineOnly
        );
        setProviders(providersData);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load providers');
      } finally {
        setLoading(false);
      }
    };

    loadProviders();
  }, [selectedService, userLocation, searchRadius, isDevelopmentMode, onlineOnly]);

  const handleRequestService = (providerId: string) => {
    if (onRequestService) {
      onRequestService(providerId);
    }
  };

  if (loading) {
    return (
      <div className="h-[400px] flex items-center justify-center bg-gray-50">
        <div className="text-gray-600">Loading providers...</div>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      {error && (
        <div className="p-4 bg-red-50 border border-red-200 rounded-lg">
          <p className="text-red-800">{error}</p>
        </div>
      )}
      
      {!error && providers.length === 0 && (
        <div className="p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
          <p className="text-yellow-800">
            No service providers available within {searchRadius}km of your location. 
            Please try again later or contact emergency services if needed.
          </p>
        </div>
      )}

      {providers.length > 0 && (
        <div className="grid gap-2 mb-4">
          <h3 className="text-lg font-semibold text-gray-900">
            Available Providers ({providers.length})
          </h3>
          <p className="text-sm text-gray-600">
            Showing {onlineOnly ? 'available ' : ''}providers within {searchRadius}km of your location
          </p>
        </div>
      )}
      
      <div className="rounded-lg overflow-hidden shadow-lg">
        <div style={{ height: '400px' }}>
          <MapContainer
            center={userLocation}
            zoom={11}
            style={{ height: '100%', width: '100%' }}
            className="z-0"
          >
            <TileLayer
              attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
              url="/osm_tiles/{z}/{x}/{y}.png"
            />
            
            <Circle
              center={userLocation}
              radius={searchRadius * 1000}
              pathOptions={{
                color: isDevelopmentMode ? 'orange' : 'blue',
                fillColor: isDevelopmentMode ? '#f97316' : '#30f',
                fillOpacity: 0.1
              }}
            />

            {providers.map((provider) => (
              <Marker
                key={provider.id}
                position={toLatLngTuple(provider.location)}
              >
                <Popup>
                  <ProviderPopup 
                    provider={provider}
                    selectedService={selectedService}
                    onRequestService={handleRequestService}
                  />
                </Popup>
              </Marker>
            ))}

            <MapUpdater center={userLocation} />
          </MapContainer>
        </div>
      </div>
    </div>
  );
}

LocationSection.tsx

import React from 'react';
import { LocationPicker } from '../map/LocationPicker';
import { useLocation } from '../../hooks/useLocation';
import { RefreshCw } from 'lucide-react';
import { MapContainer, TileLayer, Circle, Marker, useMap } from 'react-leaflet';
import { LatLngTuple, LatLng } from 'leaflet';

// MapUpdater component to handle center updates
function MapUpdater({ center }: { center: LatLngTuple }) {
  const map = useMap();
  
  React.useEffect(() => {
    map.setView(center, map.getZoom());
  }, [center, map]);
  
  return null;
}

export function LocationSection() {
  const {
    location,
    isManualMode,
    address,
    error,
    loading,
    setManualLocation,
    toggleMode,
    updateCurrentLocation,
  } = useLocation();

  if (loading) {
    return (
      <div className="animate-pulse">
        <div className="h-[400px] bg-gray-200 rounded-lg"></div>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <h2 className="text-lg font-semibold text-gray-900">Current Location</h2>
      <p className="text-sm text-gray-600">
        This is your current location for roadside assistance. It can be different from your home address.
      </p>

      {error && (
        <div className="p-4 bg-red-50 border border-red-200 rounded-lg">
          <p className="text-red-800">{error}</p>
        </div>
      )}

      {address && (
        <div className="p-4 bg-blue-50 border border-blue-200 rounded-lg flex justify-between items-center">
          <p className="text-blue-800">
            <strong>Current Location:</strong> {address}
          </p>
          {!isManualMode && (
            <button
              onClick={updateCurrentLocation}
              className="p-2 hover:bg-blue-100 rounded-full transition-colors"
              title="Refresh current location"
            >
              <RefreshCw className="h-5 w-5 text-blue-600" />
            </button>
          )}
        </div>
      )}

      <div className="h-[400px] rounded-lg overflow-hidden shadow-lg">
        <MapContainer
          center={location}
          zoom={13}
          style={{ height: '100%', width: '100%' }}
          className="z-0"
        >
          <TileLayer
            attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
            url="/osm_tiles/{z}/{x}/{y}.png"
          />
          
          <Circle
            center={location}
            radius={5000}
            pathOptions={{
              color: 'blue',
              fillColor: '#30f',
              fillOpacity: 0.1
            }}
          />

          <Marker position={location} />
          
          {!isManualMode && <LocationPicker onLocationSelect={setManualLocation} />}
          
          <MapUpdater center={location} />
        </MapContainer>
      </div>
    </div>
  );
}

Hope that helps someone. :slight_smile:

3 Likes

OK. Just to add to this. Here’s a clever little trick for those that aren’t from a coding background. I’m not a great coder these days because it’s been too long out of the game for me. Things move on, but some things remain the same.

Try this prompt if you want to get a better idea of how Bolt has updated or fixed your issue…

can you please provide the diffs for those 4 file updates so i can better understand how you fixed this

Try it and you’ll learn a lot more this way.

Like if this helped you too. :slight_smile: :innocent:

2 Likes

I think this might be related to a feature not yet incorporated in bolt.diy Can't connect to external service (CORS issues) · Issue #3164 · stackblitz/bolt.new · GitHub

1 Like

You’re a legend - thank you. This helps heaps.

I did fix the issue with the proxy work around. But I agree, it wouldn’t be needed under normal circumstances.

I have another issue I haven’t sorted yet geolocation for mapping component not working in Bolt.diy. It works as soon as I deploy to Netlify but getting this error. I’ve stopped dev work till I can fix this.

PR…
geolocation-access-being-blocked-because-of-a-permissions-policy

So, yes. I will go looking on the road-map for where this sits. I’m sure it’s being looked at.

Mention to - ??? @aliasfox @leex279 @ColeMedin

1 Like

thanks @shawn,

@mrsimpson I think I saw something in this direction yesterday in one of your posts or and ticket/issue in github, but cant find it anymore :smiley:

1 Like

nope, nothing in the issues / epics I wrote yesterday wrt deployment. we might add this though

2 Likes

@shawn / @leex279 You guys are troopers - just reading through this whole thread now!

1 Like

@ColeMedin Haha - cheers. I remember hearing someone once say
“It’s better to be part of the solution than part of the problem”…!

I’m blocked by a few of these issues but I’ve learned a lot from trying to resolve them. That includes looking at others issues too.

What I’m seeing is a lot of is newbies coming here and expect some magic to happen. Then leave a post that indicates the same and potentially leave disgruntled. I started coding on a Vic20 and C64 in the early 80’s so I know what it is to have patience. :rofl: :rofl: :rofl:

I’ve worked in management for too long and trying to get back to coding so it’s tough. But if I can help a few get on the right path and reduce some of the pressure on the team in my spare time then I hope that’s OK.

Keep up the good work. :wink:

2 Likes

Just to add to this. I hadn’t thought to try the same scenario on my local build as I thought it could have been a Cloudflare config issue. But getting the same locally. :face_with_raised_eyebrow:

I hope the PR from @wonderwhy.er fixes it:

Didnt test yet, but will do as soon as I´ve got time. But you can also do and give Feedback in the PR, so we are good to merge :wink:

2 Likes