diff --git a/src/app/apple-icon.tsx b/src/app/apple-icon.tsx
new file mode 100644
index 0000000..85e7696
--- /dev/null
+++ b/src/app/apple-icon.tsx
@@ -0,0 +1,34 @@
+import { ImageResponse } from 'next/og';
+
+export const runtime = 'edge';
+
+export const size = {
+ width: 32,
+ height: 32,
+};
+export const contentType = 'image/png';
+
+export default function Icon() {
+ return new ImageResponse(
+ (
+
+ ☕
+
+ ),
+ {
+ ...size,
+ }
+ );
+}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index c08fc77..f02e8c0 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,6 +1,6 @@
import "~/styles/globals.css";
-import { type Metadata } from "next";
+import { type Metadata, type Viewport } from "next";
import { PT_Serif } from "next/font/google";
import { ThemeProvider } from "~/components/ThemeProvider";
@@ -11,6 +11,14 @@ export const metadata: Metadata = {
icons: [{ rel: "icon", url: "/favicon.ico" }],
};
+export const viewport: Viewport = {
+ themeColor: "#8B4513",
+ width: "device-width",
+ initialScale: 1,
+ maximumScale: 1,
+ userScalable: false,
+};
+
const ptSerif = PT_Serif({
subsets: ["latin"],
weight: ["400", "700"],
diff --git a/src/app/manifest.ts b/src/app/manifest.ts
new file mode 100644
index 0000000..ab7a170
--- /dev/null
+++ b/src/app/manifest.ts
@@ -0,0 +1,25 @@
+import { type MetadataRoute } from 'next';
+
+export default function manifest(): MetadataRoute.Manifest {
+ return {
+ name: 'Lewisburg Coffee Map',
+ short_name: 'Coffee Map',
+ description: 'Find the best coffee in Lewisburg, PA',
+ start_url: '/',
+ display: 'standalone',
+ background_color: '#ffffff',
+ theme_color: '#8B4513',
+ icons: [
+ {
+ src: '/favicon.ico',
+ sizes: 'any',
+ type: 'image/x-icon',
+ },
+ {
+ src: '/icon.svg',
+ sizes: 'any',
+ type: 'image/svg+xml',
+ }
+ ],
+ };
+}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 98930cf..1422364 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -17,6 +17,7 @@ export default function HomePage() {
setSelectedShop(shop)}
+ selectedShop={selectedShop}
/>
diff --git a/src/components/Map.tsx b/src/components/Map.tsx
index 0912214..9236fc1 100644
--- a/src/components/Map.tsx
+++ b/src/components/Map.tsx
@@ -1,6 +1,6 @@
"use client";
-import { MapContainer, TileLayer, Marker } from 'react-leaflet';
+import { MapContainer, TileLayer, Marker, useMap } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import { useState, useEffect } from 'react';
@@ -24,9 +24,25 @@ interface CoffeeShop {
interface MapProps {
shops: CoffeeShop[];
onShopSelect: (shop: CoffeeShop) => void;
+ selectedShop: CoffeeShop | null;
}
-const Map = ({ shops, onShopSelect }: MapProps) => {
+const MapController = ({ selectedShop }: { selectedShop: CoffeeShop | null }) => {
+ const map = useMap();
+
+ useEffect(() => {
+ if (selectedShop) {
+ map.flyTo([selectedShop.lat, selectedShop.lng], 16, {
+ duration: 1.5,
+ easeLinearity: 0.25,
+ });
+ }
+ }, [selectedShop, map]);
+
+ return null;
+};
+
+const Map = ({ shops, onShopSelect, selectedShop }: MapProps) => {
useEffect(() => {
// Fix for Leaflet default icon not found
// @ts-expect-error Fix for Leaflet default icon not found
@@ -107,6 +123,7 @@ const Map = ({ shops, onShopSelect }: MapProps) => {
attributionControl={false}
>
+