Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
22c0fd4
feat: add cmd/popola for authoring documentation for agents
Xe Feb 4, 2026
414c88f
chore(popola): add agent skills to make writing better
Xe Feb 4, 2026
236d9a5
feat(popola): use Xe Iaso's writing style guide
Xe Feb 4, 2026
abb7544
feat(sitegen): add initial command structure
Xe Feb 4, 2026
22d8519
feat(sitegen): add markdown and frontmatter dependencies
Xe Feb 4, 2026
d7be969
feat(sitegen): add frontmatter parsing with tests
Xe Feb 4, 2026
affefb0
feat(sitegen): add content directory scanning
Xe Feb 4, 2026
a47c54a
feat(sitegen): add templ templates and CSS styling
Xe Feb 4, 2026
cba6ca7
feat(sitegen): add HTML page generation
Xe Feb 4, 2026
ddcbfbf
feat(sitegen): add llms.txt generation
Xe Feb 4, 2026
5deb783
feat(sitegen): wire up full generation pipeline
Xe Feb 4, 2026
a144844
chore: add var/ to gitignore for sitegen output
Xe Feb 4, 2026
0f36e7e
docs: add sitegen to main README
Xe Feb 4, 2026
9cdae9a
docs: expand popola description in README
Xe Feb 4, 2026
4c6fb8f
feat(sitegen): skip index.md files in llms.txt
Xe Feb 4, 2026
da1a9d2
docs: add sitegen plan
Xe Feb 4, 2026
ada6a24
chore: npm run format
Xe Feb 4, 2026
566de35
chore(popola): cleanups
Xe Feb 4, 2026
3656e5c
refactor(sitegen): simplify index page list to append to body
Xe Feb 4, 2026
0f6091f
feat(sitegen): root index shows all non-index pages
Xe Feb 4, 2026
4881faa
docs(popola): rewrite README with clear usage instructions
Xe Feb 4, 2026
6a4fd32
feat(popola): add output folder flag and improve tool logging
Xe Feb 5, 2026
85d0e5c
feat(popola): auto-commit generated content to git
Xe Feb 5, 2026
3fa5ad1
fix(sitegen): use MDPath for llms.txt links instead of URLPath
Xe Feb 5, 2026
4ab26cc
fix(popola): rename NoChangesToCommit to ErrNoChangesToCommit
Xe Feb 5, 2026
9d089cc
docs(popola): clean up redundant prompt rules
Xe Feb 5, 2026
014332b
test(popola): update test topic for AWS SDK to Tigris SDK migration
Xe Feb 5, 2026
3357eb7
refactor(popola): use output folder as working directory
Xe Feb 5, 2026
2116a34
feat(popola): add SEO/AEO skill
Xe Feb 9, 2026
a60b349
feat(popola): parse Bash tool uses and add WebFetch/model config
Xe Feb 11, 2026
ae1938f
refactor(popola): extract event handling and deduplicate tool logging
Xe Feb 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ go.work.sum
# env file
.env

# sitegen output
var/

# Editor/IDE
# .idea/
# .vscode/
Expand Down
15 changes: 9 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ This is a repository full of code written in Go. Use the table driven testing sk

### Build, Test & Development Commands

| Command | Description |
| ---------------- | -------------------------------------------------- |
| `npm test` | Runs tests with `go test ./...`. |
| `go build ./...` | Compiles all Go packages. |
| `go test ./...` | Runs all tests. |
| `npm run format` | Formats Go (`goimports`) and JS/HTML (`prettier`). |
| Command | Description |
| ---------------- | ----------------------------------------------------------- |
| `npm run build` | Builds all Go packages, outputting binaries to `./var/bin`. |
| `npm test` | Runs tests with `go test ./...`. |
| `go build ./...` | Compiles all Go packages. |
| `go test ./...` | Runs all tests. |
| `npm run format` | Formats Go (`goimports`) and JS/HTML (`prettier`). |

