Choose Native Plants helps US residents find native plants for their gardens and locate nearby nurseries that sell them.
- Searches and filters plants by growing conditions and ecological value
- Shows plant details, native range, and local availability
- Includes a garden planner and favorites
- Supports desktop and mobile browsers
The app uses Vue 3, Node.js/Express, and MongoDB. Plant data originates in shared Google Sheets, images live in Linode Object Storage, and nursery availability comes from Plant Agents.
- Node.js 20 LTS (the version used by the Docker image)
- MongoDB Community Server, running locally
- MongoDB Database Tools (
mongorestore) - AWS CLI, needed only to restore a database backup
- Access to the project's shared environment values
mongosh is useful for inspecting the database but is not required to run the app.
On Windows, these can be installed with:
winget install OpenJS.NodeJS.LTS
winget install MongoDB.Server
winget install MongoDB.DatabaseTools
winget install Amazon.AWSCLIAfter installing, open a new terminal so node, mongorestore, and aws are available on PATH.
git clone https://github.com/CodeForPhilly/pa-wildflower-selector
cd pa-wildflower-selector
npm ci
cp .env.example .envAsk in the Code for Philly #choose-native-plants-pa Slack channel for the private values, then edit .env for native local development:
DB_HOST=localhost
DB_PORT=27017
DB_NAME=pa-wildflower-selector
PORT=8080If your local MongoDB does not use authentication, leave MONGODB_USER and MONGODB_PASSWORD blank. Keep all real credentials in .env; it is ignored by Git.
Download the image library:
npm run sync-imagesThis command uses the project's AWS SDK and does not require the AWS CLI. It downloads into the ignored images/ directory and safely skips files that are already current.
Restore the latest shared database backup:
npm run sync:down:dbDatabase restore requires both aws and mongorestore to be available on PATH. MongoDB does not support every cross-version dump/restore combination; use a server version compatible with the backup when mongorestore reports a version warning.
Check the setup and start both servers:
npm run dev:localOpen http://localhost:8080. The Vue development server runs on port 8080 and proxies API and image requests to Express on port 3000.
The first backend start may take a few minutes while missing plant embeddings are generated. Later starts should be quick.
Docker remains available for a containerized environment:
cp .env.example .env
# Set DB_HOST=mongodb and add the private values.
npm run docker:upOpen http://localhost:6868, or the value configured by NODE_LOCAL_PORT.
npm run docker:downThe Compose stack pins MongoDB 5.0.6. Local development is often more convenient when working directly with sync and database tools.
| Command | Purpose |
|---|---|
npm run dev:local |
Validate local setup and run client + server |
npm run dev:client |
Run only the Vue client |
npm run dev:server |
Run only Express on port 3000 |
npm run sync-images |
Download Linode images |
npm run sync:down:db |
Download and restore the latest database backup |
npm run sync:plantagents -- --dry-run |
Validate PlantAgents Neon data without publishing |
npm run sync:plantagents |
Publish PlantAgents vendors, availability, and ZIP data to MongoDB |
npm run fast-update-data |
Refresh plant data from the source sheets |
npm run lint |
Run lint checks |
npm run build |
Build SSR and browser bundles |
npm run docker:up |
Build and start the Compose stack |
npm run docker:down |
Stop the Compose stack |
Run npm run to see the complete script list, including schema, index, embedding, and upload utilities.
| Setting | Native local | Docker |
|---|---|---|
DB_HOST |
localhost |
mongodb |
DB_PORT |
27017 |
27017 |
| Browser URL | http://localhost:8080 |
http://localhost:6868 |
| Express port | 3000 |
Value of PORT |
| MongoDB host port | 27017 |
Value of MONGODB_LOCAL_PORT |
Never commit .env, downloaded images, database backups, or node_modules. They are already covered by .gitignore.
Choose Native Plants serves local and online nursery availability and location lookups from MongoDB. Online stores are vendors classified as mail_order in PlantAgents; links use the current offering's product page or plant profile when available and fall back to the vendor website. The sync job is the only component that connects to PlantAgents PostgreSQL; normal web requests never contact Neon, the legacy PlantAgents API, or the former vendor Google Sheets.
Set PLANTAGENTS_DATABASE_URL in .env to a Neon role with read-only access to vendors, plants, vendor_current_plant_offerings, and zip_code_geographies. Validate and publish with:
Create the Neon role as an administrator, substitute a generated password, and keep the password out of source control:
CREATE ROLE choose_native_plants_sync LOGIN PASSWORD '<generated-password>';
GRANT CONNECT ON DATABASE neondb TO choose_native_plants_sync;
GRANT USAGE ON SCHEMA public TO choose_native_plants_sync;
GRANT SELECT ON TABLE public.vendors,
public.plants,
public.vendor_current_plant_offerings,
public.zip_code_geographies
TO choose_native_plants_sync;Do not grant membership in the crawler role or write privileges. If the PlantAgents views are recreated by a migration, reapply their SELECT grants as part of that migration.
npm run sync:plantagents -- --dry-run
npm run sync:plantagentsThe command stages a complete snapshot, validates counts and plant-name matches, then atomically selects it as active. Neon currently provides ZIP centroids but not city/state labels, so the sync fills missing labels from the bundled BSD-licensed zipcodes dataset and records that provenance on each MongoDB row. More than a 20% source-count drop or a high unmatched-plant ratio fails without changing live data. Use --force only after reviewing an intentional upstream change. The previous successful snapshot is retained for rollback; restore it by updating the plantagents-active document's activeSnapshotId in plantagents_sync_state.
The final output line is JSON suitable for job logs. /api/v1/plantagents-sync-status reports freshness and counts without exposing credentials.
In Kubernetes, create a plantagents-postgres SealedSecret containing PLANTAGENTS_DATABASE_URL, run the CronJob once manually, then set plantagentsSync.enabled: true. The default 0 7 * * 0 schedule is Sunday 07:00 UTC (3:00 AM EDT / 2:00 AM EST). Rotate the credential by resealing that secret; no application configuration changes are required.
- Confirm the MongoDB service is running.
- Confirm
DB_HOST=localhostandDB_PORTmatches the local service. - If authentication is disabled locally, clear
MONGODB_USERandMONGODB_PASSWORD. - Run
node scripts/check-mongodb.jsfor a focused connection check.
- Confirm Express is listening on port 3000.
- Confirm the database has been restored with
npm run sync:down:db. - Do not give the local client and server the same port.
- Use
npm run dev:local; its scripts reserve 8080 for Vue and 3000 for Express. - If the browser shows the app shell but plant requests return 500s, check MongoDB first. A common cause is leaving Docker defaults in
.env, especiallyDB_HOST=mongodbor non-empty Mongo credentials when the local service has no authentication.
- Image sync needs Node.js and the
.envLinode values. - Database sync additionally needs AWS CLI and MongoDB Database Tools on
PATH. - Restart the terminal after installing Windows packages so its
PATHrefreshes.
The first local backend start may generate missing plant embeddings after the database restore. Wait for the server log to finish that work and print Listening on port 3000; later starts should be much faster.
src/— Vue applicationapp.js,lib/— Express server and database accessscripts/— sync, migration, indexing, embedding, and maintenance toolspublic/— static assets bundled with the appimages/— downloaded plant images; ignored by Githelm-chart/,deployment/— deployment configuration
The development-only studio image pipeline is documented in scripts/studio_images/README.md.
- Create a feature branch.
- Make and verify a focused change.
- Commit and push the branch.
- Open a pull request.
Questions are welcome in the Code for Philly project channel or at contact@choosenativeplants.com.
This project is licensed under the MIT License.
