For one time setup instructions see setup for macOS
For everyday use see work on macOS
Use the version in .nvmrc. Install Node.js directly, or use nvm and run nvm use in the repo root.
- Clone this repository and
cdinto it. - Install or select Node.js per Prerequisites.
- Run
nvm useto switch to the latest compatible version of node. - Run
npm ci. If package.json is missing runnpm installinstead. The ci command needs a package.json to work. - Following PDS/SA practices, create buckets: one for the built app (upload
disthere after the build) and one or more for data behind CloudFront origins.
-
Create a bucket that will store the built app (upload
disthere after the build). -
Create CloudFront Origin Server that references the bucket in the previous step noting that:
- Origin Access — Select "Origin access control settings (recommended)"
- Create (or reuse) an "Origin access control" that matches the settings below and reference it:
- Name: Name this OAC appropriately
- Description: Describe this OAC appropriately
- Signing Behavior: "Sign requests (recommended)" (Is labeled as "Always sign requests" when viewing an existing OAC)
- Origin Type: "S3"
- Bucket Policy — "No, I will update the bucket policy"
- Enable Origin Sheild — No
-
Update the bucket policy for the bucket created in step 1, substituting
<CLOUDFRONT_DISTRIBUTION_ARN>and<APP_BUCKET_NAME>with your CloudFront Distribution ARN and S3 Browser App bucket name respectively:{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "1", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<APP_BUCKET_NAME>/*", "Condition": { "StringEquals": { "AWS:SourceArn": "<CLOUDFRONT_DISTRIBUTION_ARN>" } } } ] } -
Add a CloudFront behavior that uses the newly created origin server that references the bucket:
-
Path Pattern: Choose a name that will be used to access the app via CloudFront. For example, if we want the path the user uses to access the app to be "data-browser", the path pattern would be
/data-browser* -
Origin and origin groups: Select the bucket created in step 1
-
Compress objects automatically: Yes
-
Viewer protocol policy: "HTTPS Only"
-
Allowed HTTP methods: "GET, HEAD, OPTIONS"
-
Restrict viewer access: No
-
Cache key and origin requests: "Cache policy and origin request policy (recommended)"
-
Cache policy: CachingDisabled
-
Origin request policy: "AllViewerExceptHostHeader"
-
Response Headers Policy: "SimpleCORS"
-
Create a CloudFront Function and assign it to the "viewer request" function association. The function should rewrite paths so that the user is redirected to the app's
index.htmlfile that is uploaded to the bucket. Note the<PATH_PATTERN>used in the function that needs to be updated to match the path pattern you chose in step 1, the trailing/is needed here:Development Runtime: cloudfront-js-2.0
function handler(event) { var request = event.request; request.uri = request.uri.replace(/^\/<PATH_PATTERN>/, '') || '/'; if (request.uri.endsWith('/')) { request.uri += 'index.html' } return request; }
-
-
Create or reuse a bucket that will store the data that the s3 browser will allow users to browse. This bucket can be in the EN venue account or in a Node's Venue account.
-
Create CloudFront Origin Server that references the bucket in the previous step noting that:
- Note:: if referencing a bucket that is in another AWS account, be sure to use the fully qualified domain URL in the
origin domainfield. - Origin Access — Select "Origin access control settings (recommended)"
- Create (or reuse) an "Origin access control" that matches the settings below and reference it:
- Name: Name this OAC appropriately
- Description: Describe this OAC appropriately
- Signing Behavior: "Sign requests (recommended)" (Is labeled as "Always sign requests" when viewing an existing OAC)
- Origin Type: "S3"
- Bucket Policy — "No, I will update the bucket policy"
- Enable Origin Sheild — No
- Note:: if referencing a bucket that is in another AWS account, be sure to use the fully qualified domain URL in the
-
Update the bucket policy for the bucket created in step 1, substituting
<CLOUDFRONT_DISTRIBUTION_ARN>and<DATA_BUCKET_NAME>with your CloudFront Distribution ID and bucket name respectively:Note: If thie bucket is in a separate account, the CloudFront ARN still needs to reference the EN CloudFront distribution that will be accessing it.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowCloudFrontGetObject", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<DATA_BUCKET_NAME>/*", "Condition": { "StringEquals": { "AWS:SourceArn": "<CLOUDFRONT_DISTRIBUTION_ARN>" } } }, { "Sid": "AllowCloudFrontListBucket", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::<DATA_BUCKET_NAME>", "Condition": { "StringEquals": { "AWS:SourceArn": "<CLOUDFRONT_DISTRIBUTION_ARN>" } } } ] } -
Add a CloudFront behavior that uses the newly created origin server that references the bucket:
-
Path Pattern: Choose a name that will be displayed in s3-browser. For example, if we called the data folder "peer-review-data", the path pattern would be
peer-review-data/* -
Origin and origin groups: Select the bucket created in step 1
-
Compress objects automatically: Yes
-
Viewer protocol policy: "HTTPS only"
-
Allowed HTTP methods: "GET, HEAD, OPTIONS"
-
Restrict viewer access: No
-
Cache key and origin requests: "Cache policy and origin request policy (recommended)"
-
Cache policy: CachingDisabled
-
Origin request policy: "AllViewerExceptHostHeader"
-
Response Headers Policy: "SimpleCORS"
-
Create a CloudFront Function and assign it to the "viewer request" function association. The function should rewrite paths to the data in the bucket. Note the
<PATH_PATTERN>used in the function that needs to be updated to match the path pattern you chose in step 1, the trailing/is needed here:Development Runtime: cloudfront-js-2.0
function handler(event) { var request = event.request; if (request.method === 'OPTIONS') { return { statusCode: 204, statusDescription: 'No Content', headers: { 'access-control-allow-origin': { value: '*' }, 'access-control-allow-methods': { value: 'GET, HEAD, OPTIONS' }, 'access-control-allow-headers': { value: '*' }, 'access-control-max-age': { value: '86400' } } }; } request.uri = request.uri.replace(/^\/<PATH_PATTERN>/, '') || '/'; return request; }
-
-
In
webpack.config.js, findnew webpack.EnvironmentPluginand setPUBLIC_PATHto the path where the app will be hosted (default/data/). -
Edit
./src/js/bucketEndpoints.js:
bucketEndpoints: Each object key is the bucket label in the UI (bucket list and links). Each value needsURL(origin base for listing requests—typically your CloudFront hostname, e.g.https://d1234567890abc.cloudfront.net, or an S3 REST endpoint).listingUrlPathPrefix(for CloudFront path-style /appendPathToUrlnotfalse): Path segment matched by your distribution behavior, used in listing URLs and at the start of hash routes (prefer a trailing/). Omit for direct virtual-hosted bucket access (appendPathToUrl: false); usedeepLinkPathalone for the hash and S3 prefix root in that case.deepLinkPath(optional): Path under the listing base without repeatinglistingUrlPathPrefix. With path-style listing, it becomes the S3prefixat browse root. WithappendPathToUrl: falseand nolistingUrlPathPrefix, it is the sole browse hash root and ListBucket prefix. SeegetMissionBrowsePathinbucketEndpoints.js.appendPathToUrl(optional on each bucketEndpoint): Defaults totrue. Whentrue, the app requests listings atURLwithlistingUrlPathPrefixin the path (typical CloudFront behavior URL). Whenfalse, the app usesURLas-is and sends the full browse path (getMissionBrowsePath: optionallistingUrlPathPrefix+ optionaldeepLinkPath, plus subfolders) via theprefixquery parameter (virtual-hosted S3).exclude_prefixes: Prefix strings to omit from file rows in directory listings (seebucketEndpoints.jsfor the export used by the listing code).
- Run
npm run buildand uploaddist/to the app bucket.
Note: Prefer npm ci for installs from a locked tree. Use npm install only when you intend to change dependency versions in package.json.
- Clone this repository and
cdinto it. - Run
nvm use. - Run
npm ciornpm installif the package.json file is missing. - Edit dev server port in webpack.config.js to an available port on your localhost. Under plugins -> devServer ->
port: 9002. - Run
npm run start. - Open a browser and go to
localhost:9002orlocalhost:<port>.