Website for PaCE - an intelligence technology company focused on forecasting geopolitical conflict, civil unrest, and political instability using machine learning and dynamic exposure modeling.
- Node.js (version 18 or higher) - Download here
- npm (comes with Node.js)
- Git (for version control)
npm installnpm run devOpen http://localhost:3000 to view the site in your browser.
npm run buildThis creates an optimized production build in the out/ directory.
Fast local build (skip data prebuild):
# Option A (Mac/Linux):
SKIP_PREBUILD=1 npm run build
# Option B:
npm run build:fastDuring the build, data steps run automatically:
- Sync latest national forecast CSVs from GitHub and snapshot them
- Generate PRIOβGRID GeoJSON (
public/data/grid/{period}.geo.json) from the live grid CSV - Generate monthly point JSONs (
public/data/grid/{period}-m{1..6}.json) for fast grid rendering
Common one-liners youβll likely use.
Development
npm install
npm run devBuild/Export
npm run buildGrid data utilities
# Build centroids from the PRIO-GRID shapefile (one-time / when shapefile changes)
npm run grid:centroids
# Build polygon GeoJSON from the live grid CSV
npm run grid:build
# Build monthly point JSONs from the polygon GeoJSON (used by the map for speed)
node scripts/geojson-to-month-points.js --period 2025-10Scenario utilities (local testing)
# Convert sce_dictionary.pkl to JSON (requires Python 3)
node scripts/convert-scenarios-pkl.js --src /path/to/sce_dictionary.pkl --out public/data/scenarios.jsonThen run the site and click a country on the forecasts page to see the scenario plot.
CI monthly refresh
-
The workflow
.github/workflows/update-minmax.ymldownloadssce_dictionary.pkl(defaults toThomasSchinca/Pace-map-risk@main) and converts it topublic/data/scenarios.jsoneach month, then rebuildspublic/data/minmax.jsonandpublic/data/scenarios.denorm.json. -
Configure via repository variables:
SCE_REPO(owner/repo),SCE_BRANCH(branch),SCE_PATH(path to pickle). Defaults areThomasSchinca/Pace-map-risk,main, andsce_dictionary.pkl. -
The workflow
.github/workflows/update-matches.ymldownloads the DTW matches pickle monthly and converts it topublic/data/matches.jsonfor country pages.- Configure via repository variables:
MATCHES_REPO(owner/repo),MATCHES_BRANCH(branch),MATCHES_PATH(path to pickle in repo). Defaults areThomasSchinca/Pace-map-risk,main, andmatches.pkl. - The pickle is expected to map
country_name -> [Series, distance, Series, distance, ...]. The converter normalizes tocountry_name -> [{ series: { values: [...], index?: [...] }, distance: <number> }, ...]. - Optional: provide a full historical monthly CSV to enable matched-future overlays by setting:
MATCHES_HIST_REPO(owner/repo)MATCHES_HIST_BRANCH(branch)MATCHES_HIST_PATH(path in repo) The workflow will download it topublic/data/hist_full.csv. The UI will prefer this file and fall back topublic/data/hist.csvif absent.
- If you already have a long-run monthly CSV named
Conf.csv(as in Pace-map-risk), you can pointMATCHES_HIST_PATHtoConf.csv. The UI will also look forpublic/data/conf.csvand prefer it when present.
- Configure via repository variables:
CI automation (GitHub Actions)
.github/workflows/sync-forecasts.ymlruns onmainpushes and monthly schedule:- Syncs forecast CSVs, rebuilds centroids, builds GeoJSON, builds monthly points, exports static API
- Commits generated files under
content/forecasts,public/data/csv,public/data/grid, andpublic/api
.github/workflows/update-minmax.ymlruns monthly:- Downloads
sce_dictionary.pkl, converts topublic/data/scenarios.json, computespublic/data/minmax.json, denormalizes topublic/data/scenarios.denorm.json
- Downloads
Forecast CSV sync (from GitHub)
Monthly (latest only, public repo β no token):
npm run csv:sync:github -- --repo ThomasSchinca/Pace-map-risk --dir Historical_Predictions --branch main --latestOnly --saveCsvAll periods (one-time backfill):
npm run csv:sync:github -- --repo ThomasSchinca/Pace-map-risk --dir Historical_Predictions --branch main --saveCsvOptionally use a token to avoid API rate limits:
npm run csv:sync:github -- --repo ThomasSchinca/Pace-map-risk --dir Historical_Predictions --branch main --latestOnly --saveCsv --token $GITHUB_TOKENRaw CSV downloads (from the site)
curl -L http://localhost:3000/api/v1/forecasts/raw/latest -o latest.csv
curl -L http://localhost:3000/api/v1/forecasts/raw/2025-11 -o 2025-11.csvGenerated CSV (from JSON snapshot)
curl -L http://localhost:3000/api/v1/forecasts/csv/latest -o forecasts-latest.csv
curl -L http://localhost:3000/api/v1/forecasts/csv/2025-11 -o forecasts-2025-11.csvConvert a local CSV into a snapshot
node scripts/csv-to-snapshot.js --csv content/forecasts/2025-12.csv --period 2025-12 \
--generatedAt 2025-12-01T00:00:00Z --version 1.0 \
--releaseNote "Calibration v3.3" --releaseNote "Added macro inputs"pace-website/
βββ app/ # Next.js App Router pages
β βββ about/ # About page
β βββ contact/ # Contact page
β βββ dashboard/ # Dashboard placeholder
β βββ technology/ # Technology overview
β βββ use-cases/ # Use cases and client sectors
β βββ globals.css # Global styles with Tailwind
β βββ layout.tsx # Root layout with navigation
β βββ page.tsx # Homepage
βββ components/ # Reusable React components
β βββ Navigation.tsx # Main navigation header
β βββ Footer.tsx # Site footer
βββ content/ # Content management (JSON files)
β βββ company.json # Company information
β βββ services.json # Services and capabilities
β βββ use-cases.json # Use case data
βββ public/ # Static assets
βββ README.md # This file
All website content is stored in JSON files in the /content/ directory for easy editing:
- Company name, tagline, mission
- Value propositions
- Contact information
- Core capabilities
- Product descriptions
- Features and use cases
- Target sectors
- Client examples
- Use case scenarios
- Edit
/content/use-cases.json - Add a new sector object with:
{ "name": "New Sector", "useCase": "Primary use case description", "description": "Detailed description", "icon": "IconName" }
The site uses Tailwind CSS for styling:
- Global styles:
/app/globals.css - Component classes:
.btn-primary,.btn-secondary,.section-heading - Colors:
clairient-blue,clairient-light,clairient-dark(brand colors)
- Create a new directory in
/app/ - Add a
page.tsxfile with your React component - Update navigation in
/components/Navigation.tsx
This repo is configured for static export and automatic deployment to GitHub Pages.
- Enable GitHub Pages in your repository settings (Pages β Build and deployment β Source: GitHub Actions)
- Push to
main. The workflow.github/workflows/deploy-pages.ymlwill:- Build the site (including data prebuild steps)
- Export static files to
out/ - Publish to GitHub Pages
Your site will be available at https://<user>.github.io/<repo>/.
You can deploy to Vercel by connecting the repo in the Vercel dashboard or by adding a custom workflow. This repo is optimized for GitHub Pages by default.
- Build the project:
npm run build - Drag the
out/folder to Netlify Drop
Create a .env.local file for local development:
# Add any environment variables here
# NEXT_PUBLIC_API_URL=https://api.pace.com
To use a custom domain:
- Add
CNAMEfile to/public/with your domain - Configure DNS settings with your domain provider
- Update Vercel domain settings (if using Vercel) or add a CNAME for GitHub Pages
The site is prepared for future API integration:
- Create
/app/api/directory - Add API route files (e.g.,
/app/api/forecasts/route.ts)
The dashboard page (/app/dashboard/page.tsx) is ready for:
- Real-time data fetching
- Interactive charts
- User authentication
- API endpoints
// In a component
const [forecasts, setForecasts] = useState([])
useEffect(() => {
fetch('/api/forecasts')
.then(res => res.json())
.then(data => setForecasts(data))
}, [])If your forecasts are stored as CSV files in a GitHub repository (one file per period, named like YYYY-MM.csv), you can sync them into content/forecasts/ as JSON snapshots used by the Forecasts pages.
- Oneβtime or adβhoc sync
npm run csv:sync:github -- \\
--repo your-org/your-repo \\
--dir path/to/csvs \\
--branch main \\
--token $GITHUB_TOKEN # optional, recommended to avoid rate limitsOptions:
--latestOnlyto fetch only the newest period.- You can also set env vars instead:
GITHUB_REPO,GITHUB_DIR,GITHUB_BRANCH,GITHUB_TOKEN.
The script converts matching *.csv files (deriving YYYY-MM from the filename) into content/forecasts/YYYY-MM.json and updates content/forecasts/latest.json. The Forecasts pages and API read from these JSON snapshots automatically.
Keep original CSVs (to allow raw downloads):
npm run csv:sync:github -- --repo your-org/your-repo --dir path/to/csvs --branch main --saveCsvWhen --saveCsv is used, raw files are stored under content/forecasts/csv/ and you can expose them via:
/api/v1/forecasts/raw/latest.csv/api/v1/forecasts/raw/<YYYY-MM>.csv
- Use in CI before build
npm ci
npm run csv:sync:github -- --repo your-org/your-repo --dir path/to/csvs --branch main --latestOnly --saveCsv --token $GITHUB_TOKEN
npm run buildCSV schema is documented at scripts/csv-to-snapshot.js.
The site is fully responsive and optimized for:
- Mobile phones (320px+)
- Tablets (768px+)
- Desktops (1024px+)
Run the development server and test:
- Navigation works on all screen sizes
- Forms submit properly (currently shows success message)
- All links are functional
- Images load correctly
The site is optimized for:
- Core Web Vitals compliance
- Fast loading with Next.js static generation
- SEO with proper meta tags
- Accessibility with semantic HTML
- Build fails: Check Node.js version (18+)
- Styles not loading: Ensure Tailwind CSS is configured
- Images not showing: Check file paths in
/public/
- Check Next.js documentation
- Visit Tailwind CSS docs
- Review Vercel deployment guide
- Keep headlines clear and concise
- Use active voice for better engagement
- Include specific metrics and benefits
- Maintain consistent tone throughout
- Update page titles and descriptions in layout files
- Add alt text for images
- Use proper heading hierarchy (h1, h2, h3)
- Include relevant keywords naturally
- No sensitive data is stored in the repository
- Contact form is client-side only (replace with backend)
- All external links should be verified
- Regular dependency updates recommended
This project is proprietary to Luscint. All rights reserved.
Need help? Contact the development team or refer to the documentation links above.
Last updated: July 2025