Skip to content

performant-software/core-data-places

Repository files navigation

core-data-places

A map-centric website backed by a Core Data project and Typesense index.

Getting Started

Requirements

  • Node 20.x
  • Netlify CLI
  • Core Data Project
  • Typesense Index

Environment variables

Copy the .env.example file to .env and enter required variables. For a local development setup, set TINA_PUBLIC_IS_LOCAL to "true" and TINA_LOCAL_CONTENT_PATH to "../"

Configuration

Add a /public/config.dev.json file, which will be ignored by Git, to copy local config settings when starting the application. Use the config.json table below to configure your project.

To start, run:

npm install && netlify dev

Note: Do not commit any project specific changes to /public/config.json in this repository.

Note: Changes to config.json will require a re-build of the site.

Deploy to Production

Create a content repository

On GitHub, create a new content repository. The posts, paths, and pages records you create will be stored here, as well as any i18n, your project configuration, and default user accounts.

Directory Structure

Create a directory structure in the content repository as follows. The actual files are just examples, we'll go over adding required files in the next sections.

content
├── branding
│   ├── branding.json
├── i18n
│   ├── en.json
├── pages
│   ├── Home.mdx
├── paths
│   ├── MyPath.mdx
│   ├── AnotherPath.mdx
├── posts
│   ├── FirstPost.mdx
│   ├── SecondPost.mdx
├── settings
│   ├── config.json
├── users
│   ├── index.json
Users

Copy the /data/users.json file into your content repository to /content/users/index.json. This will seed TinaCMS with the initial set of user accounts, which can be used to setup accounts for other users, then removed. Skip this step if you are using an SSO provider or institutional IdP to manage users instead.

Branding

Create the following /content/branding/branding.json file:

{
  "title": "My Awesome Project",
  "footer": {
    "allow_login": true
  }
}

The title attribute will be set as the <title> element of the HTML page. Setting footer.allow_login to true will add Core Data and TinaCMS login buttons to the content footer. Additional branding options can be configured via TinaCMS.

Configuration

Copy the /public/config.json file into your content repository to /content/settings/config.json and adjust the configuration as desired.

Key Type Description
content Object TinaCMS content collections configuration
content.collections Array Array of content keys to allow for data entry and routing: "posts", "paths"
content.localize_pages Boolean If true pages content will be pulled from a locale directory (e.g. /en/My-Awesome-Page.mdx)
core_data Object Core Data configuration
core_data.url String URL of the Core Data application
core_data.project_ids Array Array of Core Data project IDs as strings
detail_pages Object Configuration for the detail pages
detail_pages.models Array Array of model names for which to build detail pages (e.g "places", "people", etc)
detail_pages.relationship_fields Object List of fields to display in the related record components for each model type
detail_pages.relationship_fields.events Array List of fields to display in the related record components for related events
detail_pages.relationship_fields.instances Array List of fields to display in the related record components for related instances
detail_pages.relationship_fields.items Array List of fields to display in the related record components for related items
detail_pages.relationship_fields.works Array List of fields to display in the related record components for related works
i18n Object Astro i18n configuration
i18n.default_locale String The default locale
i18n.locales Array A list of all available locales
gallery String Link to the gallery IIIF manifest
layers Array A list of available map layers
layers.name String The name of the map layer to display in the UI
layers.layer_type String Map layer type: "raster", "vector", "geojson" or "georeference"
layers.url String URL to the map server
layers.overlay Boolean If true, map layer will be rendered as overlay layer. If false, map layer will be rendered as base layer
result_filtering Object Lists of fields and relationships to exclude per model.
result_filtering.events.exclude Array List of attributes, user defined fields and associations to be excluded from the search detail panel and detail pages. See Search detail filtering
result_filtering.instances.exclude Array List of attributes, user defined fields and associations to be excluded from the search detail panel and detail pages. See Search detail filtering
result_filtering.items.exclude Array List of attributes, user defined fields and associations to be excluded from the search detail panel and detail pages. See Search detail filtering
result_filtering.organizations.exclude Array List of attributes, user defined fields and associations to be excluded from the search detail panel and detail pages. See Search detail filtering
result_filtering.people.exclude Array List of attributes, user defined fields and associations to be excluded from the search detail panel and detail pages. See Search detail filtering
result_filtering.places.exclude Array List of attributes, user defined fields and associations to be excluded from the search detail panel and detail pages. See Search detail filtering
result_filtering.works.exclude Array List of attributes, user defined fields and associations to be excluded from the search detail panel and detail pages. See Search detail filtering
search Array Search UI configuration
search.facets Array Search facets configuration.
search.facets.icon String Icon to display in the facet header
search.facets.name String Name of the facet field as defined in Typesense
search.facets.type String Search facet type: "list", "range", or "select"
search.geosearch Boolean If true, the "filter by map bounds" facet will be available in the map interface.
search.map Object Map configuration
search.map.cluster_radius Number If provided, map points will be clustered for the given radius (in miles). This option is only valid if the map.geometry property contains Lat/Lng coordinates.
search.map.geometry String Path to the attribute in the Typesense document that contains the GeoJSON data to be displayed on the map
search.map.max_zoom Number The maximum zoom level to allow when the map view transitions to a set of bounds (a single place, or mulitple places).
search.map.zoom_to_place Boolean If true or not specified, clicking on an individual place marker or search result will zoom the map to its location (using the max zoom).
search.name String The name of the search index configuration.
search.result_card Object Search result card configuration
search.result_card.title String Path to the value in the Typesense document that should be used as the card title. This value can contain nested objects (e.g. <relationship-id>.0.name).
search.result_card.attributes Array Attributes to display in the search list and table
search.result_card.attributes.name String Path to the value in the Typesense document that should be used to look up the column value. This value can contain nested objects (e.g. <relationship-id>.0.name).
search.result_card.attributes.icon String Name of the icon that should displayed next to the value in the search list. If not provided, a bullet point will be used.
search.result_card.tags Array Tags to display as pills at the top of each item in the search list
search.result_card.tags.name String Name of the attribute to pull the tag value from
search.result_card.tags.primary Boolean Whether the tag should be shown in the primary site color
search.result_card.tags.secondary Boolean Whether the tag should be shown in the secondary site color
search.route String The navigation route to use when clicking on a search result card (e.g. "/places", "/organizations", etc)
search.table Boolean If false, will suppress the table view for search results
search.timeline Object Timeline configuration
search.timeline.date_range_facet String Path to the date range facet field in the Typesense document that will be used as the basis for the timeline. Required for the timeline to appear.
search.timeline.event_path String Path to the event relation in the Typesense document. Required only if Event is not the primary model of this search index configuration.
search.type String If map, the map search component will be used. If image, list, or grid, the non-map search component will be used with the corresponding layout. Defaults to map when not present.
search.typesense Object Typesense index connection information
search.typesense.host String Typesense host URL
search.typesense.port Number Typesense host port
search.typesense.protocol String Typesense host protocol. Typically "https" or "http"
search.typesense.api_key String Typesense search API key. NOTE: This should be a read-only key.
search.typesense.index_name String Name of the Typesense collection
search.typesense.query_by String Typesense attributes to query when a search is executed
search.typesense.default_sort String Typesense attribute to sort by when no search is entered or as a tiebreaker. Search relevance score will always take priority over this attribute.
search.typesense.exclude_fields String Fields to exclude from the Typesense search response
search.typesense.facets Object Facet configuration
search.typesense.facets.exclude Array Array of facet names to exclude
search.typesense.facets.include Array Array of facet names to include
search.typesense.overrides Object Overrides for the typesense-instantsearch-adapter.

