Browse Source

Fix: markdownlint MD012/MD019 errors in build-pattern-conversion-plan.md

- Removed extra blank lines at end of file to resolve MD012 (no-multiple-blanks)
- Standardized heading spacing to resolve MD019 (no-multiple-space-atx)
- Stripped trailing whitespace and ensured file ends with a single newline

All changes maintain content integrity and bring the file into full markdownlint compliance.
web-serve-fix
Matthew Raymer 2 weeks ago
parent
commit
7aa7056207
  1. 1
      .env.development
  2. 1
      .env.production
  3. 1
      .env.test
  4. 2
      BUILDING.md
  5. 93
      Dockerfile
  6. 100
      docker-compose.yml
  7. 4
      docker/README.md
  8. 75
      docs/build-pattern-conversion-plan.md
  9. 3
      docs/playwright_mcp.md
  10. 19
      package.json
  11. 37
      scripts/format-markdown.sh
  12. 2
      src/main.common.ts
  13. 11
      src/main.web.ts
  14. 18
      vite.config.common.mts
  15. 74
      vite.config.web.mts

1
.env.development

@ -1 +1,2 @@
VITE_DEFAULT_ENDORSER_API_SERVER=http://127.0.0.1:3000
VITE_PWA_ENABLED=true

1
.env.production

@ -10,3 +10,4 @@ VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch
VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app
VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch
VITE_DEFAULT_PUSH_SERVER=https://timesafari.app
VITE_PWA_ENABLED=true

1
.env.staging → .env.test

@ -11,3 +11,4 @@ VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app
VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch
VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app
VITE_PASSKEYS_ENABLED=true
VITE_PWA_ENABLED=false

2
BUILDING.md

