diff --git a/Caddyfile.dev b/Caddyfile.dev index 95311ea..74f6e63 100644 --- a/Caddyfile.dev +++ b/Caddyfile.dev @@ -9,6 +9,7 @@ localhost { reverse_proxy meshinfo:9000 } handle_path /next/* { + rewrite * /next{uri} reverse_proxy frontend:80 } handle /* { diff --git a/Caddyfile.sample b/Caddyfile.sample index 4507089..9a942ae 100644 --- a/Caddyfile.sample +++ b/Caddyfile.sample @@ -14,6 +14,7 @@ YOUR_FQDN_OR_HOSTNAME { reverse_proxy meshinfo:9000 } handle_path /next/* { + rewrite * /next{uri} reverse_proxy frontend:80 } } diff --git a/Dockerfile.spa b/Dockerfile.spa index aa1cece..498ac14 100644 --- a/Dockerfile.spa +++ b/Dockerfile.spa @@ -12,12 +12,6 @@ RUN corepack enable RUN yarn RUN yarn build --base=/next/ -FROM nginx:alpine - -COPY --from=build /frontend/dist /usr/share/nginx/html/next - -COPY frontend/nginx.conf /etc/nginx/conf.d/default.conf - EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file +CMD ["/frontend/scripts/run-frontend.sh"] \ No newline at end of file diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 8cef6ce..8d74c2c 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -36,11 +36,10 @@ services: build: context: . dockerfile: Dockerfile.spa - volumes: - - ./frontend/dist:/usr/share/nginx/html/next ports: - 8000:80 environment: + - VITE_API_BASE_URL=/api - NODE_ENV=production restart: always diff --git a/docker-compose.yml b/docker-compose.yml index 1a9f74b..60b010b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,6 +40,7 @@ services: ports: - 8000:80 environment: + - VITE_API_BASE_URL=/api - NODE_ENV=production restart: always @@ -47,7 +48,7 @@ services: image: caddy:latest ports: - 80:80 - - 8443:443 + - 443:443 volumes: - ./caddy/data:/data/caddy - ./Caddyfile:/etc/caddy/Caddyfile diff --git a/frontend/.gitignore b/frontend/.gitignore index a547bf3..427caf3 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -22,3 +22,11 @@ dist-ssr *.njsproj *.sln *.sw? + +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions \ No newline at end of file diff --git a/frontend/.yarn/install-state.gz b/frontend/.yarn/install-state.gz deleted file mode 100644 index 0578a7b..0000000 Binary files a/frontend/.yarn/install-state.gz and /dev/null differ diff --git a/frontend/README.md b/frontend/README.md index bf717e5..1f45491 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -19,3 +19,16 @@ yarn dev If you're having issues with your editor picking up types in TypeScript, follow the [yarn editor sdk docs](https://yarnpkg.com/getting-started/editor-sdks). This repo already includes Visual Studio Code sdks, but they may need to be augmented or regenerated. If you're using VSCode, make sure you install the recommended extensions. More info can be found in [the yarn docs](https://yarnpkg.com/getting-started/editor-sdks#vscode) + +## Notes + +The production portion of the frontend runs with an Express server to serve the static files so that you can switch out the api url as needed without rebuilding the container. You can change this by passing `VITE_BASE_API_URL` to the frontend container: + +```yml +frontend: +image: ghcr.io/meshaddicts/meshinfo-spa:latest +ports: + - 8000:80 +environment: + - VITE_API_BASE_URL=/api +``` diff --git a/frontend/nginx.conf b/frontend/nginx.conf deleted file mode 100644 index 25fa959..0000000 --- a/frontend/nginx.conf +++ /dev/null @@ -1,14 +0,0 @@ -server { - listen 80; - - root /usr/share/nginx/html; - index index.html; - - location /api/ { - proxy_pass http://meshinfo:9000/; - } - - location / { - try_files $uri $uri/ /next/index.html; - } -} \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 4969406..ae3e011 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,7 +15,9 @@ "autoprefixer": "^10.4.19", "date-fns": "^3.6.0", "date-fns-tz": "^3.1.3", + "express": "^4.19.2", "ol": "^9.2.4", + "pm2": "^5.4.2", "postcss": "^8.4.38", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -24,6 +26,7 @@ "tailwindcss": "^3.4.4" }, "devDependencies": { + "@types/express": "^4", "@types/react": "^18.2.66", "@types/react-dom": "^18.2.22", "@typescript-eslint/eslint-plugin": "^7.0.0", diff --git a/frontend/scripts/run-frontend.sh b/frontend/scripts/run-frontend.sh new file mode 100755 index 0000000..6b39205 --- /dev/null +++ b/frontend/scripts/run-frontend.sh @@ -0,0 +1,2 @@ +echo "API BASE URL: " $VITE_API_BASE_URL +yarn build --base=/next/ && npx pm2-runtime /frontend/scripts/server.js diff --git a/frontend/scripts/server.js b/frontend/scripts/server.js new file mode 100644 index 0000000..430e4a7 --- /dev/null +++ b/frontend/scripts/server.js @@ -0,0 +1,27 @@ +import express from "express"; +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const app = express(); +const port = process.env.PORT || 80; + +// Serve static files from the dist directory +app.use("/next", express.static(path.join(__dirname, "../dist"))); + +// log all requests +app.use((req, res, next) => { + console.log(req.method, req.url); + next(); +}); + +// Handle every other route with index.html, which will contain a script tag to your application's JavaScript +app.get("/next/*", (req, res) => { + res.sendFile(path.join(__dirname, "../dist", "index.html")); +}); + +app.listen(port, () => { + console.log(`Server is running on port ${port}`); +}); diff --git a/frontend/src/components/HeardBy.tsx b/frontend/src/components/HeardBy.tsx index a257aa7..c1582b6 100644 --- a/frontend/src/components/HeardBy.tsx +++ b/frontend/src/components/HeardBy.tsx @@ -9,10 +9,10 @@ export const HeardBy = () => { <> {" "} that have been heard by the mesh by{" "} - - {config?.server.node_id} + + {config?.server?.node_id} {" "} - ({config?.server.node_id}) + ({config?.server?.node_id}) ); }; diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index c7fb617..2e556ba 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -2,6 +2,14 @@ import { Link, useLocation } from "react-router-dom"; import { useGetConfigQuery } from "../slices/apiSlice"; +const defaultTools = [ + { name: "Armooo's MeshView", url: "https://meshview.armooo.net" }, + { name: "Liam's Meshtastic Map", url: "https://meshtastic.liamcottle.net" }, + { name: "MeshMap", url: "https://meshmap.net" }, + { name: "Bay Mesh Explorer", url: "https://app.bayme.sh" }, + { name: "HWT Path Profiler", url: "https://heywhatsthat.com/profiler.html" }, +]; + export const Layout = ({ children }: { children: React.ReactNode }) => { const { pathname } = useLocation(); const { data: config } = useGetConfigQuery(); @@ -12,7 +20,7 @@ export const Layout = ({ children }: { children: React.ReactNode }) => {
- {config?.mesh.name.split(" ").map((word, index) => ( + {config?.mesh?.name?.split(" ").map((word, index) => ( // eslint-disable-next-line react/no-array-index-key
{word[0]} @@ -22,10 +30,10 @@ export const Layout = ({ children }: { children: React.ReactNode }) => {
-
{config?.mesh.description}
+
{config?.mesh?.description}
- + Website
@@ -150,7 +158,7 @@ export const Layout = ({ children }: { children: React.ReactNode }) => {