# Landforge

**Generate, A/B-test, deploy, and audit static landing pages — as Claude Code skills.**

[![License: MIT](https://img.shields.io/github/license/monthu56/landforge)](LICENSE)
[![Stars](https://img.shields.io/github/stars/monthu56/landforge?style=social)](https://github.com/monthu56/landforge/stargazers)
[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
[![Built for Claude Code](https://img.shields.io/badge/built%20for-Claude%20Code-8A5CF6)](https://claude.com/claude-code)

📖 **English** · [Русский](README.ru.md)

Landforge is a small system of **Claude Code skills** that take a landing page from a brief to a
deployed, measurable page — with SEO, analytics, A/B testing, and a change-audit trail built in.
Landings stay **static HTML** (content in the markup, zero JS on the critical path), so they're
fast and fully indexable. No bundler, no backend, no heavy tooling.

## Why Landforge

- **Static-first, indexable by design.** Content lives in the HTML — crawlers and social previews
  see real content, not an empty `<div id="root">`.
- **Brief → page.** Describe the offer; the generator produces a contract-compliant landing
  (SEO tags, JSON-LD, analytics, A/B scaffold) and self-checks it.
- **A/B on a single URL.** Inline split, no cloaking, variant piped into analytics — safe for SEO.
- **Audit trail.** Every change is recorded (append-only journal + git) — "memory of changes".
- **Portable.** Drop the whole system into any existing project with one skill.
- **Works with any agent.** The toolbox is also exposed as an **MCP server** — call it from
  Cursor, Claude Desktop or your own agent, not only Claude Code.
- **No build step.** What you edit is what ships.

## Skills

| Skill | What it does |
|---|---|
| **`/new-landing`** | a landing from a brief — contract + skeleton + `check_landing.py` validator |
| **`/landing-experiment`** | an A/B test on one URL (inline split), variant tracking, experiment card |
| **`/landing-journal`** | audit journal of every change (`experiments/journal.jsonl` + git) |
| **`/landing-ads`** | ad materials (UTM, copy, keywords, editor exports) — artifacts, no spend |
| **`/init-landing-system`** | deploy this whole system into another existing project |

The generator's input is a **brief** — a single format plus an interviewer prompt you can paste
into any LLM (see `.claude/skills/new-landing/reference/`).

## Use from any agent (MCP)

Beyond Claude Code, the deterministic toolbox (validators, audit journal, UTM) is exposed as an
**MCP server**, so Cursor, Claude Desktop or your own agent can call it too. Tools wrap the same
scripts — one source of logic — and the contract, brief schema and skeleton are served as
resources. Generative workflows (brief interview, landing generation, A/B checklist) are exposed
as prompts; the generation itself stays with the host's model.

```bash
pip install -e mcp     # then point your MCP client at the `landforge-mcp` stdio server
```

See [`mcp/README.md`](mcp/README.md) and [ADR-0002](docs/adr/0002-mcp-server.md). The static-HTML
invariant is untouched — the server is an optional dev tool, never part of a landing's runtime.

## Quick start

**A. Use the system in this repo**
```text
# in Claude Code:
/new-landing          # generate a landing from a brief
```

**B. Install the system into your own existing project**
```bash
bash .claude/skills/init-landing-system/scripts/sync_templates.sh
bash .claude/skills/init-landing-system/scripts/install_user.sh
# then, in your project (Claude Code):
/init-landing-system  # asks for brand/domains/slug, deploys the system (merge-aware)
```

## How it works

```
brief ──▶ /new-landing ──▶ static HTML (SEO + analytics + A/B scaffold)
              │                     │  self-check: check_landing.py
              ▼                     ▼
        git branch ─────▶ preview URL ─────▶ review ─────▶ prod
                                                  every step → audit journal
```

## Requirements

- **Claude Code** (the skills run inside it).
- *(optional)* **Any MCP host** (Claude Desktop, Cursor, custom agents) — to drive the toolbox
  via the bundled MCP server (`mcp/`, needs Python ≥ 3.10) instead of / alongside Claude Code.
- For deployment: a server with **Docker + Traefik** and two `nginx` containers (prod/staging),
  deployed via **GitHub Actions** over SSH. CI and nginx configs are included as templates.

## Deployment

`.github/workflows/deploy.yml` routes by branch:

| Branch | Target | Index |
|---|---|---|
| `main` | production | indexable |
| `dev` | staging | `noindex` |
| any other | preview at `…/{branch}` | `noindex` |

Infra values (domains, containers, dirs) are `{{placeholders}}` resolved by `init-landing-system`
or by hand (`.claude/skills/init-landing-system/reference/placeholders.md`). Only production is
indexed — staging and previews are closed with `X-Robots-Tag: noindex` at the nginx layer.

## Project structure

```
.claude/skills/   the skills (new-landing, landing-experiment, landing-journal, landing-ads, init-landing-system)
mcp/              optional MCP server — exposes the toolbox to any MCP host (ADR-0002)
.github/workflows/ CI: deploy.yml (branch-routed), cleanup-preview.yml
deploy/           nginx.{prod,staging}.conf (IaC templates)
docs/adr/         architecture decision records
experiments/      A/B experiments + audit journal
CLAUDE.md         notes for Claude Code
```

## Contributing

PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md).
The one rule that must never break: a landing stays **static HTML with content in the markup and
zero JS on the critical path** (see [ADR-0001](docs/adr/0001-static-html-invariant.md)).

## License

[MIT](LICENSE) © Александр Перебоев
