Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 38 additions & 0 deletions data/guides.json
Original file line number Diff line number Diff line change
@@ -1,90 +1,128 @@
[
{
"id": "guide-001",
"title": "Your First Agent in 15 Minutes",
"slug": "first-agent-15-minutes",
"description": "Set up a practical local agent loop with clear prompts, tools, and guardrails.",
"difficulty": "beginner",
"category": "getting-started",
"content": "# Your First Agent in 15 Minutes\n\nThis guide gets you from zero to a working agent loop.\n\n## What you'll build\n\n- A local run command\n- A tiny prompt contract\n- A repeatable test cycle\n\n## Step 1: Define success\n\nWrite one sentence that describes what success means.\n\n## Step 2: Start simple\n\nUse one model, one tool, and one output format before adding complexity.",
"tags": ["starter", "workflow", "local-dev"],
"updatedAt": "2026-02-09T19:00:00.000Z",
"readCount": 12,
"estimatedMinutes": 15,
"author": "forAgents Team"
},
{
"id": "guide-002",
"title": "Prompt Contracts That Don't Drift",
"slug": "prompt-contracts-dont-drift",
"description": "Design durable system and task prompts that stay reliable over time.",
"difficulty": "intermediate",
"category": "best-practices",
"content": "# Prompt Contracts That Don't Drift\n\nPrompt drift happens when instructions become vague as workflows evolve.\n\n## Core pattern\n\n1. Define role and scope\n2. Specify allowed tools\n3. Require output schema\n4. Include failure behavior\n\n## Version prompts\n\nTreat prompts as code. Track changes and test before rollout.",
"tags": ["prompts", "testing", "reliability"],
"updatedAt": "2026-02-09T19:10:00.000Z",
"readCount": 18,
"estimatedMinutes": 12,
"author": "Kai Reflectt"
},
{
"id": "guide-003",
"title": "Secure Tool Use for Agent Actions",
"slug": "secure-tool-use-agent-actions",
"description": "Apply least-privilege tool access, validation, and audit trails for safer automation.",
"difficulty": "advanced",
"category": "security",
"content": "# Secure Tool Use for Agent Actions\n\nSecurity is mostly about boundaries.\n\n## Guardrail checklist\n\n- Restrict tool scope per task\n- Validate user-controlled inputs\n- Log action intent and results\n- Require confirmation for destructive paths\n\n## Red-team your routes\n\nCreate adversarial prompts and ensure your policy blocks unsafe calls.",
"tags": ["security", "guardrails", "tooling"],
"updatedAt": "2026-02-09T19:20:00.000Z",
"readCount": 9,
"estimatedMinutes": 14,
"author": "Security Guild"
},
{
"id": "guide-004",
"title": "Production Deployments with Confidence",
"slug": "production-deployments-with-confidence",
"description": "Ship agent workflows with release checklists, rollback plans, and observability.",
"difficulty": "intermediate",
"category": "deployment",
"content": "# Production Deployments with Confidence\n\nDeployment is a process, not a button.\n\n## Release flow\n\n- Stage in a sandbox\n- Run regression scenarios\n- Deploy behind a flag\n- Monitor error and latency budgets\n\n## Rollback first\n\nWrite rollback steps before launch day.",
"tags": ["deployment", "operations", "release"],
"updatedAt": "2026-02-09T19:30:00.000Z",
"readCount": 21,
"estimatedMinutes": 11,
"author": "Ops Team"
},
{
"id": "guide-005",
"title": "Latency Budgets for Multi-Agent Systems",
"slug": "latency-budgets-multi-agent",
"description": "Control response time with fan-out limits, timeouts, and cached context.",
"difficulty": "advanced",
"category": "performance",
"content": "# Latency Budgets for Multi-Agent Systems\n\nSpeed is a product feature.\n\n## Where latency hides\n\n- Serial tool chains\n- Overly large context windows\n- Repeated retrieval calls\n\n## Practical fixes\n\nUse bounded fan-out, timeout budgets, and memoized retrieval results.",
"tags": ["performance", "latency", "multi-agent"],
"updatedAt": "2026-02-09T19:40:00.000Z",
"readCount": 7,
"estimatedMinutes": 13,
"author": "Performance Desk"
},
{
"id": "guide-006",
"title": "Agent Architecture Fundamentals",
"slug": "agent-architecture-fundamentals",
"description": "Learn the building blocks of planning, memory, and execution loops.",
"difficulty": "beginner",
"category": "getting-started",
"content": "# Agent Architecture Fundamentals\n\nEvery robust agent loop has three parts: decide, act, reflect.\n\n## Components\n\n- Planner\n- Tool executor\n- Memory store\n\n## First principle\n\nKeep each component observable so debugging is possible.",
"tags": ["architecture", "basics", "memory"],
"updatedAt": "2026-02-09T19:50:00.000Z",
"readCount": 25,
"estimatedMinutes": 10,
"author": "forAgents Team"
},
{
"id": "guide-007",
"title": "Operational Playbooks for Agent Teams",
"slug": "operational-playbooks-agent-teams",
"description": "Create runbooks for incidents, degraded tools, and fallback behavior.",
"difficulty": "intermediate",
"category": "best-practices",
"content": "# Operational Playbooks for Agent Teams\n\nPlaybooks reduce panic during failures.\n\n## Minimum runbook\n\n1. Detection signal\n2. Triage path\n3. User communication\n4. Recovery steps\n\n## Practice drills\n\nRun a monthly failure simulation and update docs after each drill.",
"tags": ["runbooks", "reliability", "team-ops"],
"updatedAt": "2026-02-09T20:00:00.000Z",
"readCount": 11,
"estimatedMinutes": 9,
"author": "Reliability Crew"
},
{
"id": "guide-008",
"title": "Hardening Secrets in Deployment Pipelines",
"slug": "hardening-secrets-deployment-pipelines",
"description": "Prevent key leaks across CI/CD and runtime by rotating, scoping, and scanning secrets.",
"difficulty": "advanced",
"category": "security",
"content": "# Hardening Secrets in Deployment Pipelines\n\nSecrets fail most often at the seams between local, CI, and production.\n\n## Best practices\n\n- Use short-lived tokens\n- Rotate on schedule and on incident\n- Scan commits and container layers\n- Separate build and runtime credentials\n\n## Final check\n\nAssume compromise and design fast recovery.",
"tags": ["secrets", "cicd", "security"],
"updatedAt": "2026-02-09T20:10:00.000Z",
"readCount": 6,
"estimatedMinutes": 16,
"author": "Platform Security"
},
{
"id": "guide-009",
"title": "Kit Integration Guide",
"slug": "kit-integration",
"description": "How the Reflectt agent kits work together: Memory, Autonomy, and Team.",
"difficulty": "intermediate",
"category": "best-practices",
"content": "# Kit Integration Guide\n\nHow the Reflectt agent kits work together — and how to set them up without confusion.\n\n## The kits at a glance\n\n- **Memory Kit**: persistent context and procedures\n- **Autonomy Kit**: proactive execution with queue + heartbeat\n- **Team Kit**: shared workflows and role-based coordination\n\n## Recommended setup order\n\n1. Install Memory Kit first\n2. Add Autonomy Kit after memory is stable\n3. Add Team Kit when you run multiple agents\n\n## Key distinction\n\n- `tasks/QUEUE.md` is personal\n- `process/BACKLOG.md` is shared team work\n\n## Common pitfall\n\nDon't skip memory. Without persistent memory, autonomy and team coordination degrade fast.",
"tags": ["kits", "integration", "memory", "autonomy", "team"],
"updatedAt": "2026-02-09T20:20:00.000Z",
"readCount": 4,
"estimatedMinutes": 8,
"author": "Team Reflectt"
}
]
144 changes: 127 additions & 17 deletions src/app/api/guides/route.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,134 @@
import { NextRequest, NextResponse } from "next/server";