**Important**: When building Go binaries, always output to `./var/bin` (e.g., `go build -o ./var/bin ./cmd/popola`). This keeps build artifacts out of the repository root.

### Code Formatting & Style

Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
@AGENTS.md
@AGENTS.md
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,28 @@
# glue

Various "glue" code that otherwise defies categorization. This repo is immune from API stability. Use at your own risk.

## Commands

### sitegen

Static site generator for documentation:

```bash
# Generate site from ./content to ./var
go run cmd/sitegen

# Use custom config
go run cmd/sitegen --config custom.yaml
```

See `cmd/sitegen/README.md` for details.

### popola

Popola serves as the canonical implementation of the Omnlana "agent protocol", enabling
consistent agent interactions across AI platforms. It reads a JSON input from stdin with
`topic` and `relevantDocs` fields, then launches a Claude Code session with MCP tools for
web reading and Tigris Discord integration.

See `cmd/popola/README.md` for details.
72 changes: 72 additions & 0 deletions cmd/mcp-yolo-approval/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package main

import (
"context"
"flag"
"log"
"net/http"

"github.com/modelcontextprotocol/go-sdk/mcp"
)

var (
bind = flag.String("bind", "", "TCP host:port to bind HTTP to")
apiKey = flag.String("api-key", "", "API key required for Authorization Bearer header")
)

type Input struct {
ToolName string `json:"tool_name"`
Reason string `json:"reason"`
Input any `json:"input"`
}

type Approval struct {
Behavior string `json:"behavior"`
UpdatedInput any `json:"updatedInput,omitempty"`
Message string `json:"message,omitempty"`
}

func Yolo(ctx context.Context, req *mcp.CallToolRequest, input Input) (*mcp.CallToolResult, *Approval, error) {
result := &Approval{
Behavior: "allow",
UpdatedInput: input.Input,
}

return nil, result, nil
}

func main() {
flag.Parse()

srv := mcp.NewServer(&mcp.Implementation{Name: "approval", Version: "1.0.0"}, nil)
mcp.AddTool(srv, &mcp.Tool{Name: "prompt-user", Description: "Request approval from the user"}, Yolo)

switch *bind {
case "":
if err := srv.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
log.Fatal(err)
}

default:
// Base MCP HTTP handler.
inner := mcp.NewStreamableHTTPHandler(func(req *http.Request) *mcp.Server {
return srv
}, nil)

// Optional bearer token authentication.
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if *apiKey != "" {
if r.Header.Get("Authorization") != "Bearer "+*apiKey {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
}
inner.ServeHTTP(w, r)
})

log.Printf("MCP server listening on %s", *bind)
if err := http.ListenAndServe(*bind, h); err != nil {
log.Fatalf("Server failed: %v", err)
}
}
}
46 changes: 46 additions & 0 deletions cmd/popola/.claude/skills/seo-aeo-best-practices/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
name: seo-aeo-best-practices
description: SEO and AEO (Answer Engine Optimization) best practices including EEAT principles, structured data, and technical SEO. Use when implementing metadata, sitemaps, structured data, or optimizing content for search engines and AI assistants.
license: MIT
metadata:
author: sanity
version: "1.0.0"
---

# SEO & AEO Best Practices

Principles for optimizing content for both traditional search engines (SEO) and AI-powered answer engines (AEO). Includes Google's EEAT guidelines and structured data implementation.

## When to Apply

Reference these guidelines when:

- Implementing metadata and Open Graph tags
- Creating sitemaps and robots.txt
- Adding JSON-LD structured data
- Optimizing content for featured snippets
- Preparing content for AI assistants (ChatGPT, Perplexity, etc.)
- Evaluating content quality using EEAT principles

## Core Concepts

### SEO (Search Engine Optimization)

Optimizing content to rank well in traditional search results (Google, Bing).

### AEO (Answer Engine Optimization)

