diff --git a/pages/sites/[slug]/[locale]/test-layers.tsx b/pages/sites/[slug]/[locale]/test-layers.tsx
new file mode 100644
index 0000000000..11c782d272
--- /dev/null
+++ b/pages/sites/[slug]/[locale]/test-layers.tsx
@@ -0,0 +1,74 @@
+import React from 'react';
+import { AbstractIntlMessages } from 'next-intl';
+import { Tenant } from '@planet-sdk/common';
+import {
+ GetStaticProps,
+ GetStaticPropsContext,
+ GetStaticPropsResult,
+} from 'next';
+import {
+ constructPathsForTenantSlug,
+ getTenantConfig,
+} from '../../../../src/utils/multiTenancy/helpers';
+import { defaultTenant } from '../../../../tenant.config';
+import getMessagesForPage from '../../../../src/utils/language/getMessagesForPage';
+import LayersMap from '../../../../src/layers/LayersMap';
+
+export default function TestLayersPage() {
+ return (
+
+ );
+}
+
+export const getStaticPaths = async () => {
+ const subDomainPaths = await constructPathsForTenantSlug();
+
+ const paths = subDomainPaths?.map((path) => {
+ return {
+ params: {
+ slug: path.params.slug,
+ locale: 'en',
+ },
+ };
+ });
+
+ return {
+ paths,
+ fallback: 'blocking',
+ };
+};
+
+interface PageProps {
+ messages: AbstractIntlMessages;
+ tenantConfig: Tenant;
+}
+
+export const getStaticProps: GetStaticProps = async (
+ context: GetStaticPropsContext
+): Promise> => {
+ const tenantConfig =
+ (await getTenantConfig(context.params?.slug as string)) ?? defaultTenant;
+
+ const messages = await getMessagesForPage({
+ locale: context.params?.locale as string,
+ filenames: ['common', 'donate', 'country', 'manageProjects', 'leaderboard'],
+ });
+
+ return {
+ props: {
+ messages,
+ tenantConfig,
+ },
+ };
+};
diff --git a/src/layers/LayersMap.tsx b/src/layers/LayersMap.tsx
new file mode 100644
index 0000000000..647db5d0ad
--- /dev/null
+++ b/src/layers/LayersMap.tsx
@@ -0,0 +1,85 @@
+import { useEffect, useState } from 'react';
+import Map, { MapStyle, Source, Layer } from 'react-map-gl-v7/maplibre';
+import getMapStyle from '../utils/maps/getMapStyle';
+import 'maplibre-gl/dist/maplibre-gl.css';
+import { NavigationControl } from 'react-map-gl-v7/maplibre';
+import { useRef, MutableRefObject } from 'react';
+import { ViewState } from 'react-map-gl-v7';
+
+interface MapState {
+ mapStyle: MapStyle;
+ dragPan: boolean;
+ scrollZoom: boolean;
+ minZoom: number;
+ maxZoom: number;
+}
+
+const EMPTY_STYLE = {
+ version: 8,
+ sources: {},
+ layers: [] as MapStyle['layers'],
+} as const;
+
+function LayersMap() {
+ const mapRef: MutableRefObject = useRef(null);
+ // mapState and viewState logic will need to be refined and move elsewhere (either context or props) once we fetch data from the API
+ const [mapState, setMapState] = useState({
+ mapStyle: EMPTY_STYLE,
+ dragPan: true,
+ scrollZoom: false,
+ minZoom: 1,
+ maxZoom: 15,
+ });
+
+ const [viewState, setViewState] = useState({
+ longitude: 0,
+ latitude: 0,
+ zoom: 1,
+ bearing: 0,
+ pitch: 0,
+ padding: { top: 0, bottom: 0, left: 0, right: 0 },
+ });
+
+ useEffect(() => {
+ async function loadMapStyle() {
+ const result = await getMapStyle('default');
+ if (result) {
+ setMapState({ ...mapState, mapStyle: result });
+ }
+ }
+ loadMapStyle();
+ }, []);
+
+ return (
+
+ );
+}
+
+export default LayersMap;