-
+
|
🛠️ Local Setup
@@ -24,7 +24,7 @@
# Local Development Setup
-Follow this guide to run the CommNG applications locally for development and testing.
+Follow this guide to run the GuardConnect applications locally for development and testing.
## Prerequisites
@@ -38,13 +38,16 @@ Follow this guide to run the CommNG applications locally for development and tes
```bash
git clone
-cd CommNG
+cd GuardConnect # Root Repository
# Backend dependencies
-cd server && npm install
+cd server
+npm install
+# In another terminal - keep both open
# Frontend dependencies
-cd ../web && npm install
+cd web
+npm install
```
## 2. Configure Environment Variables
@@ -52,58 +55,67 @@ cd ../web && npm install
1. Copy the example environment files (update values as needed):
```bash
- cd server
- cp .env.example .env.local
+ # In /server
+ cp .env.example .env
- cd ../web
- cp .env.example .env.local
+ # In /web
+ cp .env.example .env
```
2. Populate the environment files with credentials:
- - PostgreSQL connection string (`DATABASE_URL`)
- - Redis details (`REDIS_HOST`, `REDIS_AUTH`)
- - VAPID keys for push notifications (or temporary placeholders for local tests)
+ - BETTER_AUTH_SECRET
+ - VAPID keys for push notifications (front end too)
+ - TWILIO values for SMS
+
+ _Locations of all values explained in files._
-3. Start Redis (and any other required services) via Docker Compose:
+3. Start Docker:
```bash
- cd ../
+ # In /server directory
docker compose up -d
+
+ # Add PGVector - insert values in [] from server/.env
+ docker exec -it commng-postgres psql -U [POSTGRES_USER] -d [POSTGRES_DB] -c "CREATE EXTENSION IF NOT EXISTS vector;"
```
## 3. Start Development Servers
```bash
-# Terminal 1 - API server
-cd server
+# Terminal 1 - DB and API server in /server
+npx drizzle-kit push # Apply latest migrations
npm run dev
-# Terminal 2 - Next.js web app
-cd web
+# Terminal 2 - Next.js web app in /web
npm run dev
```
- API available at `http://localhost:3000`
- Web UI available at `http://localhost:3001`
-## 4. Database Management
-
-Run these commands from the `server` directory:
+Use Drizzle Studio (shown below) or your preferred SQL client to inspect data.
+## 4. Add roles and users
```bash
-# Apply latest migrations
-npx drizzle-kit push
+# In a new terminal tab
+cd server
+
+# Create roles
+npx tsx --env-file=.env scripts/create-roles.ts
-# Open Drizzle Studio
-npx drizzle-kit studio
+# Create your user
+# Go to server/scripts/create-user.ts and edit the user info (lines 20-35)
+# Then run:
+npx tsx --env-file=.env scripts/create-user.ts
```
+_NOTE: You may need to go back to the other /server terminal and rerun_ ```npm run dev```
-Use Drizzle Studio or your preferred SQL client to inspect data.
+### > You should now be able to go to http://localhost:3001/ and sign in with the user you just created.
## 5. Development Scripts
```bash
-npm run dev # start dev server
+# Frontend and backend
npm run test # run unit tests
npm run lint # lint codebase
npm run format # format code
@@ -111,7 +123,6 @@ npm run lintfix # lint + auto-fix issues
```
### Backend-specific Scripts
-
```bash
npx drizzle-kit push # apply latest migrations
npm run db:studio # open Drizzle Studio UI
@@ -121,20 +132,19 @@ npm run db:studio # open Drizzle Studio UI
```bash
# Reset Docker services
-cd CommNG
+# In root directory
docker compose down -v
-
docker compose up -d
```
Common issues:
-- **Ports already in use**: stop conflicting processes or change ports in `.env.local`.
+- **Ports already in use**: stop conflicting processes or change ports in `.env`.
- **Missing VAPID keys**: generate temporary keys with `npx web-push generate-vapid-keys --json`.
-- **Database connectivity**: ensure PostgreSQL is running and credentials match `.env.local`.
+- **Database connectivity**: ensure PostgreSQL is running and credentials match `.env`.
## 7. Next Steps
-After local setup, proceed with:
+After local setup, proceed with (if not done already):
1. [Secrets configuration](./SECRETS-SETUP.md)
2. [Infrastructure provisioning](./INFRA.md)
3. [Deployment workflows](./QUICK-REFERENCE.md)
diff --git a/docs/SECRETS-SETUP.md b/docs/SECRETS-SETUP.md
index 31f1ede0..ba4853f8 100644
--- a/docs/SECRETS-SETUP.md
+++ b/docs/SECRETS-SETUP.md
@@ -2,7 +2,7 @@
-
+
|
🔐 Secrets Setup
@@ -25,7 +25,7 @@
# Secrets Management Setup Guide
-This guide explains how to set up and manage secrets in AWS Secrets Manager for the CommNG application.
+This guide explains how to set up and manage secrets in AWS Secrets Manager for the GuardConnect application.
## Overview
diff --git a/server/.env.example b/server/.env.example
index 8408bb3f..78502137 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -1,33 +1,28 @@
-POSTGRES_HOST=
-POSTGRES_DB=comm_ng
-POSTGRES_SSL=true
-AWS_REGION="us-east-1"
-DB_SECRET_ID=
+# BASIC VALUES & KEYS
+DEV_ENV=true # Ensures values are pulled from .env in dev
+BACKEND_URL=http://localhost:3000
+PORT=3000
+LOG_LEVEL=debug
+USE_PRESIGNED_UPLOADS=true
DB_SECRET_REFRESH_INTERVAL_MS=30000
-# uncomment if using drizzle studio / if you want to not use secrets manager
-# POSTGRES_USER=comm_ng_dev_user
-# POSTGRES_PASSWORD=
-
-
-# local pg (user either these 3, or the above 6, but not both)
-# POSTGRES_USER=commng-pg-user
-# POSTGRES_PASSWORD=
-# POSTGRES_DB=comm_ng
+BETTER_AUTH_SECRET= # AWS Secrets Manager dev/guardconnect/better-auth-dev
-BETTER_AUTH_SECRET=
-
-S3_BUCKET_NAME=
-AWS_REGION=us-east-1
-USE_PRESIGNED_UPLOADS=true
+# LOCAL POSTGRES
+POSTGRES_USER=commng-pg-user
+POSTGRES_PASSWORD=localpassword
+POSTGRES_DB=comm_ng
-BACKEND_URL=http://localhost:3000
+# AWS
+AWS_REGION="us-east-1"
+S3_BUCKET_NAME=dev-comm-ng-files-6c661e9c
+# Need IAM permissions in group "guardconnect-dev-s3-upload"
+# VAPID - Get from AWS Secrets Manager dev/comm_ng/vapid-keys
VAPID_PUBLIC_KEY=
VAPID_PRIVATE_KEY=
-VAPID_CONTACT_EMAIL=mailto:admin@example.com
-
-PORT=3000
-LOG_LEVEL=debug
+VAPID_CONTACT_EMAIL=
-# add this if you don't have aws signed in, if this varible is not added/is set to true, it assumes aws exists and is enabled
-EMBEDDINGS_ENABLED=false
\ No newline at end of file
+# TWILIO - Get from AWS Secrets Manager prod/guardconnect/twilio
+TWILIO_ACCOUNT_SID=
+TWILIO_AUTH_TOKEN=
+TWILIO_PHONE_NUMBER=
diff --git a/server/package-lock.json b/server/package-lock.json
index 5ea2902d..24f4918d 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -1473,7 +1473,6 @@
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.4.5.tgz",
"integrity": "sha512-dQ3hZOkUJzeBXfVEPTm2LVbzmWwka1nqd9KyWmB2OMlMfjr7IdUeBX4T7qJctF67d7QDhlX95jMoxu6JG0Eucw==",
- "peer": true,
"dependencies": {
"@standard-schema/spec": "^1.0.0",
"zod": "^4.1.12"
@@ -1503,14 +1502,12 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz",
"integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@better-fetch/fetch": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz",
- "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==",
- "peer": true
+ "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA=="
},
"node_modules/@biomejs/biome": {
"version": "2.2.5",
@@ -2176,7 +2173,6 @@
"resolved": "https://registry.npmjs.org/@redis/client/-/client-5.8.3.tgz",
"integrity": "sha512-MZVUE+l7LmMIYlIjubPosruJ9ltSLGFmJqsXApTqPLyHLjsJUSAbAJb/A3N34fEqean4ddiDkdWzNu4ZKPvRUg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"cluster-key-slot": "1.1.2"
},
@@ -3281,7 +3277,6 @@
"https://trpc.io/sponsor"
],
"license": "MIT",
- "peer": true,
"peerDependencies": {
"typescript": ">=5.7.2"
}
@@ -3396,7 +3391,6 @@
"integrity": "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/node": "*",
"pg-protocol": "*",
@@ -3731,7 +3725,6 @@
"resolved": "https://registry.npmjs.org/better-call/-/better-call-1.1.4.tgz",
"integrity": "sha512-NJouLY6IVKv0nDuFoc6FcbKDFzEnmgMNofC9F60Mwx1Ecm7X6/Ecyoe5b+JSVZ42F/0n46/M89gbYP1ZCVv8xQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@better-auth/utils": "^0.3.0",
"@better-fetch/fetch": "^1.1.4",
@@ -4391,7 +4384,6 @@
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz",
"integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==",
"hasInstallScript": true,
- "peer": true,
"bin": {
"esbuild": "bin/esbuild"
},
@@ -4480,7 +4472,6 @@
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.0",
@@ -4936,7 +4927,6 @@
"resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz",
"integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==",
"license": "MIT",
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/panva"
}
@@ -5006,7 +4996,6 @@
"resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.8.tgz",
"integrity": "sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=20.0.0"
}
@@ -5171,7 +5160,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": "^20.0.0 || >=22.0.0"
}
@@ -5322,7 +5310,6 @@
"resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
"integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"pg-connection-string": "^2.9.1",
"pg-pool": "^3.10.1",
@@ -5420,7 +5407,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -6266,7 +6252,6 @@
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz",
"integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "~0.25.0",
"get-tsconfig": "^4.7.5"
@@ -6395,7 +6380,6 @@
"integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@@ -6673,7 +6657,6 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz",
"integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==",
"license": "MIT",
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
diff --git a/server/src/service/twilio-service.ts b/server/src/service/twilio-service.ts
index 3f9913f5..d72b665d 100644
--- a/server/src/service/twilio-service.ts
+++ b/server/src/service/twilio-service.ts
@@ -21,10 +21,18 @@ interface BroadcastResult {
const client = new SecretsManagerClient({ region: "us-east-1" });
async function getTwilioSecrets() {
- const response = await client.send(
- new GetSecretValueCommand({ SecretId: "prod/guardconnect/twilio" }),
- );
- return JSON.parse(response.SecretString!);
+ if (process.env.DEV_ENV === "true") {
+ return {
+ TWILIO_ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
+ TWILIO_AUTH_TOKEN: process.env.TWILIO_AUTH_TOKEN,
+ TWILIO_PHONE_NUMBER: process.env.TWILIO_PHONE_NUMBER,
+ };
+ } else {
+ const response = await client.send(
+ new GetSecretValueCommand({ SecretId: "prod/guardconnect/twilio" }),
+ );
+ return JSON.parse(response.SecretString!);
+ }
}
export class TwilioSMSService {
diff --git a/web/.env.example b/web/.env.example
index 737d2afa..43aca815 100644
--- a/web/.env.example
+++ b/web/.env.example
@@ -1,4 +1,4 @@
-NEXT_PUBLIC_WEB_BASE_URL=
-NEXT_PUBLIC_API_BASE_URL=
-NEXT_PUBLIC_VAPID_PUBLIC_KEY=
+NEXT_PUBLIC_WEB_BASE_URL= # Leave blank
+NEXT_PUBLIC_API_BASE_URL=http://localhost:3000
+NEXT_PUBLIC_VAPID_PUBLIC_KEY= # Get from AWS Secrets Manager dev/comm_ng/vapid-keys
PORT=3001
\ No newline at end of file
| |