See Configuration Schema for more detailed information.

Create a new Personal Access Token

In your developer settings, create a new personal access token with access to your newly created repository with read/write permissions to code.

Add an IAM user to AWS

If using media uploads, you'll need to create a new IAM user to access the S3 bucket for media storage. All media for TinaCMS content is stored in the core-data-tina-cms bucket and access to sub-folders is given to users. Create a new user with the following inline policy:

{
 "Version":"2012-10-17",
 "Statement": [
   {
     "Sid": "AllowListingOfFolder",
     "Action": ["s3:ListBucket"],
     "Effect": "Allow",
     "Resource": ["arn:aws:s3:::core-data-tina-cms"],
     "Condition":{"StringLike":{"s3:prefix":["<folder-name>/*"]}}
   },
   {
     "Sid": "AllowAllS3ActionsInFolder",
     "Effect": "Allow",
     "Action": ["s3:*"],
     "Resource": ["arn:aws:s3:::core-data-tina-cms/<folder-name>/*"]
   }
 ]
}

Replace <folder-name> with the name of the folder in the S3 bucket where the media should be stored. As a naming convention, the name of the folder should be the same as the name of the GitHub repository created above.

After the user is created, use the "Security Credentials" tab to create an access key/secret for the user.

Deploy to Netlify

Create a new site on Netlify deployed from the core-data-places repository. Set all of the environment variables in .env.example as appropriate. Currently, Core Data Places can only be hosted on Netlify in "server" mode, as the TinaCMS functions are dependent on Netlify functions.

Single Sign On

See Keycloak documentation for single sign on.

Static Build

Core Data Places can be built in "static" mode, which will remove the dependency on an existing Core Data project. See static deploy documentation.

Upgrading

For more information on upgrading your existing Core Data Places site to a newer version, see the update notes section.

Typesense Fields

To find all of the available fields in the Typesense schema, a GET request can be made to the Typesense API:

GET ${TYPESENSE_HOST}/collections/:collection

An x-typesense-api-key header will need to be added to the request.

Core Data Fields and Relationships

To find the UUID values for Core Data user-defined fields and relationships, the "Identifier" column can be added to the respective lists within the Core Data application under Project Settings > Configure.

About

Core Data Places Client

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 6