Optimizing content to be selected as authoritative answers by AI systems.

### EEAT (Experience, Expertise, Authoritativeness, Trustworthiness)

Google's framework for evaluating content quality.

## Resources

See `resources/` for detailed guidance:

- EEAT implementation
- Structured data patterns
- Technical SEO checklist
- AI/AEO considerations
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# AI/AEO Considerations

Answer Engine Optimization (AEO) prepares content to be selected as authoritative answers by AI systems like ChatGPT, Perplexity, Google AI Overviews, and Bing Copilot.

## How AI Selects Answers

AI systems evaluate content based on:

1. **Clarity:** Is the answer direct and easy to extract?
2. **Authority:** Is the source trustworthy?
3. **Comprehensiveness:** Does it fully address the question?
4. **Recency:** Is the information up to date?
5. **Structure:** Can the AI parse and understand it?

## Content Structure for AI

### Direct Answers First

Lead with the answer, then explain.

**Bad:**

> The history of JavaScript dates back to 1995 when Brendan Eich... [500 words later] ...JavaScript runs in the browser.

**Good:**

> JavaScript is a programming language that runs in web browsers. It was created in 1995 by Brendan Eich...

### Clear Headings

Use descriptive H2/H3 headings that match user questions.

**Bad:** "Overview" → "Details" → "More Information"
**Good:** "What is X?" → "How does X work?" → "When should you use X?"

### Lists and Tables

AI extracts structured information more easily than prose.

```markdown
## Benefits of Structured Content

- **Reusability:** Use content across channels
- **Flexibility:** Change presentation without changing content
- **Scalability:** Manage large content volumes
```

### FAQ Format

Question-answer pairs are ideal for AI extraction.

```typescript
// Schema for AI-friendly FAQs
defineType({
name: "faq",
type: "document",
fields: [
defineField({ name: "question", type: "string" }),
defineField({ name: "answer", type: "text" }),
defineField({
name: "category",
type: "reference",
to: [{ type: "faqCategory" }],
}),
],
});
```

## Technical Implementation

### Structured Data (Critical)

JSON-LD helps AI understand content type and relationships.

```typescript
// FAQ structured data
const faqSchema = {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: faqs.map((faq) => ({
"@type": "Question",
name: faq.question,
acceptedAnswer: {
"@type": "Answer",
text: faq.answer,
},
})),
};
```

### Canonical Content

Ensure AI finds your authoritative version, not copies.

- Set canonical URLs
- Avoid duplicate content across pages
- Use `rel="canonical"` for syndicated content

### Freshness Signals

AI systems prefer current information.

- Display publish and update dates prominently
- Update content regularly (even small updates signal freshness)
- Use `dateModified` in structured data

## Content Quality Signals

### Author Credentials

AI systems increasingly check author authority.

- Display author name and credentials
- Link to author profiles
- Include author structured data

### Citations and Sources

Linking to authoritative sources increases trust.

- Cite primary sources
- Link to studies, documentation, official sources
- Avoid circular citations (sites citing each other)

### Comprehensive Coverage

AI prefers content that fully answers questions.

- Cover related questions users might have
- Include definitions for technical terms
- Address common misconceptions

## Measuring AEO Success

### Monitor AI Mentions

Track when AI assistants cite your content:

- Search for your brand + "according to"
- Monitor traffic from AI platforms
- Check Perplexity, Bing Copilot responses

### Track Zero-Click Queries

If AI answers questions directly, traditional rankings matter less.

### Featured Snippet Capture

Featured snippets often become AI answers. Track which you own.

## AEO vs SEO Balance

AEO and SEO largely align—quality content serves both. Key differences:

| Aspect | SEO Focus | AEO Focus |
| ------ | -------------- | ----------------------- |
| Goal | Rank on page 1 | Be THE answer |
| Format | Varies | Direct, structured |
| Length | Often longer | Concise + comprehensive |
| Links | Link building | Source citations |
Loading