The Unified Identity Platform: Trusted Identity for Machines and Humans — Verified, Private, Attested
Static marketing website for the Artagon Identity Platform, built with Astro and deployed to GitHub Pages at artagon.com.
- Quick Start
- Project Structure
- Technology Stack
- Configuration
- Development
- Build & Deployment
- Security & Performance
- Scripts & Utilities
- CI/CD Pipeline
- OpenSpec Workflow
- Contributing
# Install dependencies
npm install
# Start development server (http://localhost:4321)
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Format code
npm run formatartagon-site/
├── .agents/ # AI agent configuration and policies
├── .github/workflows/ # GitHub Actions CI/CD pipelines
├── openspec/ # OpenSpec spec-driven development
│ ├── changes/ # Proposed changes and features
│ ├── specs/ # Current capability specifications
│ ├── project.md # Project conventions
│ ├── contributing.md # Contribution guidelines
│ └── AGENTS.md # AI agent instructions
├── public/ # Static assets (copied as-is to dist/)
│ ├── .well-known/ # Well-known URIs
│ ├── assets/ # Images, logos, OG images
│ │ └── logos/ # Logo variants and documentation
│ ├── icons/ # Favicons and app icons
│ ├── docsearch.json # Algolia DocSearch config
│ ├── robots.txt # Search engine directives
│ └── sitemap.xml # Generated sitemap
├── scripts/ # Build and asset generation scripts
│ ├── csp.mjs # Content Security Policy injection
│ ├── lhci-serve.mjs # LHCI local server with ready signal
│ ├── sri.mjs # Subresource Integrity injection
│ ├── make-og-from-template.sh # OG image generation
│ ├── make-favicon.sh # Favicon generation
│ └── icons/ # Icon generation utilities
├── src/
│ ├── components/ # Reusable Astro components
│ │ ├── Header.astro # Main navigation
│ │ ├── Footer.astro # Site footer
│ │ ├── SeoTags.astro # SEO meta tags
│ │ ├── FaqSearch.astro # FAQ search functionality
│ │ └── ...
│ ├── data/ # Structured data
│ │ ├── faq.ts # FAQ content with schema
│ │ └── roadmap.ts # Roadmap phases and timeline
│ ├── layouts/
│ │ └── BaseLayout.astro # Main layout template
│ └── pages/ # File-based routing
│ ├── index.astro # Homepage
│ ├── platform/ # Platform features
│ ├── roadmap/ # Product roadmap
│ ├── faq/ # FAQ page
│ ├── vision/ # Vision and strategy
│ ├── docs/ # Docs shell
│ ├── console/ # Console shell
│ ├── search/ # Search interface
│ └── ...
├── astro.config.mjs # Astro configuration
├── lighthouserc.json # Lighthouse CI thresholds
├── lychee.toml # Link checker configuration
├── package.json # Dependencies and scripts
└── README.md # This file
- Astro v5.15.5 - Static site generator with zero JS by default
- Static Output - Pure HTML/CSS/JS, no server required
- File-based Routing - Pages in
src/pages/map to routes
- @astrojs/sitemap - Automatic sitemap.xml generation
- Filters out
/_drafts/pages - Canonical domain:
https://artagon.com
- Filters out
- Node.js 20+ (CI uses Node 20 and 22)
- npm - Package manager
- Prettier 3.6.2 - Code formatting
- Subresource Integrity (SRI) - Cryptographic hash validation for JS/CSS
- Content Security Policy (CSP) - Script execution controls via meta tags
- Lighthouse CI - Automated performance and accessibility audits
- Lychee - Link checking and validation
File: astro.config.mjs
export default defineConfig({
site: "https://artagon.com", // Canonical domain
output: "static", // Static site generation
trailingSlash: "never", // Clean URLs without trailing slashes
integrations: [
sitemap({
filter: (page) => !page.includes("/_drafts/"),
customPages: [],
}),
],
});File: lighthouserc.json
Performance thresholds enforced in CI:
- Performance: ≥90% (warning)
- Accessibility: ≥95% (error)
- Best Practices: ≥90% (error)
- SEO: ≥95% (error)
Runs 2 times per URL and uploads to temporary public storage.
Local usage:
npm run build
npx -y @lhci/cli@0.14.x autorun --config=lighthouserc.jsonThe LHCI config starts scripts/lhci-serve.mjs, which prints READY once the
static server responds. Override the port with LHCI_PORT if needed.
File: lychee.toml
verbose = "info"
accept = ["200..299", "403"]
exclude_path = ["dist", "node_modules"]
exclude = [
"http://localhost.*",
"https://twitter.com/.*", # Often blocks bots
"mailto:.*"
]
retry_wait_time = 2
max_retries = 2
timeout = 20{
"dev": "astro dev", // Start dev server
"build": "astro build", // Build + run postbuild scripts
"preview": "astro preview", // Preview production build
"format": "prettier --write .", // Format all files
"postbuild": "node scripts/sri.mjs && node scripts/csp.mjs"
}Postbuild Pipeline:
astro build- Compiles todist/scripts/sri.mjs- Injects SRI hashes and crossorigin attributesscripts/csp.mjs- Generates CSP meta tags with inline script hashes
npm run dev- Runs on
http://localhost:4321 - Hot module reloading enabled
- File watching for instant updates
Create .env file for local configuration (gitignored):
# Currently no environment variables required
# Add as needed for local development- Create
.astrofile insrc/pages/ - Use
BaseLayoutwrapper:
---
import BaseLayout from "../layouts/BaseLayout.astro";
---
<BaseLayout
title="Page Title"
description="SEO description (150-160 chars)"
path="/page-path"
>
<!-- Page content -->
</BaseLayout>- Update navigation in
src/components/Header.astroif adding top-level route
Location: src/components/
All components are Astro components (.astro files) with:
- Zero JavaScript by default (ships pure HTML/CSS)
- Optional client-side JS via
<script>tags - TypeScript support in frontmatter
Key Components:
Header.astro- Main navigation with theme toggleFooter.astro- Site footer with linksSeoTags.astro- Meta tags, Open Graph, JSON-LD schemaFaqSearch.astro- Client-side FAQ searchRoadmapPhaseCard.astro- Roadmap timeline cards
Location: src/data/
TypeScript files exporting structured content:
faq.ts - FAQ with JSON-LD schema:
export const faqData = {
title: "Frequently Asked Questions",
items: [
{
question: "What is Artagon?",
answer: "...",
},
],
};roadmap.ts - Product roadmap phases:
export const roadmapPhases = [
{
phase: "Foundation",
quarter: "Q1 2024",
status: "in-progress",
items: [...],
},
];npm run buildBuild Process:
- Astro compiles pages, components, and assets to
dist/ - Sitemap generated at
dist/sitemap.xml - Postbuild: SRI script adds integrity hashes to
<script>and<link>tags - Postbuild: CSP script injects Content Security Policy meta tag
Output: dist/ directory with static HTML/CSS/JS
npm run previewServes dist/ on http://localhost:4321 to test production build.
Automatic deployment on push to main branch.
Workflow: .github/workflows/deploy.yml
1. Checkout code
2. Setup Node.js 22
3. npm install
4. npm run build
5. Upload dist/ artifact
6. Deploy to GitHub PagesRequired Pages setting: set Source to GitHub Actions so deployments run from .github/workflows/deploy.yml (branch-based Jekyll builds are not supported).
Configuration:
- Custom domain:
artagon.com(set in repo settings) - CNAME:
artagon.com(inpublic/CNAME) - HTTPS: Enforced via GitHub Pages settings
- Permissions:
contents: read, pages: write, id-token: write
Tagged releases (e.g., v0.1.0) automatically:
- Build the site
- Create GitHub release
- Attach
dist.zipto release
Workflow: .github/workflows/release.yml
Script: scripts/sri.mjs
Automatically adds cryptographic hashes to local JS/CSS resources:
<!-- Before -->
<script src="/assets/app.js"></script>
<!-- After -->
<script src="/assets/app.js" integrity="sha256-..." crossorigin="anonymous"></script>Important: Disable CDN minification to avoid SRI mismatches.
Script: scripts/csp.mjs
Generates strict CSP as <meta> tag with:
default-src 'self'- Only same-origin resourcesscript-src 'self' 'sha256-...'- Inline scripts hashedstyle-src 'self' 'unsafe-inline'- Styles allowed (Astro scoped styles)img-src 'self' data:- Images from same origin + data URIsobject-src 'none'- No pluginsbase-uri 'none'- Prevent base tag injectionframe-ancestors 'none'- Prevent clickjacking
All inline <script> tags are hashed and added to CSP automatically.
- Zero JS by default - Astro ships pure HTML/CSS
- Scoped CSS - Component styles are scoped and bundled
- Asset optimization - Images and icons optimized for web
- Static generation - No server-side rendering overhead
- Lighthouse scores - Enforced ≥90% performance in CI
Recommended headers (configure at CDN/hosting level):
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
All scripts located in scripts/ directory.
./scripts/make-og-from-template.sh \
"Artagon — Identity that can prove it" \
"Passkeys • VCs • Attestation • Policy" \
public/assets/og-image.png \
--logo public/assets/logo-lockup.pngCreates Open Graph images from SVG templates.
./scripts/make-favicon.shGenerates multi-size favicons from source SVG.
./scripts/icons/make-icons.shCreates app icons, touch icons, and PWA assets.
Documentation:
scripts/icons/README.md- Icon generation overviewscripts/icons/VERIFICATION.md- Icon verification checklist
./scripts/svg-to-pngs.sh input.svg output-dir/Batch converts SVG to multiple PNG sizes.
./scripts/convert-logos.shGenerates logo variants from source files.
Documentation:
public/assets/logos/README.md- Logo usage guidelinesdocs/LOGO_USAGE.md- Detailed logo documentationdocs/LOGO_CONVERSION_SUMMARY.md- Conversion process
File: scripts/sri.mjs
- Scans all HTML files in
dist/ - Computes SHA-256 hashes for local JS/CSS
- Adds
integrityandcrossoriginattributes - Updates HTML in-place
File: scripts/csp.mjs
- Extracts inline script content from all HTML files
- Computes SHA-256 hashes
- Builds CSP policy with script hashes
- Injects
<meta http-equiv="Content-Security-Policy">tag
Location: .github/workflows/
Trigger: Push to main or manual dispatch
Jobs:
- Build - Install deps, build site, upload artifact
- Deploy - Deploy to GitHub Pages
Node version: 22
Trigger: Push to main
Process:
- Build site
- Start HTTP server on port 8081
- Run Lighthouse audits (2 runs)
- Assert score thresholds
- Upload results to temporary storage
Thresholds:
- Performance: ≥90% (warn)
- Accessibility: ≥95% (error)
- Best Practices: ≥90% (error)
- SEO: ≥95% (error)
Trigger: Scheduled (weekly) or manual
Process:
- Build site
- Run
lycheelink checker on:- Markdown files (
**/*.md) - HTML files (
public/**/*.html) - Astro components (
src/**/*.astro)
- Markdown files (
Configuration: lychee.toml
Trigger: Push
Validates AI agent configuration in .agents/ directory.
Trigger: Manual dispatch or changes to the workflow file
Prepares the repository for GitHub Copilot coding agent sessions. The workflow must define a single copilot-setup-steps job that checks out the repo, installs the latest LTS Node.js version, and runs npm ci.
Trigger: Push tag matching v*.*.*
Process:
- Build site
- Create zip of
dist/ - Create GitHub release
- Attach
dist.zipas release asset
This project uses OpenSpec for spec-driven development.
- Specs (
openspec/specs/) - Current truth, what IS built - Changes (
openspec/changes/) - Proposals, what SHOULD change - Archive (
openspec/changes/archive/) - Completed changes
# List active changes
openspec list
# List all specifications
openspec list --specs
# Show change or spec details
openspec show <change-id>
openspec show <spec-id> --type spec
# Validate changes
openspec validate <change-id> --strict
# Archive after deployment
openspec archive <change-id> --yes-
Create Proposal - New feature or breaking change
openspec/changes/<change-id>/proposal.mdopenspec/changes/<change-id>/tasks.mdopenspec/changes/<change-id>/specs/<spec-id>/spec.md
-
Create Issue - Link or copy the spec into the issue description
-
Implement - Follow tasks.md checklist
- Branch:
feature/site(<spec#>)-<feature-short-name>(spec#is the GitHub issue number) - Commits:
feat(<spec-id>): description - Update agent context docs with a summary of branch changes
- Branch:
-
Archive - After deployment to production
- Branch:
archive/<change-id> - Command:
openspec archive <change-id> --yes - Creates:
openspec/changes/archive/YYYY-MM-DD-<change-id>/
- Branch:
openspec/AGENTS.md- Comprehensive OpenSpec guide for AI agentsopenspec/project.md- Project context and conventionsopenspec/contributing.md- Contribution guidelines with examples
See openspec/contributing.md for:
- Branch naming conventions (conventional commits)
- OpenSpec workflow examples
- AI agent best practices
- Archiving and closing issues
- Code formatting and linting
-
Check existing work:
openspec list # Active changes openspec list --specs # Existing capabilities
-
Create issue and include spec content:
# Issue description must link to or include the OpenSpec change gh issue create --title "Spec: <change-id>" --body "..."
-
Create feature branch (spec# = GitHub issue number):
git checkout -b feature/site(<spec#>)-<feature-short-name>
-
Make changes, commit:
git commit -m "feat(<spec-id>): description Implements openspec/changes/<change-id>/ Affects: specs/<spec-id>/spec.md Closes #<spec#>"
-
Run local checks:
npm run format npm run build npm run preview
-
Create PR:
gh pr create --title "feat(<spec-id>): Title" --body "..."
-
After deployment, archive:
git checkout -b archive/<change-id> openspec archive <change-id> --yes openspec validate --strict # Commit, PR, merge
- Formatting: Prettier (run
npm run format) - Commits: Conventional commits format
- Components: Astro components with TypeScript frontmatter
- CSS: Scoped component styles, CSS custom properties
- Branch follows naming convention (
feature/site(spec#)-...for OpenSpec changes;feat/,fix/, etc. otherwise) - Commits reference OpenSpec changes and issues
- Local build succeeds (
npm run build) - Code formatted (
npm run format) - SEO tags updated for new pages
- Navigation updated if adding routes
- Screenshots included for UI changes
- OpenSpec tasks marked complete
[x]
Location: .agents/ and OpenSpec instructions
.agents/policies/guardrails.md- Development guardrails and constraints.agents/policies/release-checklist.md- Pre-release validation stepsAGENTS.md→openspec/AGENTS.md- Main OpenSpec agent instructionsCLAUDE.md- Symlink to AGENTS.mdGEMINI.md- Symlink to AGENTS.md
AI agents should:
- Read
openspec/AGENTS.mdfor OpenSpec workflow - Read
openspec/project.mdfor project context - Read
openspec/contributing.mdfor contribution guidelines - Use OpenSpec commands to understand existing work
- Follow OpenSpec branch naming (
feature/site(spec#)-...) for spec work; conventional naming for other changes - Update agent context docs with a summary of branch changes
- Create proposals for new features/breaking changes
- Track tasks with TODO lists
- Archive changes after deployment
docs/SITE_AUDIT.md- Site structure and content auditdocs/LOGO_USAGE.md- Logo usage guidelines and variantsdocs/LOGO_CONVERSION_SUMMARY.md- Logo conversion processpublic/assets/logos/README.md- Logo file referencescripts/icons/README.md- Icon generation guidescripts/icons/VERIFICATION.md- Icon verification checklist
Private repository - All rights reserved.
For issues or questions:
- Open an issue on GitHub
- Review existing OpenSpec changes and specs
- Check
.agents/policies/for guardrails and checklists