@ -83,7 +83,7 @@ TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.
rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari
```
(Let's replace that with a .env.development or .env.staging file.)
(Let's replace that with a .env.development or .env.test file.)
(Note: The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.)

93
Dockerfile

@ -4,9 +4,11 @@
#
# Build Process:
# 1. Base stage: Node.js with build dependencies
# 2. Builder stage: Compile web assets with Vite
# 2. Builder stage: Copy pre-built web assets from host
# 3. Production stage: Nginx server with optimized assets
#
# Note: Web assets are built on the host using npm scripts before Docker build
#
# Security Features:
# - Non-root user execution
# - Minimal attack surface with Alpine Linux
@ -14,25 +16,26 @@
# - No build dependencies in final image
#
# Usage:
# Production: docker build -t timesafari:latest .
# Staging: docker build --build-arg BUILD_MODE=staging -t timesafari:staging .
# Development: docker build --build-arg BUILD_MODE=development -t timesafari:dev .
# IMPORTANT: Build web assets first, then build Docker image
#
# Using npm scripts (recommended):
# Production: npm run build:web:docker:prod
# Test: npm run build:web:docker:test
# Development: npm run build:web:docker
#
# Manual workflow:
# 1. Build web assets: npm run build:web:build -- --mode production
# 2. Build Docker: docker build -t timesafari:latest .
#
# Note: For development, use npm run build:web directly (no Docker needed)
#
# Build Arguments:
# BUILD_MODE: development, staging, or production (default: production)
# BUILD_MODE: development, test, or production (default: production)
# NODE_ENV: node environment (default: production)
# VITE_PLATFORM: vite platform (default: web)
# VITE_PWA_ENABLED: enable PWA (default: true)
# VITE_DISABLE_PWA: disable PWA (default: false)
#
# Environment Variables:
# NODE_ENV: Build environment (development/production)
# VITE_APP_SERVER: Application server URL
# VITE_DEFAULT_ENDORSER_API_SERVER: Endorser API server URL
# VITE_DEFAULT_IMAGE_API_SERVER: Image API server URL
# VITE_DEFAULT_PARTNER_API_SERVER: Partner API server URL
# VITE_DEFAULT_PUSH_SERVER: Push notification server URL
# VITE_PASSKEYS_ENABLED: Enable passkeys feature
# BUILD_MODE: Build mode for asset selection (development/test/production)
# =============================================================================
# BASE STAGE - Common dependencies and setup
@ -66,34 +69,20 @@ RUN npm ci --only=production --audit --fund=false && \
npm audit fix --audit-level=moderate || true
# =============================================================================
# BUILDER STAGE - Compile web assets
# BUILDER STAGE - Copy pre-built assets
# =============================================================================
FROM base AS builder
# Define build arguments with defaults
ARG BUILD_MODE=production
ARG NODE_ENV=production
ARG VITE_PLATFORM=web
ARG VITE_PWA_ENABLED=true
ARG VITE_DISABLE_PWA=false
# Set environment variables from build arguments
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
ENV VITE_PLATFORM=${VITE_PLATFORM}
ENV VITE_PWA_ENABLED=${VITE_PWA_ENABLED}
ENV VITE_DISABLE_PWA=${VITE_DISABLE_PWA}
# Install all dependencies (including dev dependencies)
RUN npm ci --audit --fund=false && \
npm audit fix --audit-level=moderate || true
# Copy source code
COPY . .
# Build the application with proper error handling
RUN echo "Building TimeSafari in ${BUILD_MODE} mode..." && \
npm run build:web || (echo "Build failed. Check the logs above." && exit 1)
# Copy pre-built assets from host
COPY dist/ ./dist/
# Verify build output exists
RUN ls -la dist/ || (echo "Build output not found in dist/ directory" && exit 1)
@ -150,52 +139,22 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
# Start nginx with proper signal handling
CMD ["nginx", "-g", "daemon off;"]
# =============================================================================
# DEVELOPMENT STAGE - For development with hot reloading
# =============================================================================
FROM base AS development
# Define build arguments for development stage
ARG BUILD_MODE=development
ARG NODE_ENV=development
ARG VITE_PLATFORM=web
ARG VITE_PWA_ENABLED=true
ARG VITE_DISABLE_PWA=false
# Set environment variables
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
ENV VITE_PLATFORM=${VITE_PLATFORM}
ENV VITE_PWA_ENABLED=${VITE_PWA_ENABLED}
ENV VITE_DISABLE_PWA=${VITE_DISABLE_PWA}
# Install all dependencies including dev dependencies
RUN npm ci --audit --fund=false && \
npm audit fix --audit-level=moderate || true
# Copy source code
COPY . .
# Expose development port
EXPOSE 5173
# Start development server
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
# =============================================================================
# STAGING STAGE - For staging environment testing
# TEST STAGE - For test environment testing
# =============================================================================
FROM production AS staging
FROM production AS test
# Define build arguments for staging stage
ARG BUILD_MODE=staging
ARG NODE_ENV=staging
# Define build arguments for test stage
ARG BUILD_MODE=test
ARG NODE_ENV=test
# Set environment variables
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
# Copy staging-specific nginx configuration
# Copy test-specific nginx configuration
COPY docker/staging.conf /etc/nginx/conf.d/default.conf
# Expose port 80

100
docker-compose.yml

@ -2,24 +2,21 @@
# Author: Matthew Raymer
# Description: Multi-environment Docker Compose setup for TimeSafari
#
# IMPORTANT: Build web assets first using npm scripts before running docker-compose
#
# Usage:
# Development: docker-compose up dev
# Staging: docker-compose up staging
# Production: docker-compose up production
# Custom: BUILD_MODE=staging docker-compose up custom
# Development: npm run build:web:build -- --mode development && docker-compose up dev
# Test: npm run build:web:build -- --mode test && docker-compose up test
# Production: npm run build:web:build -- --mode production && docker-compose up production
# Custom: BUILD_MODE=test npm run build:web:build -- --mode test && docker-compose up custom
#
# Environment Variables:
# BUILD_MODE: development, staging, or production (default: production)
# BUILD_MODE: development, test, or production (default: production)
# NODE_ENV: node environment (default: production)
# VITE_PLATFORM: vite platform (default: web)
# VITE_PWA_ENABLED: enable PWA (default: true)
# VITE_DISABLE_PWA: disable PWA (default: false)
# PORT: port to expose (default: 80 for production, 5173 for dev)
# PORT: port to expose (default: 80 for production, 8080 for test)
# ENV_FILE: environment file to use (default: .env.production)
#
# See .env files for application-specific configuration
# VITE_APP_SERVER: Application server URL
# VITE_DEFAULT_ENDORSER_API_SERVER: Endorser API server URL
# Note: For development, use npm run build:web directly (no Docker needed)
version: '3.8'
@ -31,9 +28,6 @@ x-defaults: &defaults
args:
BUILD_MODE: ${BUILD_MODE:-production}
NODE_ENV: ${NODE_ENV:-production}
VITE_PLATFORM: ${VITE_PLATFORM:-web}
VITE_PWA_ENABLED: ${VITE_PWA_ENABLED:-true}
VITE_DISABLE_PWA: ${VITE_DISABLE_PWA:-false}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
@ -43,60 +37,23 @@ x-defaults: &defaults
start_period: 40s
services:
# Development service with hot reloading
dev:
<<: *defaults
build:
context: .
dockerfile: Dockerfile
target: development
args:
BUILD_MODE: development
NODE_ENV: development
VITE_PLATFORM: web
VITE_PWA_ENABLED: true
VITE_DISABLE_PWA: false
ports:
- "${DEV_PORT:-5173}:5173"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
- VITE_PLATFORM=web
- VITE_PWA_ENABLED=true
- VITE_DISABLE_PWA=false
env_file:
- ${DEV_ENV_FILE:-.env.development}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5173"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Staging service for testing
staging:
# Test service for testing environment
test:
<<: *defaults
build:
context: .
dockerfile: Dockerfile
target: staging
target: test
args:
BUILD_MODE: staging
NODE_ENV: staging
VITE_PLATFORM: web
VITE_PWA_ENABLED: true
VITE_DISABLE_PWA: false
BUILD_MODE: test
NODE_ENV: test
ports:
- "${STAGING_PORT:-8080}:80"
- "${TEST_PORT:-8080}:80"
environment:
- NODE_ENV=staging
- VITE_PLATFORM=web
- VITE_PWA_ENABLED=true
- VITE_DISABLE_PWA=false
- NODE_ENV=test
- BUILD_MODE=test
env_file:
- ${STAGING_ENV_FILE:-.env.staging}
- ${TEST_ENV_FILE:-.env.test}
# Production service
production:
@ -108,16 +65,11 @@ services:
args:
BUILD_MODE: production
NODE_ENV: production
VITE_PLATFORM: web
VITE_PWA_ENABLED: true
VITE_DISABLE_PWA: false
ports:
- "${PROD_PORT:-80}:80"
environment:
- NODE_ENV=production
- VITE_PLATFORM=web
- VITE_PWA_ENABLED=true
- VITE_DISABLE_PWA=false
- BUILD_MODE=production
env_file:
- ${PROD_ENV_FILE:-.env.production}
@ -131,17 +83,12 @@ services:
args:
BUILD_MODE: production
NODE_ENV: production
VITE_PLATFORM: web
VITE_PWA_ENABLED: true
VITE_DISABLE_PWA: false
ports:
- "${SSL_PORT:-443}:443"
- "${HTTP_PORT:-80}:80"
environment:
- NODE_ENV=production
- VITE_PLATFORM=web
- VITE_PWA_ENABLED=true
- VITE_DISABLE_PWA=false
- BUILD_MODE=production
env_file:
- ${PROD_ENV_FILE:-.env.production}
volumes:
@ -164,16 +111,11 @@ services:
args:
BUILD_MODE: ${BUILD_MODE:-production}
NODE_ENV: ${NODE_ENV:-production}
VITE_PLATFORM: ${VITE_PLATFORM:-web}
VITE_PWA_ENABLED: ${VITE_PWA_ENABLED:-true}
VITE_DISABLE_PWA: ${VITE_DISABLE_PWA:-false}
ports:
- "${CUSTOM_PORT:-8080}:${CUSTOM_INTERNAL_PORT:-80}"
environment:
- NODE_ENV=${NODE_ENV:-production}
- VITE_PLATFORM=${VITE_PLATFORM:-web}
- VITE_PWA_ENABLED=${VITE_PWA_ENABLED:-true}
- VITE_DISABLE_PWA=${VITE_DISABLE_PWA:-false}
- BUILD_MODE=${BUILD_MODE:-production}
env_file:
- ${CUSTOM_ENV_FILE:-.env.production}
healthcheck:

4
docker/README.md

@ -121,7 +121,7 @@ Docker Compose supports these environment variables:
| `STAGING_PORT` | `8080` | Staging port |
| `PROD_PORT` | `80` | Production port |
| `DEV_ENV_FILE` | `.env.development` | Development env file |
| `STAGING_ENV_FILE` | `.env.staging` | Staging env file |
| `TEST_ENV_FILE` | `.env.test` | Test env file |
| `PROD_ENV_FILE` | `.env.production` | Production env file |
### Environment Files
@ -137,7 +137,7 @@ VITE_DEFAULT_PARTNER_API_SERVER=https://dev-partner-api.endorser.ch
VITE_DEFAULT_PUSH_SERVER=https://dev.timesafari.app
VITE_PASSKEYS_ENABLED=true
# .env.staging
# .env.test
VITE_APP_SERVER=https://staging.timesafari.app
VITE_DEFAULT_ENDORSER_API_SERVER=https://staging-api.endorser.ch
VITE_DEFAULT_IMAGE_API_SERVER=https://staging-image-api.timesafari.app

75
docs/build-pattern-conversion-plan.md

@ -2,7 +2,7 @@
**Author**: Matthew Raymer
**Date**: 2025-07-09
**Status**: 🎯 **PLANNING** - Ready for Implementation
**Status**: **PLANNING** - Ready for Implementation
## Overview
@ -12,7 +12,7 @@ management and consistency across all build targets.
## Why Vite Mode Instead of NODE_ENV?
### Vite's Native Mode System
### Vite's Native Mode System
Vite is designed to work with `mode`, which:
@ -21,7 +21,7 @@ Vite is designed to work with `mode`, which:
- Is used to set behavior for dev/prod/test at config level
- Provides better integration with Vite's build system
### 🚫 NODE_ENV Limitations
### NODE_ENV Limitations
`NODE_ENV` is legacy from Webpack-era tooling:
@ -33,23 +33,25 @@ Vite is designed to work with `mode`, which:
### Usage Pattern
```bash
# Correct: Use Vite's mode system
# Correct: Use Vite's mode system
vite build --mode production
vite build --mode development
vite build --mode test
# ⚠️ Only if third-party libraries require NODE_ENV
# Only if third-party libraries require NODE_ENV
NODE_ENV=production vite build --mode production
```
### Development vs Build Environments
**Development Environment:**
- **Build with defaults**: `npm run build:*` - Uses `--mode development` by default
- **Purpose**: Development builds for testing and debugging
- **Output**: Bundled files with development optimizations
**Testing/Production Environments:**
- **Build with explicit mode**: `npm run build:* -- --mode test/production`
- **Purpose**: Validate and deploy the bundled application
- **Output**: Optimized, bundled files for specific environment
@ -76,6 +78,7 @@ npm run build:electron -- --mode production
```
**Key Points:**
- Base scripts have **no hardcoded `--mode`** to allow override
- `npm run build:electron` defaults to `--mode development`
- `npm run build:electron -- --mode test` overrides to `--mode test`
@ -98,6 +101,36 @@ npm run build:capacitor -- --mode production && npx cap sync android
npm run build:capacitor -- --mode development && npx cap sync ios
```
### Docker Build Commands
Docker builds include both Vite asset generation and Docker image creation:
```bash
# General Docker build (Vite build + Docker image)
npm run build:web:docker
# Environment-specific Docker builds
npm run build:web:docker:test # Test environment + Docker image
npm run build:web:docker:prod # Production environment + Docker image
# Manual mode overrides for Docker builds
npm run build:web:docker -- --mode test
npm run build:web:docker -- --mode production
```
**Docker Build Process:**
1. **Vite Build**: Creates optimized web assets with environment-specific variables
2. **Docker Build**: Creates Docker image using `Dockerfile` in project root
3. **Image Tagging**: Images are tagged as `timesafari-web` for consistent management
**Key Features:**
- Complete end-to-end Docker workflow in single command
- Environment-aware builds (test/production configurations)
- Consistent image tagging for deployment
- Mode override flexibility for custom environments
### Electron Platform-Specific Commands
Electron requires platform-specific build commands after the Vite build:
@ -189,8 +222,12 @@ npm run build:capacitor -- --mode production && npx cap sync
npm run build:electron -- --mode production
# Docker builds
npm run build:web-docker -- --mode test
npm run build:web-docker -- --mode production
npm run build:web:docker -- --mode test
npm run build:web:docker -- --mode production
# Docker environment-specific builds
npm run build:web:docker:test
npm run build:web:docker:prod
# Capacitor platform-specific builds
npm run build:capacitor:android -- --mode test
@ -221,11 +258,12 @@ npm run build:electron:dmg -- --mode production
```json
{
"build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts",
"build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite --mode development --config vite.config.web.mts",
"build:web:dev": "npm run build:web",
"build:web:test": "npm run build:web -- --mode test",
"build:web:prod": "npm run build:web -- --mode production"
"build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts",
"build:web:build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode development --config vite.config.web.mts",
"build:web:test": "npm run build:web:build -- --mode test",
"build:web:prod": "npm run build:web:build -- --mode production",
"build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .",
"build:web:docker:test": "npm run build:web:docker -- --mode test",
"build:web:docker:prod": "npm run build:web:docker -- --mode production",
@ -348,12 +386,19 @@ export default defineConfig(({ mode }) => {
```json
{
"build:web-docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts",
"build:web-docker-test": "npm run build:web-docker -- --mode test",
"build:web-docker-prod": "npm run build:web-docker -- --mode production"
"build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .",
"build:web:docker:test": "npm run build:web:docker -- --mode test",
"build:web:docker:prod": "npm run build:web:docker -- --mode production"
}
```
**Docker Build Features:**
- Complete Vite build + Docker image creation workflow
- Environment-specific configurations (test/production)
- Consistent image tagging (`timesafari-web`)
- Mode override flexibility for custom environments
### Phase 3: Shell Script Updates (Day 2)
#### 3.1 Update build-electron.sh
@ -418,6 +463,8 @@ export default defineConfig(({ mode }) => {
- [ ] Test electron appimage builds across environments
- [ ] Test electron dmg builds across environments
- [ ] Test docker builds across environments
- [ ] Test docker image creation and tagging
- [ ] Test docker environment-specific configurations
#### 5.3 Integration Testing

3
docs/playwright_mcp.md

@ -36,7 +36,6 @@ First, install the Playwright MCP server with your client. A typical configurati
[<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in VS Code">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) [<img alt="Install in VS Code Insiders" src="https://img.shields.io/badge/VS_Code_Insiders-VS_Code_Insiders?style=flat-square&label=Install%20Server&color=24bfa5">](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D)
<details><summary><b>Install in VS Code</b></summary>
You can also install the Playwright MCP server using the VS Code CLI:
@ -791,5 +790,5 @@ X Y coordinate space, based on the provided screenshot.
</details>
<!--- End of tools generated section -->

19
package.json

@ -6,11 +6,6 @@
"name": "Time Safari Team"
},
"scripts": {
"dev": "vite --config vite.config.dev.mts --host",
"serve": "vite preview",
"build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.mts",
"build:optimized": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.optimized.mts",
"dev:optimized": "vite --config vite.config.optimized.mts --host",
"lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src",
"lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src",
"prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js",
@ -23,7 +18,19 @@
"check:android-device": "adb devices | grep -w 'device' || (echo 'No Android device connected' && exit 1)",
"check:ios-device": "xcrun xctrace list devices 2>&1 | grep -w 'Booted' || (echo 'No iOS simulator running' && exit 1)",
"build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts",
"build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts",
"build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite --mode development --config vite.config.web.mts",
"build:web:dev": "npm run build:web",
"build:web:build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode development --config vite.config.web.mts",
"build:web:test": "npm run build:web:build -- --mode test",
"build:web:prod": "npm run build:web:build -- --mode production",
"build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .",
"build:web:docker:test": "npm run build:web:docker -- --mode test",
"build:web:docker:prod": "npm run build:web:docker -- --mode production",
"docker:up": "docker-compose up",
"docker:up:test": "npm run build:web:build -- --mode test && docker-compose up test",
"docker:up:prod": "npm run build:web:build -- --mode production && docker-compose up production",
"docker:down": "docker-compose down",
"docker:logs": "docker-compose logs -f",
"build:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode electron --config vite.config.electron.mts",
"electron:dev": "npm run build:electron && npx cap copy electron && cd electron && npm run electron:start",
"electron:setup": "./scripts/setup-electron.sh",

37
scripts/format-markdown.sh

@ -0,0 +1,37 @@
#!/usr/bin/env bash
# format-markdown.sh
# Author: Matthew Raymer
# Date: 2025-07-09
# Description: Format markdown files to comply with project markdown ruleset
set -e
if [ $# -eq 0 ]; then
echo "Usage: $0 <file-or-directory> [more files...]"
exit 1
fi
for target in "$@"; do
if [ -d "$target" ]; then
files=$(find "$target" -type f -name "*.md")
else
files="$target"
fi
for file in $files; do
# Remove trailing spaces
sed -i 's/[[:space:]]*$//' "$file"
# Remove multiple consecutive blank lines
awk 'NF{blank=0} !NF{blank++} blank<2' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
# Ensure file ends with a single newline
awk '1; END{if (NR && $0!="") print ""}' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
# Optionally run markdownlint (requires npx and markdownlint-cli)
if command -v npx >/dev/null 2>&1; then
npx markdownlint "$file"
else
echo "npx/markdownlint not found, skipping lint check for $file"
fi
done
done
echo "Markdown formatting complete."

2
src/main.common.ts

@ -10,8 +10,6 @@ import { FontAwesomeIcon } from "./libs/fontawesome";
import Camera from "simple-vue-camera";
import { logger } from "./utils/logger";
// const platform = process.env.VITE_PLATFORM;
// const pwa_enabled = process.env.VITE_PWA_ENABLED === "true";
// Global Error Handler
function setupGlobalErrorHandler(app: VueApp) {

11
src/main.web.ts

@ -4,17 +4,6 @@ import { logger } from "./utils/logger";
const platform = process.env.VITE_PLATFORM;
const pwa_enabled = process.env.VITE_PWA_ENABLED === "true";
// Only log SharedArrayBuffer info for web platform in development
if (platform === "web" && process.env.NODE_ENV !== "production") {
logger.debug(
`[SharedArrayBuffer] Available: ${typeof SharedArrayBuffer !== "undefined"}`,
);
logger.debug(`[Browser] User Agent: ${navigator.userAgent}`);
logger.debug(
`[Headers] Check COOP/COEP in Network tab if SharedArrayBuffer is false`,
);
}
// Only import service worker for web builds
if (pwa_enabled) {
import("./registerServiceWorker"); // Web PWA support

18
vite.config.common.mts

@ -11,16 +11,19 @@ dotenv.config();
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export async function createBuildConfig(mode: string): Promise<UserConfig> {
export async function createBuildConfig(platform: string): Promise<UserConfig> {
const appConfig = await loadAppConfig();
const isCapacitor = mode === "capacitor";
const isElectron = mode === "electron";
const isCapacitor = platform === "capacitor";
const isElectron = platform === "electron";
const isNative = isCapacitor || isElectron;
// Set platform and disable PWA for native platforms
process.env.VITE_PLATFORM = mode;
// Set platform and configure PWA based on environment or platform
process.env.VITE_PLATFORM = platform;
// Use .env file value if set, otherwise default based on platform
if (process.env.VITE_PWA_ENABLED === undefined) {
process.env.VITE_PWA_ENABLED = isNative ? 'false' : 'true';
process.env.VITE_DISABLE_PWA = isNative ? 'true' : 'false';
}
if (isNative) {
process.env.VITE_PWA_ENABLED = 'false';
@ -59,9 +62,8 @@ export async function createBuildConfig(mode: string): Promise<UserConfig> {
},
define: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.VITE_PLATFORM': JSON.stringify(mode),
'process.env.VITE_PLATFORM': JSON.stringify(platform),
'process.env.VITE_PWA_ENABLED': JSON.stringify(!isNative),
'process.env.VITE_DISABLE_PWA': JSON.stringify(isNative),
__dirname: JSON.stringify(process.cwd()),
__IS_MOBILE__: JSON.stringify(isCapacitor),
__IS_ELECTRON__: JSON.stringify(isElectron),

74
vite.config.web.mts

@ -3,11 +3,79 @@ import { VitePWA } from "vite-plugin-pwa";
import { createBuildConfig } from "./vite.config.common.mts";
import { loadAppConfig } from "./vite.config.utils.mts";
export default defineConfig(async () => {
export default defineConfig(async ({ mode }) => {
const baseConfig = await createBuildConfig('web');
const appConfig = await loadAppConfig();
// Environment-specific configuration based on mode
const getEnvironmentConfig = (mode: string) => {
switch (mode) {
case 'production':
return {
// Production optimizations
build: {
minify: 'terser',
sourcemap: false,
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
utils: ['luxon', 'ramda', 'zod'],
crypto: ['@ethersproject/wallet', '@ethersproject/hdnode', 'ethereum-cryptography'],
sql: ['@jlongster/sql.js', 'absurd-sql']
}
}
}
},
define: {
__DEV__: false,
__TEST__: false,
__PROD__: true
}
};
case 'test':
return {
// Test environment configuration
build: {
minify: false,
sourcemap: true,
rollupOptions: {
output: {
manualChunks: undefined
}
}
},
define: {
__DEV__: false,
__TEST__: true,
__PROD__: false
}
};
default: // development
return {
// Development configuration
build: {
minify: false,
sourcemap: true,
rollupOptions: {
output: {
manualChunks: undefined
}
}
},
define: {
__DEV__: true,
__TEST__: false,
__PROD__: false
}
};
}
};
const environmentConfig = getEnvironmentConfig(mode);
return mergeConfig(baseConfig, {
...environmentConfig,
// Server configuration inherited from base config
// CORS headers removed to allow images from any domain
plugins: [
@ -15,13 +83,13 @@ export default defineConfig(async () => {
registerType: 'autoUpdate',
manifest: appConfig.pwaConfig?.manifest,
devOptions: {
enabled: false
enabled: mode === 'development'
},
workbox: {
cleanupOutdatedCaches: true,
skipWaiting: true,
clientsClaim: true,
sourcemap: true,
sourcemap: mode !== 'production',
maximumFileSizeToCacheInBytes: 10 * 1024 * 1024 // 10MB
}
})

Loading…
Cancel
Save