- Proximiio Wayfinding Client
- Installation
- Configuration
- Usage
- Building the App
- Dockerization
- Changing Default Colors
- Configuring Manifest with Vite-PWA
- Project Structure
- Initiate the map with url params
To get started, clone this repository:
git clone https://github.com/proximiio/wayfinding-react-client.git
cd wayfinding-react-client
# Install dependencies
npm install
# or
yarnBefore you run development server please check out .env file and fill the configuration fields with your data.
# Base URL app will be initiated with
# when you define e.g '/something', your app will be available at http://localhost:6001/something
# some more edits are required when defining this, check out below
BASE_URL=
PORT=6001 # app dev/preview server will run on this port
VITE_APP_TITLE=Proximi.io - Wayfinding Client # app title
VITE_PROXIMIIO_TOKEN=PASTE YOUR TOKEN HERE # fill your proximi.io token here
VITE_PROXIMIIO_API=https://api.proximi.fi # api address, you don't need to change this
VITE_PROXIMIIO_GEO_VERSION=v5 # geo api version, you don't need to change this
# default place id your app will be initated with
VITE_WAYFINDING_DEFAULT_PLACE_ID=PASTE YOUR DEFAULT PLACE ID HERE
# define feature id which is considered as entrance of your venue
# it's also default starting point for kiosks
VITE_WAYFINDING_ENTRANCE_FEATURE_ID=PASTE YOUR ENTRANCE FEATURE ID HERE
# define parking amenity id if you have one
VITE_WAYFINDING_PARKING_AMENITY_ID=PASTE YOUR PARKING AMENITY ID HERE
# default longitude coordinate for map center
VITE_WAYFINDING_DEFAULT_LOCATION_LONGITUDE=longitude
# default latitude coordinate for map center
VITE_WAYFINDING_DEFAULT_LOCATION_LATITUDE=latitude
# default level your app will be initiated on
VITE_WAYFINDING_DEFAULT_LOCATION_LEVEL=0
# default map zoom
VITE_WAYFINDING_DEFAULT_ZOOM=19
# default map pitch
VITE_WAYFINDING_DEFAULT_PITCH=40
# default map bearing
VITE_WAYFINDING_DEFAULT_BEARING=12
# show/hide language toggle component
VITE_WAYFINDING_SHOW_LANGUAGE_TOGGLE=false
# show/hide reset button component (will reset the view and refetch data)
VITE_WAYFINDING_SHOW_RESET_BUTTON=false
# if app is initated as kiosk enable/disable virtual keyboard
VITE_WAYFINDING_USE_VIRTUAL_KEYBOARD_AT_KIOSKS=false
# use your device gps location within the app
VITE_WAYFINDING_USE_GPS_LOCATION=false
# enable/disable auto data refetch in default 1 hour interval
VITE_WAYFINDING_AUTO_DATA_REFETCH=false
# change interval for auto data refetch
VITE_WAYFINDING_REFETCH_INTERVAL=3600000 # 1 hour
# max 4 items per category, the last one will be toggle button
VITE_WAYFINDING_CATEGORY_ITEMS_LIMIT=5
# show/hide ads sidebar
VITE_WAYFINDING_SHOW_ADS=true
# time after last interaction, user session will be resetted
VITE_WAYFINDING_SESSION_TIMEOUT=60000 # 1 minuteAfter you change your BASE_URL in .env file to e.g /something, there are few more parts of code required to change. In case you don't plan to dockerize your app, only step 1 is mandatory.
- in
src/i18n.tscomment out line 31 and uncomment line 30, this is necessary to keep translations working in production - If dockerizing: in
Dockerfilecheck line 22-26, uncomment line 23 and comment out line 26, also don't forget to paste yourBASE_URLin line 23 - If dockerizing: in
nginx.confcomment out lines 38-42 and uncomment 45-49 and don't forget to paste yourBASE_URL
Run the development server:
npm run dev
# or
yarn devOpen http://localhost:6001 to view it in your browser.
To build the app for production:
npm run build
# or
yarn buildTo build a Docker image for this app:
docker build -t proximiio-wayfinding-client .Run the Docker container:
docker run -p 8080:80 proximiio-wayfinding-clientThe app will be available at http://localhost:8080.
This project utilizes vite-plugin-pwa for Progressive Web App (PWA) functionality. To configure the manifest file using Vite-PWA, follow these steps:
-
Locate the Configuration File: The Vite-PWA plugin allows you to configure the PWA manifest file. Look for the
vite.config.tsfile in the root directory of your project. -
Update the Plugin Configuration: Within the Vite configuration file, find the section where the
vite-plugin-pwais defined. There, you can specify various settings including themanifestobject.import { VitePWA } from 'vite-plugin-pwa'; export default { plugins: [ VitePWA({ manifest: { /* Add or modify manifest properties here */ name: 'Your App Name', short_name: 'Short Name', /* Other manifest properties */ }, /* Other Vite-PWA configurations */ }), ], };
-
Edit Manifest Properties: Customize the properties within the
manifestobject according to your application's requirements. This includes the app's name, short name, icons, theme color, background color, and other relevant metadata. -
Generate App Icons: Ensure you have app icons in various sizes to support different devices. You can use online tools or generators like favicon.io and maskable.app to create these icons and replace the default ones specified in the manifest.
-
Test the PWA: After making changes to the manifest configuration, rebuild your app (
npm run buildoryarn build) and test the PWA functionality on a supported browser or device.
Our app use TailwindCSS and shadcn/ui component library for styling.
-
Locate the CSS Variables: To change default colors, look for a
src/index.cssfile. -
Override Variables: Change values for variables defined in
:rootsection, you'll be probably most interested in--primary, --secondary, --accentand their-foregroundvariables, use HSL color values./* In this example we change primary to black and primary-foreground to white */ :root { --primary: 0 0% 0%; --primary-foreground: 100 100% 100%; }
In our app we use same color for secondary and accent but you can of course use different for each of them if required.
Briefly explain the structure of your project, especially if it deviates from the default Vite or React setup. You can mention key directories or files and their purposes.
Here's an overview of the directory structure of this project:
proximiio-wayfinding-client/
│
├── public/
│ ├── locales/ (translations json files)
│ ├── ... (PWA manifest files)
│ └── ... (other static assets)
│
├── src/
│ ├── components/
│ │ ├── ui/ (UI components)
│ │ ├── MapView.tsx (place where we initate the map, you can change map configuration here)
│ │ └── ... (other react components)
│ │
│ ├── hooks/
│ │ ├── useKiosk.tsx (Custom hook for handling kiosk behavior)
│ │ └── useRouting.tsx (Custom hook for handling route finding)
│ │
│ ├── lib/
│ │ └── utils.ts (Utility functions)
│ │
│ ├── models/
│ │ └── ... (some custom interface models)
│ │
│ ├── store/
│ │ ├── data.ts (We store there some static data for filters and kiosks)
│ │ └── mapStore.ts (Global data store)
│ │
│ ├── App.tsx (the place where the app is initialized)
│ ├── i18n.ts (internationalizations config)
│ ├── index.css (styling)
│ └── ... (other main project files)
│
├── .env (configurations file)
├── .gitignore
├── DockerFile (Docker configuration)
├── index.html
├── nginx.conf (Nginx configuration file for dockerizing)
├── package.json
├── README.md
└── ... (other configuration files or additional folders)In file src/store/data.ts you can define filterItems which are then displayed in a Sidebar component via Filters component. In the same file you can define kiosks which is a list of venue kiosks and the app can be initiated as kiosk via urlParams using the kiosk name parameter defined there.
Model for filter items can be found here src/models/filterItem.model.tsx.
export interface FilterItemModel {
title: string;
icon?: string;
iconImage?: string;
id: string | string[];
type: 'list' | 'closest';
}Based on this, every FilterItem entry should contain:
typewe have two types of filters,listwhich will list all available features in PoiList component and theclosestwhich should automatically pick up closest feature to starting pointtitlewhich should be string defined intranslation.jsonfileicon/iconImagefor icon from react-icons library useiconand for static image from assets folder useiconImageidwhich could be a string or an array of strings of amenity id/'s to filter out (forclosesttype it should be always a single id)
Model for kiosk can be found here src/models/kiosk.model.tsx.
export interface KioskModel {
name: string;
latitude?: number;
longitude?: number;
level?: number;
zoom?: number;
pitch?: number;
bearing?: number;
bounds?: [[number, number], [number, number]];
poiId?: string;
}Important property here is the name, we are calling it via url params when then map should be initated like kiosk, e.g. http://localhost:6001?kiosk=kioskName
There are two options how to define kiosk location
- Using
latitude, longitude, levelproperties - Or you can omit them and use
poiId, id of existing map feature
Then you can define also default zoom, pitch and bearing. If you want to limit the bounding box you can use bounds property.
In demo we have handleUrlParams enabled as default, so you can pass some url params into browser url to load map with predefined route generated for example. We can just serve them like this:
http://localhost:6001?defaultPlace=placeIdOrTitle&startFeature=featureIdOrTitle&destinationFeature=featureIdOrTitle
or with kiosk behavior
http://localhost:6001?kiosk=MyKiosk&destinationFeature=featureIdOrTitle