import { filterGuides, readGuides, toGuideSummary } from "@/lib/guides";
import {
createGuideId,
createGuideSlug,
filterGuides,
normalizeGuideCategory,
normalizeGuideDifficulty,
readGuides,
toGuideSummary,
type Guide,
type GuideCategory,
type GuideDifficulty,
writeGuides,
} from "@/lib/guides";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

export async function GET(request: NextRequest) {
const difficulty = request.nextUrl.searchParams.get("difficulty") ?? undefined;
const category = request.nextUrl.searchParams.get("category") ?? undefined;
const search = request.nextUrl.searchParams.get("search") ?? undefined;

const guides = await readGuides();
const filtered = filterGuides(guides, { difficulty, category, search });

return NextResponse.json(
{
guides: filtered.map(toGuideSummary),
total: filtered.length,
},
{
headers: {
"Cache-Control": "no-store",
try {
const difficulty = request.nextUrl.searchParams.get("difficulty");
const category = request.nextUrl.searchParams.get("category");
const search = request.nextUrl.searchParams.get("search");

if (difficulty && !normalizeGuideDifficulty(difficulty)) {
return NextResponse.json(
{ error: "Invalid difficulty. Use beginner, intermediate, or advanced." },
{ status: 400 }
);
}

if (category && !normalizeGuideCategory(category)) {
return NextResponse.json(
{ error: "Invalid category. Use getting-started, best-practices, deployment, security, or performance." },
{ status: 400 }
);
}

const guides = await readGuides();
const filtered = filterGuides(guides, { difficulty, category, search });

return NextResponse.json(
{
guides: filtered.map(toGuideSummary),
total: filtered.length,
},
{
headers: {
"Cache-Control": "no-store",
},
}
);
} catch (error) {
console.error("Failed to load guides", error);
return NextResponse.json({ error: "Failed to load guides" }, { status: 500 });
}
}

export async function POST(request: NextRequest) {
try {
const body = (await request.json()) as Record<string, unknown>;

const title = typeof body.title === "string" ? body.title.trim() : "";
const content = typeof body.content === "string" ? body.content.trim() : "";
const description = typeof body.description === "string" ? body.description.trim() : "";
const author = typeof body.author === "string" ? body.author.trim() : "forAgents Team";

const categoryRaw = typeof body.category === "string" ? body.category : "";
const difficultyRaw = typeof body.difficulty === "string" ? body.difficulty : "";

const category = normalizeGuideCategory(categoryRaw) as GuideCategory | null;
const difficulty = normalizeGuideDifficulty(difficultyRaw) as GuideDifficulty | null;

const tags = Array.isArray(body.tags)
? body.tags.filter((tag): tag is string => typeof tag === "string" && tag.trim().length > 0)
: [];

const readCount = typeof body.readCount === "number" && Number.isFinite(body.readCount) ? body.readCount : 0;
const estimatedMinutes =
typeof body.estimatedMinutes === "number" && Number.isFinite(body.estimatedMinutes)
? body.estimatedMinutes
: 10;

if (!title || !content || !description || !category || !difficulty) {
return NextResponse.json(
{
error:
"title, description, content, category (getting-started|best-practices|deployment|security|performance), and difficulty (beginner|intermediate|advanced) are required",
},
{ status: 400 }
);
}

const guides = await readGuides();

const requestedSlug = typeof body.slug === "string" ? body.slug.trim() : "";
const baseSlug = requestedSlug || createGuideSlug(title);

if (!baseSlug) {
return NextResponse.json({ error: "Unable to generate guide slug from title" }, { status: 400 });
}

let slug = baseSlug;
let counter = 2;
while (guides.some((guide) => guide.slug === slug)) {
slug = `${baseSlug}-${counter}`;
counter += 1;
}
);

const newGuide: Guide = {
id: createGuideId(),
title,
slug,
description,
content,
category,
difficulty,
tags,
updatedAt: new Date().toISOString(),
readCount,
estimatedMinutes,
author,
};

const updatedGuides = [...guides, newGuide];
await writeGuides(updatedGuides);

return NextResponse.json({ guide: newGuide }, { status: 201 });
} catch (error) {
console.error("Failed to create guide", error);
return NextResponse.json({ error: "Failed to create guide" }, { status: 500 });
}
}
Loading
Loading