CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a multilingual Jekyll website for Mirigi, a digital concierge service for condominiums. The site showcases features and customer testimonials in English, Spanish, and French. It’s built using Jekyll with a Bootstrap-based theme and Docker deployment.

Development Commands

Primary Development Workflow

# Build and serve using Docker (recommended)
docker build -t mirigi-jekyll-site .
docker run -v $(pwd):/usr/src/app -p 4000:4000 mirigi-jekyll-site

# Or use the Makefile (requires docker image to be built first)
make serve

# For frontend asset development (SCSS/JS changes)
npm install
npm run start        # Runs gulp watch with BrowserSync on port 3000

Build Commands

make all            # Build frontend assets using gulp (runs npm install if needed)
gulp build          # Build CSS/JS assets and copy vendor dependencies
gulp css            # Compile SCSS only
gulp vendor         # Copy node_modules dependencies to /vendor/

Architecture & Structure

Multilingual Setup

Key Directories

Layout Hierarchy

Content Management

Features and customers are Jekyll collections. Each content piece requires this frontmatter:

---
title: "Feature Name"
image: "/img_mirigi/feature-image.jpg"
layout: feature  # or "customer"
description: "Short description for SEO"
keywords: keyword1, keyword2, keyword3
image_credits: '@<a href="url">author</a>'  # optional
---

The lang and permalink are auto-set by _config.yml defaults based on file path.

Frontend Build Process

Multilingual Content Pattern

When adding content, create the same file (same filename) in all three language directories:

Brochure System

brochure.html is a static, print-optimized marketing brochure (US Letter, 8.5”×11”). Styled by scss/_brochure.scss with luxury typography (Playfair Display, Montserrat) and a dark charcoal/pearl/gold palette.

Key SCSS variables:

$print-page-height: 11in
$print-page-width: 8.5in
$print-margin: 0.5in
$brochure-dark-bg: #58595b
$brochure-light-bg: #f5f5f5

Key CSS classes:

The same CSS framework and components (_includes/brochure_feature.html, _includes/brochure_customer.html) are reused in proposal.html for dynamic proposals.

Proposal System

The site includes a sales proposal generator system that allows salespeople to create customized PDF proposals for buildings.

JS Module Roles

Proposal Output Sections (proposal.html)

Decrypts ?d= URL parameter and dynamically renders:

  1. Cover (building name, tagline, salesperson, date)
  2. About Mirigi
  3. Highlighted features (2/page, alternating left-right layout)
  4. Compact features grid (non-highlighted features)
  5. Pricing (platform + one-time services)
  6. Terms (timeline, notes, valid-until)
  7. Customers grid
  8. Next Steps / Contact

Authentication & Encryption Method

The proposal system uses a key-based authentication with encrypted URL parameters:

Authentication Flow:
1. User enters symmetric key (only the user knows it - NOT stored in code)
2. localStoredKey = HMAC-SHA256(symmetricKey, SALT)
3. accessHash = HMAC-SHA256(localStoredKey, SALT)
4. Verify: accessHash === ACCESS_HMAC (pre-calculated constant in code)
5. encryptionKey = HMAC-SHA256(localStoredKey, "encrypt") - for AES encryption

SALT = "mirigi is the best smartbuilding solution"
ACCESS_HMAC = "c5a1de2293c3aed54d86479d5e8df92a685a97aadcde11563491a7fc8d17af5c"

Security properties:

Key derivation:

// Login verification (symmetric key only exists in user's memory)
localStoredKey = HMAC(userEnteredKey, SALT)
accessHash = HMAC(localStoredKey, SALT)
isValid = (accessHash === ACCESS_HMAC)  // ACCESS_HMAC is pre-calculated constant

// Encryption key derivation
encryptionKey = HMAC(localStoredKey, "encrypt")  // Used for AES-GCM

To change the access key: Calculate new ACCESS_HMAC offline:

node -e "
const crypto = require('crypto');
const SALT = 'mirigi is the best smartbuilding solution';
const newKey = 'YOUR_NEW_KEY';
const localKey = crypto.createHmac('sha256', SALT).update(newKey).digest('hex');
const ACCESS_HMAC = crypto.createHmac('sha256', SALT).update(localKey).digest('hex');
console.log('ACCESS_HMAC:', ACCESS_HMAC);
"

Proposal Builder Pages

All three language versions use the shared layout with just frontmatter:

Login Translations

Login UI strings are in _data/[lang].yml: