Skip to content

rolling-scopes-school/gis-app-aws

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MapPoints β€” Starter Application

This repository contains the starter application for the MapPoints AWS Developer Course.

You will work in this repository throughout all 10 modules, progressively adding AWS services to the same application.


What Is MapPoints?

MapPoints is an interactive map SPA where users can:

  • Browse geographic points of interest on a world map
  • Create new points with a title, description, and coordinates
  • Upload photos to individual points
  • Import multiple points at once from a CSV file
  • Authenticate via AWS Cognito and make protected API calls
  • View AI-generated image labels on uploaded photos (module 10 bonus)

Repository Structure

gis-app-aws/
β”œβ”€β”€ frontend/                        ← React SPA (Vite + TypeScript) β€” complete starter
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ App.tsx                  ← Root component, auth state, feature flag wiring
β”‚   β”‚   β”œβ”€β”€ api/client.ts            ← Typed API client (reads env vars at runtime)
β”‚   β”‚   β”œβ”€β”€ components/              ← UI components (map, forms, upload, import)
β”‚   β”‚   β”œβ”€β”€ config/featureFlags.json ← Active flags for current module
β”‚   β”‚   └── types.ts                 ← Shared TypeScript types
β”‚   β”œβ”€β”€ .env.example                 ← Template for your local environment variables
β”‚   β”œβ”€β”€ index.html
β”‚   └── package.json
β”‚
β”œβ”€β”€ backend_node/                    ← Node.js Lambda handler stubs β€” implement these
β”‚   β”œβ”€β”€ point_service/handlers/
β”‚   β”‚   β”œβ”€β”€ getPointsList.ts         ← GET /points
β”‚   β”‚   β”œβ”€β”€ getPointById.ts          ← GET /points/{pointId}
β”‚   β”‚   └── createPoint.ts           ← POST /points
β”‚   β”œβ”€β”€ import_service/handlers/
β”‚   β”‚   β”œβ”€β”€ getUploadUrl.ts          ← GET /upload?pointId=&fileName=
β”‚   β”‚   β”œβ”€β”€ importPointsFile.ts      ← GET /import?fileName=
β”‚   β”‚   β”œβ”€β”€ processUploadedPhoto.ts  ← S3 trigger on uploads/
β”‚   β”‚   β”œβ”€β”€ importFileParser.ts      ← S3 trigger on uploaded/
β”‚   β”‚   β”œβ”€β”€ catalogBatchProcess.ts   ← SQS trigger
β”‚   β”‚   └── enrichPhoto.ts           ← S3 trigger on uploads/ (module 10)
β”‚   β”œβ”€β”€ authorization_service/handlers/
β”‚   β”‚   β”œβ”€β”€ basicAuthorizer.ts       ← Lambda Authorizer (module 7)
β”‚   β”‚   └── postConfirmation.ts      ← Cognito Post Confirmation trigger (module 8)
β”‚   β”œβ”€β”€ package.json
β”‚   └── tsconfig.json
β”‚
β”œβ”€β”€ module_02_infra_node/            ← CDK starter for module 2 (S3 + CloudFront)
β”‚   β”œβ”€β”€ lib/module-02-hosting-stack.ts
β”‚   β”œβ”€β”€ bin/
β”‚   β”œβ”€β”€ cdk.json
β”‚   └── package.json
β”‚
β”œβ”€β”€ FeatureGuard.tsx                 ← React component: renders fallback when flag is off
β”œβ”€β”€ FeatureFlagsPanel.tsx            ← Dev-only panel for toggling flags in the browser
└── featureFlags.ts                  ← TypeScript type for the FeatureFlags shape

Getting Started

Prerequisites

Tool Version Install
Node.js 20+ https://nodejs.org
AWS CLI v2 latest https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html
AWS CDK 2.x npm install -g aws-cdk
AWS account free tier https://aws.amazon.com/free

Run the frontend locally

cd frontend
npm install
npm run dev

Open http://localhost:5173 β€” the map is visible, all backend-dependent features are shown as disabled placeholders.

Configure your environment variables

cp frontend/.env.example frontend/.env.local

Edit .env.local and fill in values as you deploy each module:

# Module 3+ β€” Points service API Gateway base URL
VITE_POINTS_API_URL=

# Module 5+ β€” Import service API Gateway base URL
VITE_IMPORT_API_URL=

# Module 8-9+ β€” Cognito configuration
VITE_COGNITO_USER_POOL_ID=
VITE_COGNITO_CLIENT_ID=
VITE_COGNITO_DOMAIN=
VITE_COGNITO_REDIRECT_URI=http://localhost:5173

Rules:

  • Leave blank any variable whose backend is not yet deployed β€” the API client skips calls when the URL is empty.
  • For production (deployed to CloudFront) change VITE_COGNITO_REDIRECT_URI to your CloudFront URL.

Bootstrap CDK (once per AWS account/region)

ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
REGION=$(aws configure get region)
npx cdk bootstrap aws://$ACCOUNT/$REGION

Module 2 β€” Deploy the Frontend (CDK starter)

# Build the frontend first
cd frontend
npm install && npm run build

# Deploy S3 bucket + CloudFront distribution
cd ../module_02_infra_node
npm install
npm run cdk:deploy

The stack output contains:

Output Description
CloudFrontUrl Your public HTTPS frontend URL
BucketName S3 bucket name (for reference)

To tear down:

npm run cdk:destroy

Feature Flags

Feature flags control which parts of the UI and API are active. They live in frontend/src/config/featureFlags.json.

Never enable a flag for a feature you have not implemented yet. The API client will make real HTTP calls and get errors if the backend is not deployed.

