diff --git a/.github/workflows/docker-build-push.yaml b/.github/workflows/docker-build-push.yaml
index ac50133..4897bdb 100644
--- a/.github/workflows/docker-build-push.yaml
+++ b/.github/workflows/docker-build-push.yaml
@@ -3,9 +3,10 @@ name: Docker Build and Push
on:
push:
branches:
- - "main"
+ - 'main'
paths:
- - "apps/proompteng/**"
+ - 'apps/proompteng/**'
+ - 'apps/findbobastore/**'
jobs:
version:
@@ -41,3 +42,15 @@ jobs:
secrets:
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
+
+ build-findbobastore:
+ needs: version
+ uses: ./.github/workflows/docker-build-common.yaml
+ with:
+ image_name: findbobastore
+ dockerfile: ./apps/findbobastore/Dockerfile
+ context: .
+ new_tag: ${{ needs.version.outputs.new_tag }}
+ secrets:
+ REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
+ REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index 76de617..1cd7281 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -11,7 +11,7 @@ concurrency:
cancel-in-progress: true
jobs:
- main:
+ proompteng:
runs-on: arc-arm64
steps:
- uses: actions/checkout@v4
@@ -26,12 +26,39 @@ jobs:
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
+
- uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/apps/proompteng/.next/cache
- key: ${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
+ key: ${{ runner.os }}-nextjs-proompteng-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
+ restore-keys: |
+ ${{ runner.os }}-nextjs-proompteng-${{ hashFiles('**/pnpm-lock.yaml') }}-
+
+ - run: pnpm --filter proompteng build
+
+ findbobastore:
+ runs-on: arc-arm64
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - uses: pnpm/action-setup@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22.12.0
+ cache: 'pnpm'
+
+ - run: pnpm install --frozen-lockfile
+
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ${{ github.workspace }}/apps/findbobastore/.next/cache
+ key: ${{ runner.os }}-nextjs-findbobastore-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
restore-keys: |
- ${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}-
+ ${{ runner.os }}-nextjs-findbobastore-${{ hashFiles('**/pnpm-lock.yaml') }}-
- - run: pnpm build
+ - run: pnpm --filter findbobastore build
diff --git a/apps/findbobastore/Dockerfile b/apps/findbobastore/Dockerfile
new file mode 100644
index 0000000..cdf288d
--- /dev/null
+++ b/apps/findbobastore/Dockerfile
@@ -0,0 +1,39 @@
+FROM node:lts-alpine AS deps
+WORKDIR /app
+COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
+COPY apps/findbobastore/package.json ./apps/findbobastore/
+ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
+RUN corepack enable
+RUN pnpm install --frozen-lockfile
+
+FROM node:lts-alpine AS builder
+WORKDIR /app
+ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
+RUN corepack enable
+COPY --from=deps /app/node_modules ./node_modules
+COPY --from=deps /app/apps/findbobastore/node_modules ./apps/findbobastore/node_modules
+COPY . .
+RUN pnpm build:findbobastore
+
+FROM node:lts-alpine AS runner
+WORKDIR /app
+
+ENV NODE_ENV=production
+ENV NEXT_TELEMETRY_DISABLED=1
+
+RUN addgroup --system --gid 1001 nodejs && \
+ adduser --system --uid 1001 nextjs
+
+COPY --from=builder --chown=nextjs:nodejs /app/apps/findbobastore/.next/standalone /app
+COPY --from=builder --chown=nextjs:nodejs /app/apps/findbobastore/.next/static /app/apps/findbobastore/.next/static
+COPY --from=builder --chown=nextjs:nodejs /app/apps/findbobastore/public /app/apps/findbobastore/public
+
+USER nextjs
+
+EXPOSE 3000
+
+ENV PORT=3000
+ENV HOSTNAME="0.0.0.0"
+
+WORKDIR /app/apps/findbobastore
+CMD ["node", "server.js"]
diff --git a/apps/findbobastore/next.config.ts b/apps/findbobastore/next.config.ts
index 7329063..6fa33f5 100644
--- a/apps/findbobastore/next.config.ts
+++ b/apps/findbobastore/next.config.ts
@@ -1,7 +1,8 @@
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
- /* config options here */
+ output: 'standalone',
+ poweredByHeader: false,
}
export default nextConfig
diff --git a/apps/findbobastore/package.json b/apps/findbobastore/package.json
index 6544fb3..8ee59ed 100644
--- a/apps/findbobastore/package.json
+++ b/apps/findbobastore/package.json
@@ -9,19 +9,23 @@
"lint": "next lint"
},
"dependencies": {
+ "clsx": "^2.1.1",
+ "framer-motion": "^11.15.0",
+ "mapbox-gl": "^3.9.1",
+ "next": "15.1.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
- "next": "15.1.2"
+ "tailwind-merge": "^2.5.5"
},
"devDependencies": {
- "typescript": "^5",
+ "@eslint/eslintrc": "^3",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
- "postcss": "^8",
- "tailwindcss": "^3.4.1",
"eslint": "^9",
"eslint-config-next": "15.1.2",
- "@eslint/eslintrc": "^3"
+ "postcss": "^8",
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5"
}
}
diff --git a/apps/findbobastore/src/app/layout.tsx b/apps/findbobastore/src/app/layout.tsx
index b0626eb..32800f1 100644
--- a/apps/findbobastore/src/app/layout.tsx
+++ b/apps/findbobastore/src/app/layout.tsx
@@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
})
export const metadata: Metadata = {
- title: 'Create Next App',
- description: 'Generated by create next app',
+ title: 'Find Boba Store',
+ description: 'Find Boba Store',
}
export default function RootLayout({
diff --git a/apps/findbobastore/src/app/page.tsx b/apps/findbobastore/src/app/page.tsx
index 44f7610..49310b4 100644
--- a/apps/findbobastore/src/app/page.tsx
+++ b/apps/findbobastore/src/app/page.tsx
@@ -1,7 +1,12 @@
+import { MapContainer } from '@/components/map-container'
+
export default function Home() {
return (
-
+
+
+
Find Boba Store
+
+
+
)
}
diff --git a/apps/findbobastore/src/components/map-container.tsx b/apps/findbobastore/src/components/map-container.tsx
new file mode 100644
index 0000000..65e96cc
--- /dev/null
+++ b/apps/findbobastore/src/components/map-container.tsx
@@ -0,0 +1,16 @@
+'use client'
+
+import dynamic from 'next/dynamic'
+
+const MapView = dynamic(() => import('./map-view'), {
+ ssr: false,
+ loading: () => (
+
+ ),
+})
+
+export function MapContainer() {
+ return
+}
diff --git a/apps/findbobastore/src/components/map-view.tsx b/apps/findbobastore/src/components/map-view.tsx
new file mode 100644
index 0000000..061f263
--- /dev/null
+++ b/apps/findbobastore/src/components/map-view.tsx
@@ -0,0 +1,381 @@
+import { useCallback, useEffect, useRef, memo, useState } from 'react'
+import mapboxgl from 'mapbox-gl'
+import { motion, AnimatePresence } from 'framer-motion'
+import { cn } from '../lib/utils'
+import 'mapbox-gl/dist/mapbox-gl.css'
+
+const MAPBOX_ACCESS_TOKEN = process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN
+
+if (!MAPBOX_ACCESS_TOKEN) {
+ throw new Error('Missing NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN')
+}
+
+mapboxgl.accessToken = MAPBOX_ACCESS_TOKEN
+
+interface BobaStore {
+ id: string
+ name: string
+ coordinates: [number, number]
+ rating: number
+ address: string
+}
+
+const mockBobaStores: BobaStore[] = [
+ {
+ id: '1',
+ name: 'Urban Ritual',
+ coordinates: [-122.426, 37.553],
+ rating: 4.8,
+ address: '140 South B St, San Mateo, CA 94401',
+ },
+ {
+ id: '2',
+ name: 'Tea Hut',
+ coordinates: [-122.4862, 37.7324],
+ rating: 4.5,
+ address: '1541 Sloat Blvd, San Francisco, CA 94132',
+ },
+ {
+ id: '3',
+ name: 'District Tea',
+ coordinates: [-122.4194, 37.7749],
+ rating: 4.3,
+ address: '2154 Mission St, San Francisco, CA 94110',
+ },
+ {
+ id: '4',
+ name: 'Plentea',
+ coordinates: [-122.4044, 37.7946],
+ rating: 4.7,
+ address: '341 Kearny St, San Francisco, CA 94108',
+ },
+ {
+ id: '5',
+ name: 'Boba Guys',
+ coordinates: [-122.4194, 37.7649],
+ rating: 4.0,
+ address: '3491 19th St, San Francisco, CA 94110',
+ },
+ {
+ id: '6',
+ name: 'Purple Kow',
+ coordinates: [-122.4862, 37.7857],
+ rating: 4.5,
+ address: '3620 Balboa St, San Francisco, CA 94121',
+ },
+ {
+ id: '7',
+ name: 'Little Sweet',
+ coordinates: [-122.475, 37.779],
+ rating: 4.2,
+ address: '3836 Geary Blvd, San Francisco, CA',
+ },
+ {
+ id: '8',
+ name: 'Honeybear Boba',
+ coordinates: [-122.4194, 37.7749],
+ rating: 4.2,
+ address: '801 22nd St, San Francisco, CA 94107',
+ },
+ {
+ id: '9',
+ name: 'Yi Fang Taiwan Fruit Tea',
+ coordinates: [-122.4194, 37.7849],
+ rating: 4.5,
+ address: '950 E 3rd St Unit 2A, Los Angeles, CA 90013',
+ },
+ {
+ id: '10',
+ name: 'Lady Luck Cafe',
+ coordinates: [-122.4064, 37.7946],
+ rating: 4.5,
+ address: '956 Grant Ave, San Francisco, CA 94108',
+ },
+ {
+ id: '11',
+ name: 'Boba Bliss',
+ coordinates: [-122.1089, 37.4006],
+ rating: 4.6,
+ address: '685 San Antonio Rd Suite 15, Mountain View, CA 94040',
+ },
+ {
+ id: '12',
+ name: 'Ume Tea',
+ coordinates: [-122.075, 37.3894],
+ rating: 4.4,
+ address: '220 Castro St, Mountain View, CA 94041',
+ },
+ {
+ id: '13',
+ name: 'Tea Era',
+ coordinates: [-122.075, 37.3894],
+ rating: 4.3,
+ address: '271 Castro St, Mountain View, CA 94041',
+ },
+ {
+ id: '14',
+ name: 'Teaspoon',
+ coordinates: [-122.075, 37.3894],
+ rating: 4.2,
+ address: '134A Castro St, Mountain View, CA 94041',
+ },
+ {
+ id: '15',
+ name: 'FENG CHA',
+ coordinates: [-122.0891, 37.3894],
+ rating: 4.8,
+ address: '1040 Grant Rd Suite #350, Mountain View, CA 94040',
+ },
+ {
+ id: '16',
+ name: 'Happy Lemon',
+ coordinates: [-122.075, 37.3894],
+ rating: 4.0,
+ address: '742 Villa St, Mountain View, CA 94041',
+ },
+ {
+ id: '17',
+ name: 'Alma Dessert',
+ coordinates: [-122.0307, 37.3774],
+ rating: 4.8,
+ address: '165 S Murphy Ave Suite D, Sunnyvale, CA 94086',
+ },
+ {
+ id: '18',
+ name: 'Molly Tea',
+ coordinates: [-122.0317, 37.3784],
+ rating: 4.6,
+ address: '605 E El Camino Real Suite 1, Sunnyvale, CA 94087',
+ },
+ {
+ id: '19',
+ name: 'TP TEA Sunnyvale',
+ coordinates: [-122.0297, 37.3764],
+ rating: 4.7,
+ address: '567b E El Camino Real, Sunnyvale, CA 94087',
+ },
+ {
+ id: '20',
+ name: 'R&B Tea Sunnyvale',
+ coordinates: [-122.0327, 37.3794],
+ rating: 4.1,
+ address: '568 E El Camino Real ste a, Sunnyvale, CA 94087',
+ },
+ {
+ id: '21',
+ name: 'Teazzi Tea Shop',
+ coordinates: [-122.0287, 37.3754],
+ rating: 4.2,
+ address: '200 W McKinley Ave #105, Sunnyvale, CA 94086',
+ },
+ {
+ id: '22',
+ name: 'MOOMO TEA',
+ coordinates: [-122.0337, 37.3804],
+ rating: 4.6,
+ address: '715 Sunnyvale Saratoga Rd, Sunnyvale, CA 94087',
+ },
+ {
+ id: '23',
+ name: 'Chun Yang Tea',
+ coordinates: [-122.0277, 37.3744],
+ rating: 4.0,
+ address: '1120 Kifer Rd Suite C, Sunnyvale, CA 94086',
+ },
+ {
+ id: '24',
+ name: 'Sunright Tea Studio',
+ coordinates: [-122.0347, 37.3814],
+ rating: 4.4,
+ address: '795 E El Camino Real, Sunnyvale, CA 94087',
+ },
+ {
+ id: '25',
+ name: 'Boba Drive',
+ coordinates: [-122.0267, 37.3734],
+ rating: 4.5,
+ address: '677 Tasman Dr, Sunnyvale, CA 94089',
+ },
+]
+
+function MapOverlay({ store }: { store: BobaStore | null }) {
+ if (!store) return null
+
+ return (
+
+
+ {store.name}
+
+
Rating: {store.rating.toFixed(1)} ⭐️
+
{store.address}
+
+
+
+ )
+}
+
+export function MapView() {
+ const mapContainer = useRef(null)
+ const map = useRef(null)
+ const [selectedStore, setSelectedStore] = useState(null)
+ const markersRef = useRef([])
+ const [locationError, setLocationError] = useState(null)
+
+ const clearMarkers = useCallback(() => {
+ for (const marker of markersRef.current) {
+ marker.remove()
+ }
+ markersRef.current = []
+ }, [])
+
+ const addUserLocationMarker = useCallback((location: [number, number]) => {
+ if (!map.current) return
+
+ const el = document.createElement('div')
+ el.className = 'user-location-marker'
+ el.innerHTML = '📍'
+ el.style.fontSize = '2rem'
+ el.setAttribute('aria-label', 'Your location')
+
+ const marker = new mapboxgl.Marker({ element: el }).setLngLat(location).addTo(map.current)
+ markersRef.current.push(marker)
+ }, [])
+
+ const addBobaMarkers = useCallback(() => {
+ if (!map.current) return
+
+ for (const store of mockBobaStores) {
+ const el = document.createElement('div')
+ el.className = 'boba-marker'
+ el.innerHTML = '🧋'
+ el.style.fontSize = '2rem'
+ el.style.cursor = 'pointer'
+ el.setAttribute('aria-label', `${store.name} location marker`)
+
+ const marker = new mapboxgl.Marker({ element: el }).setLngLat(store.coordinates).addTo(map.current)
+
+ el.addEventListener('click', () => {
+ setSelectedStore(store)
+ map.current?.flyTo({
+ center: store.coordinates,
+ zoom: 15,
+ duration: 1500,
+ essential: true,
+ })
+ })
+
+ markersRef.current.push(marker)
+ }
+ }, [])
+
+ const getUserLocation = useCallback(() => {
+ return new Promise<[number, number]>((resolve, reject) => {
+ if (!navigator.geolocation) {
+ reject(new Error('Geolocation is not supported by your browser'))
+ return
+ }
+
+ navigator.geolocation.getCurrentPosition(
+ (position) => {
+ resolve([position.coords.longitude, position.coords.latitude])
+ },
+ (error) => {
+ reject(error)
+ },
+ {
+ enableHighAccuracy: true,
+ timeout: 5000,
+ maximumAge: 0,
+ },
+ )
+ })
+ }, [])
+
+ const initializeMap = useCallback(async () => {
+ if (!mapContainer.current) return
+
+ try {
+ // Try to get user location first
+ const location = await getUserLocation()
+
+ map.current = new mapboxgl.Map({
+ container: mapContainer.current,
+ style: 'mapbox://styles/mapbox/dark-v11',
+ center: location,
+ zoom: 12,
+ maxZoom: 15,
+ })
+
+ map.current.on('load', () => {
+ clearMarkers()
+ addUserLocationMarker(location)
+ addBobaMarkers()
+ })
+ } catch (error) {
+ setLocationError(error instanceof Error ? error.message : 'Failed to get location')
+
+ // Fall back to showing all stores if location access fails
+ const bounds = new mapboxgl.LngLatBounds()
+ for (const store of mockBobaStores) {
+ bounds.extend(store.coordinates)
+ }
+
+ map.current = new mapboxgl.Map({
+ container: mapContainer.current,
+ style: 'mapbox://styles/mapbox/dark-v11',
+ bounds: bounds,
+ fitBoundsOptions: { padding: 50 },
+ maxZoom: 15,
+ })
+
+ map.current.on('load', () => {
+ clearMarkers()
+ addBobaMarkers()
+ })
+ }
+
+ map.current.addControl(new mapboxgl.NavigationControl(), 'top-right')
+ map.current.addControl(
+ new mapboxgl.GeolocateControl({
+ positionOptions: {
+ enableHighAccuracy: true,
+ },
+ trackUserLocation: true,
+ }),
+ )
+ }, [getUserLocation, clearMarkers, addUserLocationMarker, addBobaMarkers])
+
+ useEffect(() => {
+ if (!map.current) {
+ initializeMap()
+ }
+
+ return () => {
+ if (map.current) {
+ clearMarkers()
+ map.current.remove()
+ map.current = null
+ }
+ }
+ }, [initializeMap, clearMarkers])
+
+ return (
+
+
+
+ {locationError &&
{locationError}
}
+
+ )
+}
+
+export default memo(MapView)
diff --git a/apps/findbobastore/src/lib/utils.ts b/apps/findbobastore/src/lib/utils.ts
new file mode 100644
index 0000000..d32b0fe
--- /dev/null
+++ b/apps/findbobastore/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from 'clsx'
+import { twMerge } from 'tailwind-merge'
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/apps/proompteng/Dockerfile b/apps/proompteng/Dockerfile
index 5af5bcb..803e189 100644
--- a/apps/proompteng/Dockerfile
+++ b/apps/proompteng/Dockerfile
@@ -13,7 +13,7 @@ RUN corepack enable
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/apps/proompteng/node_modules ./apps/proompteng/node_modules
COPY . .
-RUN pnpm build
+RUN pnpm build:proompteng
FROM node:lts-alpine AS runner
WORKDIR /app
diff --git a/argocd/applications/findbobastore/deployment.yaml b/argocd/applications/findbobastore/deployment.yaml
new file mode 100644
index 0000000..421a8d9
--- /dev/null
+++ b/argocd/applications/findbobastore/deployment.yaml
@@ -0,0 +1,34 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: findbobastore
+ namespace: findbobastore
+spec:
+ selector:
+ matchLabels:
+ app: findbobastore
+ template:
+ metadata:
+ labels:
+ app: findbobastore
+ spec:
+ imagePullSecrets:
+ - name: kalmyk-registry
+ containers:
+ - name: findbobastore
+ image: kalmyk.duckdns.org/lab/findbobastore
+ resources:
+ limits:
+ cpu: '1'
+ memory: '512Mi'
+ requests:
+ cpu: '200m'
+ memory: '256Mi'
+ ports:
+ - containerPort: 3000
+ env:
+ - name: NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN
+ valueFrom:
+ secretKeyRef:
+ name: mapbox-token
+ key: token
diff --git a/argocd/applications/findbobastore/ingress.yaml b/argocd/applications/findbobastore/ingress.yaml
new file mode 100644
index 0000000..4e826a4
--- /dev/null
+++ b/argocd/applications/findbobastore/ingress.yaml
@@ -0,0 +1,17 @@
+apiVersion: traefik.containo.us/v1alpha1
+kind: IngressRoute
+metadata:
+ name: findbobastore
+ namespace: findbobastore
+spec:
+ entryPoints:
+ - web
+ - websecure
+ routes:
+ - kind: Rule
+ match: Host(`findboba.store`)
+ services:
+ - name: findbobastore
+ port: 80
+ tls:
+ certResolver: default
diff --git a/argocd/applications/findbobastore/kustomization.yaml b/argocd/applications/findbobastore/kustomization.yaml
new file mode 100644
index 0000000..99bf3fb
--- /dev/null
+++ b/argocd/applications/findbobastore/kustomization.yaml
@@ -0,0 +1,10 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+ - secrets.yaml
+ - deployment.yaml
+ - service.yaml
+ - ingress.yaml
+images:
+ - name: kalmyk.duckdns.org/lab/findbobastore
+ newTag: 0.128.0
diff --git a/argocd/applications/findbobastore/secrets.yaml b/argocd/applications/findbobastore/secrets.yaml
new file mode 100644
index 0000000..a6ba8b9
--- /dev/null
+++ b/argocd/applications/findbobastore/secrets.yaml
@@ -0,0 +1,32 @@
+---
+apiVersion: bitnami.com/v1alpha1
+kind: SealedSecret
+metadata:
+ creationTimestamp: null
+ name: kalmyk-registry
+ namespace: findbobastore
+spec:
+ encryptedData:
+ .dockerconfigjson: AgCftxmKCiQmjua8NJ30RqWmBMEMKBeSE/dZMQc/aLCz/ugyzNvVML6IJoYqqglnexgg3GyEg03YyPkU4hNDQyP1wW3QvW27VIV2qkSKD2LvNxU42Otpb+Qla8JvtljTzUdMmxHYPiPimGaEInc5xEbB0TzFmHqDWUWaS7Hh7f5DDObX7gTsP3WD10zR3pZ4t5X9ND6D7hjO+zt60Aulb0Cgjo84SvsmLafbs/UWT6qPUjIim8MjQlG1I/jwt4eQhXVHqRh+8HQ4BLsEro1+JWNoT/bDb+YC5ElasiN4JREqu9aVNmtS9i3wcAFqcaw0wRfxUXUb2JvS7+vICsSMoNrDHbN+WP/15RzjiIbAGRhRP0tG2bec46/lgzpJHrcVAqG/D30YmegdO54OtM0Wa2ofgooZSaGr7EhOuCmTgK1CUYFKncQtmDfY/yHiqSIBH78vam123iPRJ4AEHetCH+6PYx95iDykdHygQB2QnsPq4ZXgKXoCvunXH3uuk7kddFPYOvqdAmYL8CFbWXjK52GaYZx6z1hjDiGnp1LffuyyPBQZ990+Cdkl1svdvQ4wesQjH3uw1CYWLLBFztpxJ2UmspaaUj6DoamD9nLsTQjuoukNxuw/mMsTTDqDX3Qfx+MVrm3Gmhq8+sYDTqy8qVx2/x69EoKeFe7gEjuvI7SFy5r/lUhJqlBs3iVsucHkRKTFtKTOnsp+aMzT1EzPCF85Dkvb/FNDJCR6oV9U5/JXHe5nZU6numKsfq8B1dkg3Z/LmqXvc0ttv7WU1zP/WKn4j6SK9/27EKzbh7Vu5qKBUNixmbs4CjX9SpbESpXffW2fjUhA+JhsLXIqpj2vfWCb0Xp53MtoN/ufA3VYcYQ=
+ template:
+ metadata:
+ creationTimestamp: null
+ name: kalmyk-registry
+ namespace: findbobastore
+ type: kubernetes.io/dockerconfigjson
+---
+apiVersion: bitnami.com/v1alpha1
+kind: SealedSecret
+metadata:
+ creationTimestamp: null
+ name: mapbox-token
+ namespace: findbobastore
+spec:
+ encryptedData:
+ token: AgBwjlO2Fi+HvOASLbj9MCY53DCgSXqULiSjGEAdH+k+J27QjPOgIgilghw5IZ51zeiR6V+/WQ4KA2oCHpuFYBqTTNg6Zr+qbw/944zTbIKVIeAXtPeLkXW5c+GCL7Rdlpc9C0hcDDp3tfOUfO7E0k9C/tqAMankNarxLUzroa+CNSTke/goFQy+CwUhtqp+gaT63HN0sXTIGBKNeqce5fKz3+/vDNRkVyV72UdgyZWEfKqYN9L9Dbh4SfPYFoNqN14bu+KSj1piWYc1XCynb9K35JQIYvsvf68AzgRPfWq+uKzIhYC/mcwuZ6OqCQewgm6NuDwm/pURP2o7n14y9yrUJ6uAtIcBWkSVbjTKN+gwyb61/yLAAu5ar0jUNU5OLWvfZ+gK8XQjn8ZnAm7WuemyY8Yz1KU5txImZXHyjdqqftifF14jIsEtcr/BKjUlOVTXbpudwDWJ/PavaJIGc1HiGyDwd/gPP0AKFG1z/42SeCK+Nqv+nDcNqhd0HrbZO/dEP7++TUdCUTMB/RoNzZW3KQjp9Yycx4/b3cb5EeS3kJ770EMQglkUuJxBGMgC1VLX0NUrgdru4k3WqmI+Xk1vM3bNuseLa2+FqyA7AV5V3XqfRnoDL2lR4RK//wz7EFdnb72GHFcQyrc9RO8cFH+rddCnrB6V9HaSQFE4diTtf5KcWw1XnFAkvH1wTNxVf30mcTwPMcfpncs8P6cN+Mg20v898mdXpYj3WgEh5UHqXde85ButdV4XaCyYgYqMt3koRo709i+dAwQMjjhH+YepcM8IpblMUt1aWef2wE8MdryeX9TjDnAX
+ template:
+ metadata:
+ creationTimestamp: null
+ name: mapbox-token
+ namespace: findbobastore
+ type: Opaque
diff --git a/argocd/applications/findbobastore/service.yaml b/argocd/applications/findbobastore/service.yaml
new file mode 100644
index 0000000..cbcc28d
--- /dev/null
+++ b/argocd/applications/findbobastore/service.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: findbobastore
+ namespace: findbobastore
+spec:
+ selector:
+ app: findbobastore
+ ports:
+ - port: 80
+ targetPort: 3000
diff --git a/package.json b/package.json
index a28be4d..35acdd8 100644
--- a/package.json
+++ b/package.json
@@ -6,10 +6,14 @@
"node": "22.12.0"
},
"scripts": {
- "dev": "pnpm --filter proompteng dev",
- "build": "pnpm --filter proompteng build",
- "start": "pnpm --filter proompteng start",
- "lint": "pnpm --filter proompteng lint",
+ "dev:proompteng": "pnpm --filter proompteng dev",
+ "dev:findbobastore": "pnpm --filter findbobastore dev",
+ "build:proompteng": "pnpm --filter proompteng build",
+ "build:findbobastore": "pnpm --filter findbobastore build",
+ "start:proompteng": "pnpm --filter proompteng start",
+ "start:findbobastore": "pnpm --filter findbobastore start",
+ "lint:proompteng": "pnpm --filter proompteng lint",
+ "lint:findbobastore": "pnpm --filter findbobastore lint",
"clean": "pnpm -r exec rm -rf node_modules && rm -rf node_modules",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,css,md,json}\"",
"tf:plan": "tofu -chdir='./tofu/harvester' plan",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dccfc12..c80a8fb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,6 +20,15 @@ importers:
apps/findbobastore:
dependencies:
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ framer-motion:
+ specifier: ^11.15.0
+ version: 11.15.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ mapbox-gl:
+ specifier: ^3.9.1
+ version: 3.9.1
next:
specifier: 15.1.2
version: 15.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -29,6 +38,9 @@ importers:
react-dom:
specifier: ^19.0.0
version: 19.0.0(react@19.0.0)
+ tailwind-merge:
+ specifier: ^2.5.5
+ version: 2.5.5
devDependencies:
'@eslint/eslintrc':
specifier: ^3
@@ -312,6 +324,29 @@ packages:
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+ '@mapbox/jsonlint-lines-primitives@2.0.2':
+ resolution: {integrity: sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==}
+ engines: {node: '>= 0.6'}
+
+ '@mapbox/mapbox-gl-supported@3.0.0':
+ resolution: {integrity: sha512-2XghOwu16ZwPJLOFVuIOaLbN0iKMn867evzXFyf0P22dqugezfJwLmdanAgU25ITvz1TvOfVP4jsDImlDJzcWg==}
+
+ '@mapbox/point-geometry@0.1.0':
+ resolution: {integrity: sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==}
+
+ '@mapbox/tiny-sdf@2.0.6':
+ resolution: {integrity: sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==}
+
+ '@mapbox/unitbezier@0.0.1':
+ resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==}
+
+ '@mapbox/vector-tile@1.3.1':
+ resolution: {integrity: sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==}
+
+ '@mapbox/whoots-js@3.1.0':
+ resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==}
+ engines: {node: '>=6.0.0'}
+
'@next/env@15.1.2':
resolution: {integrity: sha512-Hm3jIGsoUl6RLB1vzY+dZeqb+/kWPZ+h34yiWxW0dV87l8Im/eMOwpOA+a0L78U0HM04syEjXuRlCozqpwuojQ==}
@@ -424,15 +459,30 @@ packages:
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+ '@types/geojson-vt@3.2.5':
+ resolution: {integrity: sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==}
+
+ '@types/geojson@7946.0.15':
+ resolution: {integrity: sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==}
+
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ '@types/mapbox__point-geometry@0.1.4':
+ resolution: {integrity: sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==}
+
+ '@types/mapbox__vector-tile@1.3.4':
+ resolution: {integrity: sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==}
+
'@types/node@20.17.10':
resolution: {integrity: sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==}
+ '@types/pbf@3.0.5':
+ resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==}
+
'@types/react-dom@19.0.2':
resolution: {integrity: sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==}
peerDependencies:
@@ -441,6 +491,9 @@ packages:
'@types/react@19.0.2':
resolution: {integrity: sha512-USU8ZI/xyKJwFTpjSVIrSeHBVAGagkHQKPNbxeWwql/vDmnTIBgx+TJnhFnj1NXgz8XfprU0egV2dROLGpsBEg==}
+ '@types/supercluster@7.1.3':
+ resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==}
+
'@typescript-eslint/eslint-plugin@8.18.1':
resolution: {integrity: sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -629,6 +682,9 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
+ cheap-ruler@4.0.0:
+ resolution: {integrity: sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==}
+
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
@@ -668,6 +724,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
+ csscolorparser@1.0.3:
+ resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==}
+
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
@@ -737,6 +796,9 @@ packages:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
+ earcut@3.0.1:
+ resolution: {integrity: sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==}
+
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@@ -976,6 +1038,9 @@ packages:
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ geojson-vt@4.0.2:
+ resolution: {integrity: sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==}
+
get-intrinsic@1.2.6:
resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==}
engines: {node: '>= 0.4'}
@@ -987,6 +1052,9 @@ packages:
get-tsconfig@4.8.1:
resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
+ gl-matrix@3.4.3:
+ resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -1017,6 +1085,9 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ grid-index@1.1.0:
+ resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==}
+
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
@@ -1049,6 +1120,9 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -1216,6 +1290,9 @@ packages:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
+ kdbush@4.0.2:
+ resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==}
+
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -1262,6 +1339,9 @@ packages:
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ mapbox-gl@3.9.1:
+ resolution: {integrity: sha512-KGgS07MOoGSrewRrw0zqPG/2zkUNWYVGhI4+OEGnUGnUR5GV+k6rgKBEZei3U8z9VIrhrO5Qfbh3Da9o7GhX/Q==}
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
@@ -1297,6 +1377,9 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ murmurhash-js@1.0.0:
+ resolution: {integrity: sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==}
+
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
@@ -1403,6 +1486,10 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
+ pbf@3.3.0:
+ resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==}
+ hasBin: true
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -1471,6 +1558,9 @@ packages:
resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
engines: {node: ^10 || ^12 || >=14}
+ potpack@2.0.0:
+ resolution: {integrity: sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==}
+
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@@ -1483,6 +1573,9 @@ packages:
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ protocol-buffers-schema@3.6.0:
+ resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==}
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -1490,6 +1583,9 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ quickselect@3.0.0:
+ resolution: {integrity: sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==}
+
react-dom@19.0.0:
resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
peerDependencies:
@@ -1524,6 +1620,9 @@ packages:
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+ resolve-protobuf-schema@2.1.0:
+ resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==}
+
resolve@1.22.10:
resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
engines: {node: '>= 0.4'}
@@ -1560,6 +1659,10 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ serialize-to-js@3.1.2:
+ resolution: {integrity: sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w==}
+ engines: {node: '>=4.0.0'}
+
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -1679,6 +1782,9 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
+ supercluster@8.0.1:
+ resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==}
+
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -1711,6 +1817,9 @@ packages:
thenify@3.3.1:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ tinyqueue@3.0.0:
+ resolution: {integrity: sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==}
+
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
@@ -1768,6 +1877,9 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ vt-pbf@3.1.3:
+ resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==}
+
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@@ -1974,6 +2086,22 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
+ '@mapbox/jsonlint-lines-primitives@2.0.2': {}
+
+ '@mapbox/mapbox-gl-supported@3.0.0': {}
+
+ '@mapbox/point-geometry@0.1.0': {}
+
+ '@mapbox/tiny-sdf@2.0.6': {}
+
+ '@mapbox/unitbezier@0.0.1': {}
+
+ '@mapbox/vector-tile@1.3.1':
+ dependencies:
+ '@mapbox/point-geometry': 0.1.0
+
+ '@mapbox/whoots-js@3.1.0': {}
+
'@next/env@15.1.2': {}
'@next/eslint-plugin-next@15.1.2':
@@ -2054,14 +2182,30 @@ snapshots:
'@types/estree@1.0.6': {}
+ '@types/geojson-vt@3.2.5':
+ dependencies:
+ '@types/geojson': 7946.0.15
+
+ '@types/geojson@7946.0.15': {}
+
'@types/json-schema@7.0.15': {}
'@types/json5@0.0.29': {}
+ '@types/mapbox__point-geometry@0.1.4': {}
+
+ '@types/mapbox__vector-tile@1.3.4':
+ dependencies:
+ '@types/geojson': 7946.0.15
+ '@types/mapbox__point-geometry': 0.1.4
+ '@types/pbf': 3.0.5
+
'@types/node@20.17.10':
dependencies:
undici-types: 6.19.8
+ '@types/pbf@3.0.5': {}
+
'@types/react-dom@19.0.2(@types/react@19.0.2)':
dependencies:
'@types/react': 19.0.2
@@ -2070,6 +2214,10 @@ snapshots:
dependencies:
csstype: 3.1.3
+ '@types/supercluster@7.1.3':
+ dependencies:
+ '@types/geojson': 7946.0.15
+
'@typescript-eslint/eslint-plugin@8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2))(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@@ -2306,6 +2454,8 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
+ cheap-ruler@4.0.0: {}
+
chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
@@ -2354,6 +2504,8 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
+ csscolorparser@1.0.3: {}
+
cssesc@3.0.0: {}
csstype@3.1.3: {}
@@ -2417,6 +2569,8 @@ snapshots:
es-errors: 1.3.0
gopd: 1.2.0
+ earcut@3.0.1: {}
+
eastasianwidth@0.2.0: {}
emoji-regex@8.0.0: {}
@@ -2800,6 +2954,8 @@ snapshots:
functions-have-names@1.2.3: {}
+ geojson-vt@4.0.2: {}
+
get-intrinsic@1.2.6:
dependencies:
call-bind-apply-helpers: 1.0.1
@@ -2823,6 +2979,8 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
+ gl-matrix@3.4.3: {}
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -2853,6 +3011,8 @@ snapshots:
graphemer@1.4.0: {}
+ grid-index@1.1.0: {}
+
has-bigints@1.1.0: {}
has-flag@4.0.0: {}
@@ -2877,6 +3037,8 @@ snapshots:
husky@9.1.7: {}
+ ieee754@1.2.1: {}
+
ignore@5.3.2: {}
import-fresh@3.3.0:
@@ -3047,6 +3209,8 @@ snapshots:
object.assign: 4.1.7
object.values: 1.2.1
+ kdbush@4.0.2: {}
+
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@@ -3086,6 +3250,37 @@ snapshots:
dependencies:
react: 19.0.0
+ mapbox-gl@3.9.1:
+ dependencies:
+ '@mapbox/jsonlint-lines-primitives': 2.0.2
+ '@mapbox/mapbox-gl-supported': 3.0.0
+ '@mapbox/point-geometry': 0.1.0
+ '@mapbox/tiny-sdf': 2.0.6
+ '@mapbox/unitbezier': 0.0.1
+ '@mapbox/vector-tile': 1.3.1
+ '@mapbox/whoots-js': 3.1.0
+ '@types/geojson': 7946.0.15
+ '@types/geojson-vt': 3.2.5
+ '@types/mapbox__point-geometry': 0.1.4
+ '@types/mapbox__vector-tile': 1.3.4
+ '@types/pbf': 3.0.5
+ '@types/supercluster': 7.1.3
+ cheap-ruler: 4.0.0
+ csscolorparser: 1.0.3
+ earcut: 3.0.1
+ geojson-vt: 4.0.2
+ gl-matrix: 3.4.3
+ grid-index: 1.1.0
+ kdbush: 4.0.2
+ murmurhash-js: 1.0.0
+ pbf: 3.3.0
+ potpack: 2.0.0
+ quickselect: 3.0.0
+ serialize-to-js: 3.1.2
+ supercluster: 8.0.1
+ tinyqueue: 3.0.0
+ vt-pbf: 3.1.3
+
math-intrinsics@1.1.0: {}
merge2@1.4.1: {}
@@ -3113,6 +3308,8 @@ snapshots:
ms@2.1.3: {}
+ murmurhash-js@1.0.0: {}
+
mz@2.7.0:
dependencies:
any-promise: 1.3.0
@@ -3227,6 +3424,11 @@ snapshots:
lru-cache: 10.4.3
minipass: 7.1.2
+ pbf@3.3.0:
+ dependencies:
+ ieee754: 1.2.1
+ resolve-protobuf-schema: 2.1.0
+
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -3285,6 +3487,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ potpack@2.0.0: {}
+
prelude-ls@1.2.1: {}
prettier@3.4.2: {}
@@ -3295,10 +3499,14 @@ snapshots:
object-assign: 4.1.1
react-is: 16.13.1
+ protocol-buffers-schema@3.6.0: {}
+
punycode@2.3.1: {}
queue-microtask@1.2.3: {}
+ quickselect@3.0.0: {}
+
react-dom@19.0.0(react@19.0.0):
dependencies:
react: 19.0.0
@@ -3338,6 +3546,10 @@ snapshots:
resolve-pkg-maps@1.0.0: {}
+ resolve-protobuf-schema@2.1.0:
+ dependencies:
+ protocol-buffers-schema: 3.6.0
+
resolve@1.22.10:
dependencies:
is-core-module: 2.16.1
@@ -3376,6 +3588,8 @@ snapshots:
semver@7.6.3: {}
+ serialize-to-js@3.1.2: {}
+
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -3555,6 +3769,10 @@ snapshots:
pirates: 4.0.6
ts-interface-checker: 0.1.13
+ supercluster@8.0.1:
+ dependencies:
+ kdbush: 4.0.2
+
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -3604,6 +3822,8 @@ snapshots:
dependencies:
any-promise: 1.3.0
+ tinyqueue@3.0.0: {}
+
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
@@ -3677,6 +3897,12 @@ snapshots:
util-deprecate@1.0.2: {}
+ vt-pbf@3.1.3:
+ dependencies:
+ '@mapbox/point-geometry': 0.1.0
+ '@mapbox/vector-tile': 1.3.1
+ pbf: 3.3.0
+
which-boxed-primitive@1.1.1:
dependencies:
is-bigint: 1.1.0
diff --git a/scripts/build-findbobastore.sh b/scripts/build-findbobastore.sh
new file mode 100755
index 0000000..a476e58
--- /dev/null
+++ b/scripts/build-findbobastore.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# Set variables
+IMAGE_NAME="kalmyk.duckdns.org/lab/findbobastore"
+DOCKERFILE="apps/findbobastore/Dockerfile"
+CONTEXT_PATH="."
+
+# Check if a tag is provided as an argument
+if [ $# -eq 1 ]; then
+ TAG=$1
+else
+ # If no tag is provided, use the current date and time
+ TAG=$(date +"%Y%m%d_%H%M%S")
+fi
+
+# Full image name with tag
+FULL_IMAGE_NAME="${IMAGE_NAME}:${TAG}"
+
+# Build the Docker image
+echo "Building Docker image: ${FULL_IMAGE_NAME}"
+docker buildx build --platform linux/arm64 -t ${FULL_IMAGE_NAME} -f ${DOCKERFILE} ${CONTEXT_PATH} --push
+
+# Check if the build was successful
+if [ $? -eq 0 ]; then
+ echo "Docker image built and pushed successfully: ${FULL_IMAGE_NAME}"
+else
+ echo "Docker image build or push failed"
+ exit 1
+fi