Purpose

Enable publishing Lattice research documents to the web via lattice publish <topic>, generating a static site powered by Astro Starlight and deployed to lattice.zabaca.com via Netlify.

Goals

  1. Simple workflow: lattice publish tryhackme publishes a topic
  2. Astro-powered: Use Starlight for beautiful, accessible documentation
  3. Selective publishing: Choose which topics to make public
  4. Netlify integration: Match existing zabaca.com deployment workflow
  5. Preserve graph data: Include entity relationships in published content

Architecture Overview

┌─────────────────────────────────────────────────────────────────────────┐
│ lattice publish <topic> │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Phase 1: Export │
│ ───────────────── │
│ • Read ~/.lattice/docs/<topic>/*.md │
│ • Query graph for entities & relationships │
│ • Mark topic as "published" in database │
│ • Copy/transform markdown files │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Phase 2: Generate │
│ ───────────────── │
│ • Write to Astro content collection (src/content/docs/) │
│ • Generate navigation sidebar config │
│ • Add entity/relationship metadata as frontmatter │
│ • Update site index with new topic │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Phase 3: Build (optional, with --build or --preview) │
│ ───────────────── │
│ • Run: astro build │
│ • Output to dist/ │
│ • Or: astro dev for preview │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Phase 4: Deploy (optional, with --deploy) │
│ ───────────────── │
│ • Git commit & push to zabaca/lattice-site │
│ • Or: netlify deploy --prod │
│ • Netlify auto-deploys to lattice.zabaca.com │
└─────────────────────────────────────────────────────────────────────────┘

URL Structure

Domain Setup

DomainPurpose
www.zabaca.comMain website (existing)
lattice.zabaca.comPublished research (new subdomain)

URL Patterns

lattice.zabaca.com/
├── / # Homepage (all published topics)
├── /tryhackme/ # Topic index (from README.md)
│ ├── /overview/ # Individual document
│ └── /career-readiness/ # Individual document
├── /macos-window-management/
│ ├── /minimized-window-restore/
│ └── /jetbrains-cmd-backtick-fix/
└── /search/ # Full-text search (Pagefind)

Slug Derivation

Source FilePublished URL
~/.lattice/docs/tryhackme/README.md/tryhackme/
~/.lattice/docs/tryhackme/overview.md/tryhackme/overview/
~/.lattice/docs/tryhackme/career-readiness.md/tryhackme/career-readiness/

Technology Stack

Core

ComponentTechnologyWhy
Static Site GeneratorAstro 5.xContent-focused, excellent Markdown support
Documentation ThemeStarlightBuilt-in search, dark mode, sidebar, accessibility
HostingNetlifyAlready using for zabaca.com, free tier, auto-deploy
SearchPagefindBuilt into Starlight, static search index

Astro Starlight Features Used

  • Content Collections: Type-safe Markdown handling
  • Automatic Sidebar: Generated from file structure
  • Pagefind Search: Full-text search, no server needed
  • Dark/Light Mode: Toggle built-in
  • Table of Contents: Auto-generated from headings
  • Responsive Design: Mobile-friendly out of box
  • Frontmatter Validation: Zod schemas for metadata

File Structure

Lattice Side (source)

~/.lattice/
├── docs/ # Research documents (source of truth)
│ ├── tryhackme/
│ │ ├── README.md
│ │ ├── overview.md
│ │ └── career-readiness.md
│ └── macos-window-management/
│ └── ...
├── lattice.duckdb # Graph database
└── .publish-manifest.json # Tracks what's published

Astro Site (generated)

~/.lattice/site/ # Or: ~/zabaca/lattice-site/
├── astro.config.mjs
├── package.json
├── src/
│ ├── content/
│ │ └── docs/ # Starlight content collection
│ │ ├── tryhackme/
│ │ │ ├── index.md # From README.md
│ │ │ ├── overview.md
│ │ │ └── career-readiness.md
│ │ └── index.md # Homepage
│ └── assets/ # Images, custom CSS
├── public/
│ └── favicon.ico
└── dist/ # Built output (gitignored)

Markdown Transformation

Input (Lattice format)

# TryHackMe - Platform Overview
## What is TryHackMe?
TryHackMe is a global cybersecurity training platform...
## Sources
1. [TryHackMe vs HackTheBox](https://tryhackme.com/...)

Output (Starlight format)

---
title: TryHackMe - Platform Overview
description: Comprehensive overview of the TryHackMe cybersecurity training platform
sidebar:
order: 1
label: Platform Overview
lastUpdated: 2025-12-25
editUrl: false
# Lattice metadata
lattice:
topic: tryhackme
entities:
- { type: "Technology", name: "TryHackMe" }
- { type: "Concept", name: "Cybersecurity Training" }
relationships:
- { from: "TryHackMe", to: "HackTheBox", type: "COMPARED_TO" }
---
## What is TryHackMe?
TryHackMe is a global cybersecurity training platform...
## Sources
1. [TryHackMe vs HackTheBox](https://tryhackme.com/...)

Transformation Rules

SourceTarget
First H1 headingtitle frontmatter
First paragraphdescription frontmatter
File order in dirsidebar.order
Filenamesidebar.label (humanized)
Graph entitieslattice.entities frontmatter
Graph relationshipslattice.relationships frontmatter

CLI Commands

Primary Command

Terminal window
lattice publish <topic> [options]

Options

FlagDescriptionDefault
--allPublish all topicsfalse
--previewStart local dev serverfalse
--buildBuild static sitefalse
--deployDeploy to Netlifyfalse
--dry-runShow what would be publishedfalse
--forceRepublish even if unchangedfalse
--output <path>Custom output directory~/.lattice/site/

Examples

Terminal window
# Publish tryhackme topic to content collection
lattice publish tryhackme
# Preview locally (runs astro dev)
lattice publish tryhackme --preview
# Build and deploy
lattice publish --all --build --deploy
# See what would be published
lattice publish tryhackme --dry-run
Terminal window
# List published topics
lattice published
# Unpublish a topic
lattice unpublish tryhackme
# Check publish status
lattice status --published

Implementation Plan

Phase 1: Foundation (MVP)

Goal: Basic lattice publish that copies markdown to Astro site

Tasks:

  1. Create PublishCommand in src/commands/publish.command.ts
  2. Create PublishService in src/publish/publish.service.ts
  3. Add frontmatter transformation logic
  4. Generate sidebar navigation
  5. Create Astro site scaffold (one-time init)

Files to create:

src/
├── commands/
│ └── publish.command.ts
├── publish/
│ ├── publish.module.ts
│ ├── publish.service.ts
│ └── markdown-transformer.service.ts

Phase 2: Astro Site

Goal: Starlight-based site that renders published content

Tasks:

  1. Create Astro Starlight project in ~/.lattice/site/
  2. Configure content collection for docs
  3. Customize Starlight theme (branding, colors)
  4. Add homepage template
  5. Configure Netlify deployment

Astro config:

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
site: 'https://lattice.zabaca.com',
integrations: [
starlight({
title: 'Lattice',
description: 'Research knowledge base',
social: {
github: 'https://github.com/Zabaca/lattice',
},
sidebar: [
// Auto-generated from content structure
{ label: 'Topics', autogenerate: { directory: '.' } },
],
search: {
provider: 'local', // Pagefind
},
}),
],
});

Phase 3: Graph Integration

Goal: Include entity/relationship data in published pages

Tasks:

  1. Query graph for topic entities
  2. Add entities as frontmatter metadata
  3. Create “Related Topics” component
  4. Add entity type badges to pages
  5. Generate knowledge graph visualization (optional)

Phase 4: Deployment

Goal: Automated deployment workflow

Tasks:

  1. Create GitHub repo for site (zabaca/lattice-site)
  2. Configure Netlify for subdomain
  3. Add --deploy flag to command
  4. Implement git commit/push workflow
  5. Add CI/CD via Netlify

Netlify Configuration

DNS Setup

Add subdomain in Netlify:

  1. Go to Domain settings for zabaca.com
  2. Add subdomain: lattice.zabaca.com
  3. Point to zabaca/lattice-site deployment

netlify.toml

[build]
command = "npm run build"
publish = "dist"
[build.environment]
NODE_VERSION = "20"
# SPA fallback for client-side routing (if needed)
[[redirects]]
from = "/*"
to = "/404"
status = 404
# Cache static assets
[[headers]]
for = "/_astro/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

Database Schema Additions

Published Topics Tracking

-- Add to nodes table or create new table
CREATE TABLE IF NOT EXISTS published_topics (
topic_name VARCHAR PRIMARY KEY,
published_at TIMESTAMP DEFAULT NOW(),
last_published TIMESTAMP DEFAULT NOW(),
url VARCHAR,
content_hash VARCHAR, -- To detect changes
version INTEGER DEFAULT 1
);

.publish-manifest.json (Alternative)

{
"version": 1,
"published": {
"tryhackme": {
"publishedAt": "2025-12-25T12:00:00Z",
"lastPublished": "2025-12-25T12:00:00Z",
"url": "https://lattice.zabaca.com/tryhackme/",
"contentHash": "abc123...",
"documents": [
{ "slug": "overview", "hash": "def456..." },
{ "slug": "career-readiness", "hash": "ghi789..." }
]
}
}
}

Content Policies

What Gets Published

ContentPublishedControllable
Markdown contentYesPer-topic
Entity metadataYesGlobal option
Cross-topic linksYesAuto-resolved
ImagesYesCopied to public/
Source links/citationsYesPreserved
EmbeddingsNoN/A
Internal notesNoUse <!-- --> comments

Exclusion Patterns

---
publish: false # Exclude this document
---

Or directory-level:

~/.lattice/docs/
├── tryhackme/ # Published
├── personal-notes/ # Not published (prefix or config)
└── _drafts/ # Not published (underscore prefix)

Future Enhancements

Phase 5+

  1. Knowledge Graph Visualization

    • D3.js or Cytoscape graph of entities
    • Interactive exploration
    • /graph page
  2. RSS Feed

    • Auto-generated from published topics
    • Updates when new content added
  3. API Endpoints (via Netlify Functions)

    • /api/search?q=... - Programmatic search
    • /api/graph/:topic - Graph data as JSON
  4. Multi-Author Support

    • Vanity URLs: lattice.zabaca.com/:author/:topic
    • Author attribution
  5. Versioning

    • Track document versions
    • Show “last updated” dates
    • Changelog per topic
  6. Comments/Discussions

    • GitHub Discussions integration
    • Or Giscus for page-level comments

Security Considerations

  1. No sensitive data in published content

    • Review before publishing
    • Exclude patterns for private directories
  2. No embeddings published

    • Vector data stays local
  3. Source attribution

    • Maintain source links
    • Respect copyright in research
  4. Access control (future)

    • Could add authentication for private topics
    • Netlify Identity or similar

Cost Analysis

ComponentCost
Netlify hostingFree (100GB/month bandwidth)
Custom subdomainFree (already own zabaca.com)
Astro/StarlightFree (open source)
Pagefind searchFree (static, client-side)
Total$0/month

Success Criteria

  1. lattice publish tryhackme works end-to-end
  2. Site accessible at lattice.zabaca.com/tryhackme/
  3. Search works across all published topics
  4. Mobile-friendly responsive design
  5. Fast (< 2s page load)
  6. Accessible (Lighthouse score > 90)

Next Steps

  1. Create Astro site scaffold in ~/.lattice/site/ or ~/zabaca/lattice-site/
  2. Implement PublishCommand in Lattice
  3. Test with tryhackme topic as first publish
  4. Configure Netlify subdomain
  5. Deploy and verify

Sources

  1. Astro Content Collections
  2. Astro Starlight - Getting Started
  3. Starlight Configuration Reference
  4. Netlify Subdomain Setup
  5. Pagefind Search