Flag File Structure

{
  "module": 2,
  "ui": {
    "showMap": true,
    "enableCreatePoint": false,
    "enableUploadPhoto": false,
    "enableCsvImport": false,
    "enableAuthButtons": false,
    "showAiLabels": false
  },
  "api": {
    "enablePointsApi": false,
    "pointsSource": "mock"
  },
  "security": {
    "enableBasicAuthForImport": false,
    "enableCognito": false,
    "requireAuthForCreatePoint": false
  },
  "async": {
    "enableSqsPipeline": false,
    "enableSnsNotifications": false
  },
  "ai": {
    "enableRekognitionLabels": false,
    "enableModeration": false,
    "enableTextDetection": false
  }
}

Flag Progression by Module

Flag Enable in module Description
ui.showMap 2 Renders the Leaflet map
api.enablePointsApi 3 App fetches points from API instead of hardcoded mock
api.pointsSource=mock 3 Lambda returns static mock data
api.pointsSource=dynamodb 4 Lambda reads from DynamoDB
ui.enableCreatePoint 4 "Add Point" form is enabled
ui.enableUploadPhoto 5 "Upload Photo" button is enabled
ui.enableCsvImport 5 "Import CSV" button is enabled
async.enableSqsPipeline 6 CSV import routes through SQS queue
async.enableSnsNotifications 6 Import completion sends SNS email notification
security.enableBasicAuthForImport 7 GET /import requires Authorization: Basic header
security.requireAuthForCreatePoint 8 POST /points requires Cognito id_token
security.enableCognito 9 App uses Cognito for auth (enables token handling)
ui.enableAuthButtons 9 Login / Logout buttons are shown
ai.enableRekognitionLabels 10 App calls Rekognition labels endpoint
ui.showAiLabels 10 AI labels are displayed on point detail

FeatureGuard Component

Use FeatureGuard to gate UI elements declaratively:

import { FeatureGuard } from "../../FeatureGuard";

<FeatureGuard enabled={flags.ui.enableCreatePoint} fallback={<span>Available in module 4</span>}>
  <CreatePointForm onSubmit={handleCreate} />
</FeatureGuard>

When enabled is false, the fallback is rendered. Default fallback: "Available in next modules".


API Gateway URLs

After deploying each module, save the URL and put it in your .env.local.

Points API (VITE_POINTS_API_URL)

Endpoint Method Module Description
/points GET 3 List all points
/points/{pointId} GET 3 Get single point (includes aiLabels in module 10)
/points POST 4 Create a new point (protected by Cognito in module 8)

Import API (VITE_IMPORT_API_URL)

Endpoint Method Module Description
/upload GET 5 Get S3 presigned PUT URL for photo (?pointId=&fileName=)
/import GET 5 Get S3 presigned PUT URL for CSV (?fileName=) β€” protected by Basic Auth in module 7

API Response Shapes

GET /points

[
  {
    "id": "uuid",
    "title": "Eiffel Tower",
    "description": "Iconic iron lattice tower",
    "latitude": 48.8584,
    "longitude": 2.2945,
    "photoUrl": "https://...",
    "createdAt": "2025-01-15T10:00:00Z",
    "tags": ["landmark"],
    "aiLabels": [{ "name": "Tower", "confidence": 99.5 }]
  }
]

POST /points request body

{
  "title": "string (required)",
  "description": "string",
  "latitude": 48.8584,
  "longitude": 2.2945
}

GET /upload response

{ "url": "https://s3.amazonaws.com/..." }

Cognito Configuration (Modules 8-9)

After deploying the Cognito stack in module 8, get the outputs:

aws cloudformation describe-stacks --stack-name <your-stack-name> \
  --query 'Stacks[0].Outputs'
Stack Output .env.local variable
UserPoolId VITE_COGNITO_USER_POOL_ID
UserPoolClientId VITE_COGNITO_CLIENT_ID
UserPoolDomain VITE_COGNITO_DOMAIN
CloudFront URL (module 2) VITE_COGNITO_REDIRECT_URI

The app uses the Authorization Code Grant flow:

  1. Login button β†’ redirects to Cognito Hosted UI
  2. After login β†’ Cognito redirects back with ?code=...
  3. App exchanges the code for id_token + access_token at /oauth2/token
  4. Tokens stored in localStorage
  5. id_token sent as Authorization header on POST /points

Authorization (Module 7)

Module 7 protects GET /import with a Lambda Authorizer using HTTP Basic Auth.

The lambda reads a {github_login}=TEST_PASSWORD environment variable. The frontend sends:

Authorization: Basic base64({github_login}:TEST_PASSWORD)

Set the token in the browser before testing the CSV import:

localStorage.setItem("authorization_token", btoa("<your_github_login>:TEST_PASSWORD"));

The app reads this value from localStorage automatically when security.enableBasicAuthForImport=true.


Backend Handler Stubs

All Lambda handlers are in backend_node/. Each file has a TODO comment describing what to implement. Wire each handler to API Gateway routes or S3/SQS event sources in your own CDK stacks (starting from module 3).

Do not modify module_02_infra_node/ β€” it is a complete working CDK stack for the hosting layer.


Useful Commands

# Start frontend dev server
cd frontend && npm run dev

# Build frontend for deployment
cd frontend && npm run build

# Deploy module 2 (S3 + CloudFront)
cd module_02_infra_node && npm run cdk:deploy

# Destroy module 2 stack
cd module_02_infra_node && npm run cdk:destroy

# Check AWS credentials
aws sts get-caller-identity

# Preview CDK changes before deploying
npx cdk diff

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages