feat(field-guide): add Logos Field Guide at /field-guide

Port the 16-chapter Logos Field Guide from the standalone reference site
into logos.co as content-driven pages, discoverable from the footer and
the global nav.

- content/field-guide/en: manifest (TOC) + chapter Markdown bodies
- @repo/content: fieldGuide schema + loaders, readText fs helper
- /field-guide index + /field-guide/[slug] routes (static export)
- FieldGuideShell (sidebar, pager, keyboard nav) + FieldGuideContent
  (react-markdown to design tokens); light theme, site header retained
- Footer "Brand Guidelines" group and nav Explore > Resources links
- sitemap, routes constant, i18n metadata, loader/integrity tests

Closes #65
This commit is contained in:
jinhojang6
2026-06-30 02:29:00 +09:00
committed by Jinho Jang
parent 692dbffe8d
commit 78619e28dc
35 changed files with 1795 additions and 3 deletions
@@ -0,0 +1,78 @@
import { notFound } from 'next/navigation'
import {
ContentNotFoundError,
flattenFieldGuideItems,
getFieldGuideChapter,
getFieldGuideManifest,
} from '@repo/content/loaders'
import { isActiveLocale } from '@repo/content/locales'
import { FieldGuidePageView } from '@/components/sections/field-guide'
import { ROUTES } from '@/constants/routes'
import { routing } from '@/i18n/routing'
import { createDefaultMetadata } from '@/lib/metadata'
const INDEX_SLUG = 'index'
export const dynamicParams = false
export async function generateStaticParams() {
const params: Array<{ locale: string; slug: string }> = []
for (const locale of routing.locales) {
if (!isActiveLocale(locale)) continue
const manifest = await getFieldGuideManifest(locale)
for (const item of flattenFieldGuideItems(manifest)) {
// The index chapter is served by the parent `/field-guide` route.
if (item.slug === INDEX_SLUG) continue
params.push({ locale, slug: item.slug })
}
}
return params
}
export async function generateMetadata({
params,
}: {
params: Promise<{ locale: string; slug: string }>
}) {
const { locale, slug } = await params
if (!isActiveLocale(locale)) {
throw new Error(`generateMetadata received non-active locale "${locale}"`)
}
const manifest = await getFieldGuideManifest(locale)
const item = flattenFieldGuideItems(manifest).find((it) => it.slug === slug)
const chapterTitle = item
? `${item.title}${manifest.title}`
: manifest.title
return createDefaultMetadata({
title: chapterTitle,
description: `${item?.title ?? manifest.title} — part of the ${manifest.title}.`,
locale,
path: ROUTES.fieldGuideChapter(slug),
})
}
export default async function FieldGuideChapterPage({
params,
}: {
params: Promise<{ locale: string; slug: string }>
}) {
const { locale, slug } = await params
if (!isActiveLocale(locale)) {
throw new Error(
`FieldGuideChapterPage received non-active locale "${locale}"`
)
}
try {
const [manifest, body] = await Promise.all([
getFieldGuideManifest(locale),
getFieldGuideChapter(locale, slug),
])
return <FieldGuidePageView manifest={manifest} slug={slug} body={body} />
} catch (error) {
if (error instanceof ContentNotFoundError) notFound()
throw error
}
}
@@ -0,0 +1,46 @@
import { getTranslations } from 'next-intl/server'
import {
getFieldGuideChapter,
getFieldGuideManifest,
} from '@repo/content/loaders'
import { isActiveLocale } from '@repo/content/locales'
import { FieldGuidePageView } from '@/components/sections/field-guide'
import { ROUTES } from '@/constants/routes'
import { createDefaultMetadata } from '@/lib/metadata'
const INDEX_SLUG = 'index'
export async function generateMetadata({
params,
}: {
params: Promise<{ locale: string }>
}) {
const { locale } = await params
const t = await getTranslations({ locale, namespace: 'pages.fieldGuide' })
return createDefaultMetadata({
title: t('title'),
description: t('description'),
locale,
path: ROUTES.fieldGuide,
})
}
export default async function FieldGuideIndexPage({
params,
}: {
params: Promise<{ locale: string }>
}) {
const { locale } = await params
if (!isActiveLocale(locale)) {
throw new Error(`FieldGuideIndexPage received non-active locale "${locale}"`)
}
const [manifest, body] = await Promise.all([
getFieldGuideManifest(locale),
getFieldGuideChapter(locale, INDEX_SLUG),
])
return <FieldGuidePageView manifest={manifest} slug={INDEX_SLUG} body={body} />
}
+16 -2
View File
@@ -1,6 +1,12 @@
import type { MetadataRoute } from 'next'
import { getAllIdeas, getAllRfps, getCircles } from '@repo/content/loaders'
import {
flattenFieldGuideItems,
getAllIdeas,
getAllRfps,
getCircles,
getFieldGuideManifest,
} from '@repo/content/loaders'
import siteConfig from '@/constants/site-config'
import { ROUTES } from '@/constants/routes'
@@ -41,6 +47,7 @@ const staticIndexableRoutes = [
ROUTES.activistLeaderSteward,
ROUTES.coalitionPartner,
...(ROUTE_AVAILABILITY.about ? [ROUTES.about] : []),
ROUTES.fieldGuide,
] as const
const buildSitemapEntry = (
@@ -57,12 +64,18 @@ const buildSitemapEntry = (
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const lastModified = new Date().toISOString().split('T')[0]!
const [rfps, ideas, circles] = await Promise.all([
const [rfps, ideas, circles, fieldGuide] = await Promise.all([
getAllRfps({ locale: 'en', status: 'published' }),
getAllIdeas({ locale: 'en', status: 'published' }),
getCircles({ locale: 'en', status: 'published' }),
getFieldGuideManifest('en'),
])
// Index chapter is served by ROUTES.fieldGuide (already in the static list).
const fieldGuideChapters = flattenFieldGuideItems(fieldGuide)
.filter((item) => item.slug !== 'index')
.map((item) => ROUTES.fieldGuideChapter(item.slug))
const routes = [
...staticIndexableRoutes,
...rfps.map((rfp) => `${ROUTES.rfps}/${rfp.slug}`),
@@ -70,6 +83,7 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
...(ROUTE_AVAILABILITY.circleDetailLinks
? circles.map((circle) => ROUTES.circle(circle.slug))
: []),
...fieldGuideChapters,
]
return [...new Set(routes)]
@@ -0,0 +1,120 @@
import Markdown, { type Components } from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { Link } from '@/i18n/navigation'
/**
* Renders a Field Guide chapter body (Markdown) with the Logos reading
* typography. Each Markdown element maps to the design system's tokens so the
* ported guide matches the site's look. Internal links (starting with "/")
* route through the i18n `Link`; external links open in a new tab.
*
* Pure render, no client state — safe to render on the server and pass as
* children into the client `FieldGuideShell`.
*/
const isInternalHref = (href: string | undefined): href is string =>
typeof href === 'string' && href.startsWith('/')
const components: Components = {
h1: ({ children }) => (
<h1 className="text-h2 mt-0 w-full text-brand-dark-green">{children}</h1>
),
h2: ({ children }) => (
<h2 className="text-h4-serif mt-8 w-full text-brand-dark-green">
{children}
</h2>
),
h3: ({ children }) => (
<h3 className="text-subhead-serif mt-6 w-full text-brand-dark-green">
{children}
</h3>
),
p: ({ children }) => (
<p className="text-body-sans leading-relaxed text-brand-dark-green">
{children}
</p>
),
ul: ({ children }) => (
<ul className="text-body-sans list-disc space-y-2 pl-5 text-brand-dark-green">
{children}
</ul>
),
ol: ({ children }) => (
<ol className="text-body-sans list-decimal space-y-2 pl-5 text-brand-dark-green">
{children}
</ol>
),
li: ({ children }) => <li className="leading-relaxed">{children}</li>,
blockquote: ({ children }) => (
<blockquote className="text-subhead-serif border-l-2 border-brand-dark-green pl-4 text-brand-dark-green italic">
{children}
</blockquote>
),
table: ({ children }) => (
<div className="w-full overflow-x-auto">
<table className="text-body-sans w-full border-collapse text-left text-brand-dark-green">
{children}
</table>
</div>
),
thead: ({ children }) => (
<thead className="border-b border-brand-dark-green/30">{children}</thead>
),
th: ({ children }) => (
<th className="text-eyebrow px-3 py-2 align-top font-semibold">
{children}
</th>
),
td: ({ children }) => (
<td className="border-b border-brand-dark-green/10 px-3 py-2 align-top">
{children}
</td>
),
hr: () => <hr className="border-brand-dark-green/20" />,
code: ({ children }) => (
<code className="rounded bg-gray-01 px-1 py-0.5 font-mono text-[0.9em]">
{children}
</code>
),
strong: ({ children }) => (
<strong className="font-medium">{children}</strong>
),
a: ({ href, children }) => {
if (isInternalHref(href)) {
return (
<Link
href={href}
className="underline underline-offset-2 transition-opacity hover:opacity-60"
>
{children}
</Link>
)
}
return (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
className="underline underline-offset-2 transition-opacity hover:opacity-60 [overflow-wrap:anywhere]"
>
{children}
</a>
)
},
}
interface FieldGuideContentProps {
/** Raw Markdown chapter body. */
body: string
}
export function FieldGuideContent({ body }: FieldGuideContentProps) {
return (
<div className="flex w-full flex-col gap-4">
<Markdown remarkPlugins={[remarkGfm]} components={components}>
{body}
</Markdown>
</div>
)
}
@@ -0,0 +1,57 @@
import type { FieldGuideManifest } from '@repo/content/schemas'
import { ROUTES } from '@/constants/routes'
import { FieldGuideContent } from './field-guide-content'
import { FieldGuideShell } from './field-guide-shell'
const slugToHref = (slug: string): string =>
slug === 'index' ? ROUTES.fieldGuide : ROUTES.fieldGuideChapter(slug)
interface FieldGuidePageViewProps {
manifest: FieldGuideManifest
slug: string
body: string
}
/**
* Server view shared by the `/field-guide` index route and the
* `/field-guide/[slug]` chapter route. Resolves the current chapter's
* page-reference and prev/next links from the manifest order, then renders the
* client reading shell around the Markdown content.
*/
export function FieldGuidePageView({
manifest,
slug,
body,
}: FieldGuidePageViewProps) {
const flat = manifest.sections.flatMap((section) => section.items)
const index = flat.findIndex((item) => item.slug === slug)
const current = flat[index]
if (!current) {
throw new Error(`field guide chapter "${slug}" missing from manifest`)
}
const prevItem = index > 0 ? flat[index - 1] : null
const nextItem = index < flat.length - 1 ? flat[index + 1] : null
return (
<FieldGuideShell
sections={manifest.sections}
currentSlug={slug}
pageRef={{ num: current.num, title: current.title }}
prev={
prevItem
? { href: slugToHref(prevItem.slug), title: prevItem.title }
: null
}
next={
nextItem
? { href: slugToHref(nextItem.slug), title: nextItem.title }
: null
}
>
<FieldGuideContent body={body} />
</FieldGuideShell>
)
}
@@ -0,0 +1,197 @@
'use client'
import clsx from 'clsx'
import { type ReactNode, useEffect, useState } from 'react'
import type { FieldGuideSection } from '@repo/content/schemas'
import ContentWidth from '@/components/layout/content-width'
import { Link, useRouter } from '@/i18n/navigation'
interface PagerLink {
href: string
title: string
}
interface FieldGuideShellProps {
sections: FieldGuideSection[]
currentSlug: string
/** Page-reference label parts, e.g. `07 · The Four Checks`. */
pageRef: { num: string; title: string }
prev: PagerLink | null
next: PagerLink | null
children: ReactNode
}
const slugToHref = (slug: string): string =>
slug === 'index' ? '/field-guide' : `/field-guide/${slug}`
/**
* The Field Guide reading layout: a chapter sidebar, the chapter body, and a
* prev/next pager. Ported from the reference guide's chrome but stripped to the
* site's light theme (no theme toggle / GitHub / print). The global site header
* still wraps the page.
*/
export function FieldGuideShell({
sections,
currentSlug,
pageRef,
prev,
next,
children,
}: FieldGuideShellProps) {
const router = useRouter()
const [isSidebarOpen, setIsSidebarOpen] = useState(false)
// Close the mobile sidebar whenever the chapter changes.
useEffect(() => {
setIsSidebarOpen(false)
}, [currentSlug])
// ←/→ navigate chapters; Esc closes the mobile sidebar. Ignored while a form
// control is focused so typing isn't hijacked.
useEffect(() => {
const onKeyDown = (event: KeyboardEvent) => {
const target = event.target as HTMLElement | null
if (target && /^(INPUT|TEXTAREA|SELECT)$/.test(target.tagName)) return
if (event.key === 'Escape') {
setIsSidebarOpen(false)
return
}
if (event.key === 'ArrowLeft' && prev) router.push(prev.href)
if (event.key === 'ArrowRight' && next) router.push(next.href)
}
window.addEventListener('keydown', onKeyDown)
return () => window.removeEventListener('keydown', onKeyDown)
}, [prev, next, router])
return (
<ContentWidth className="py-8 xl:py-12">
{/* Mobile chapter bar */}
<div className="flex items-center gap-3 xl:hidden">
<button
type="button"
onClick={() => setIsSidebarOpen(true)}
className="text-eyebrow inline-flex items-center gap-2 rounded-xl bg-gray-01 px-3 py-2 text-brand-dark-green"
aria-label="Open chapter list"
>
<span aria-hidden="true"></span> Chapters
</button>
<span className="text-mono-s text-brand-dark-green/70">
{pageRef.num} · {pageRef.title}
</span>
</div>
<div className="flex flex-col items-start gap-3 xl:flex-row xl:gap-24">
{/* Sidebar — backdrop + slide-in on mobile, static column on desktop */}
{isSidebarOpen && (
<button
type="button"
aria-label="Close chapter list"
onClick={() => setIsSidebarOpen(false)}
className="fixed inset-0 z-40 bg-brand-dark-green/30 xl:hidden"
/>
)}
<nav
aria-label="Field Guide chapters"
className={clsx(
'flex w-72 shrink-0 flex-col gap-6 self-start bg-brand-off-white',
'max-xl:fixed max-xl:inset-y-0 max-xl:left-0 max-xl:z-50 max-xl:overflow-y-auto max-xl:p-6 max-xl:shadow-xl max-xl:transition-transform',
isSidebarOpen ? 'max-xl:translate-x-0' : 'max-xl:-translate-x-full',
'xl:sticky xl:top-12 xl:w-56.5 xl:py-4'
)}
>
{sections.map((section) => (
<div key={section.section} className="flex flex-col gap-2">
<p className="text-eyebrow text-brand-dark-green/50">
{section.section}
</p>
<ul className="flex flex-col gap-1">
{section.items.map((item) => {
const isActive = item.slug === currentSlug
return (
<li key={item.slug}>
<Link
href={slugToHref(item.slug)}
aria-current={isActive ? 'page' : undefined}
className={clsx(
'flex items-baseline gap-2 transition-opacity hover:opacity-60',
isActive
? 'text-eyebrow text-brand-dark-green'
: 'text-mono-s text-brand-dark-green/80'
)}
>
<span className="text-brand-dark-green/40">
{item.num}
</span>
<span>{item.title}</span>
</Link>
</li>
)
})}
</ul>
</div>
))}
</nav>
{/* Main column */}
<article className="flex w-full max-w-3xl flex-col gap-6 pb-16 xl:py-4">
<p className="text-eyebrow hidden text-brand-dark-green/50 xl:block">
{pageRef.num} · {pageRef.title}
</p>
{children}
{/* Pager */}
<nav
aria-label="Chapter navigation"
className="mt-8 flex items-stretch justify-between gap-4 border-t border-brand-dark-green/15 pt-6"
>
{prev ? (
<Link
href={prev.href}
rel="prev"
className="flex flex-col gap-1 text-left transition-opacity hover:opacity-60"
>
<span className="text-eyebrow text-brand-dark-green/50">
Previous
</span>
<span className="text-body-sans text-brand-dark-green">
{prev.title}
</span>
</Link>
) : (
<span className="flex flex-col gap-1 text-left opacity-40">
<span className="text-eyebrow text-brand-dark-green/50"></span>
<span className="text-body-sans text-brand-dark-green">
Start of guide
</span>
</span>
)}
{next ? (
<Link
href={next.href}
rel="next"
className="flex flex-col items-end gap-1 text-right transition-opacity hover:opacity-60"
>
<span className="text-eyebrow text-brand-dark-green/50">
Next
</span>
<span className="text-body-sans text-brand-dark-green">
{next.title}
</span>
</Link>
) : (
<span className="flex flex-col items-end gap-1 text-right opacity-40">
<span className="text-eyebrow text-brand-dark-green/50"></span>
<span className="text-body-sans text-brand-dark-green">
End of guide
</span>
</span>
)}
</nav>
</article>
</div>
</ContentWidth>
)
}
@@ -0,0 +1,3 @@
export { FieldGuideShell } from './field-guide-shell'
export { FieldGuideContent } from './field-guide-content'
export { FieldGuidePageView } from './field-guide-page-view'
+3
View File
@@ -74,6 +74,9 @@ export const ROUTES = {
// Footer misc
brandKit: '/brand-kit',
fieldGuide: '/field-guide',
/** Dynamic route — `/field-guide/[slug]`. */
fieldGuideChapter: (slug: string) => `/field-guide/${slug}`,
// Design system reference (internal)
designSystems: '/design-systems',
+4
View File
@@ -1027,6 +1027,10 @@
"guidelinesHref": "/brand-kit/logos-brand-guidelines.pdf"
}
},
"fieldGuide": {
"title": "Field Guide | Logos",
"description": "The Logos Field Guide: how to build, communicate, and participate in the Logos movement — beliefs, practices, and expression."
},
"connect": {
"title": "Let's Connect | Logos",
"description": "Be part of what's unfolding. Receive updates on progress, gatherings and opportunities to contribute.",
+44
View File
@@ -0,0 +1,44 @@
# Credo
> Build the parallel. Prove it in practice. Keep it human.
## What the Credo means
**Build the parallel:** where existing systems fail, we build alternatives.
**Prove it in practice:** show the work. Code, prototypes, problems solved, events hosted. We measure by what was built, shipped, and used by others.
**Keep it human:** our technology is a catalyst. The work lives in real places and serves real people and communities.
## Stories
Stories are how we communicate the Credo. They are told by everyone through Circles, field notes, social media, gatherings, IRL events, and word of mouth. The story of Logos is the story of society failing its people and the parallel society we build in its place.
## Codes
Codes are actions we take to reinforce the Credo. For example:
- The lambda (λ) in handles, commits, terminals, and signatures signals belonging.
- Repetition of the Credo or the call to action signals alignment.
- A ring of chairs in a Circle with no head signals peers, not rank.
- Gathering in person rather than online signals that human relationships are the priority.
## Call to action
The CTA gives the movement a clear, memorable signal.
> Build the parallel.
## Contributor bridges
Contributor bridges are phrases that move people from passive support into active contribution.
> Tools not permission.
>
> Action not permission.
## The Four Checks
The Four Checks are a quick way to assess whether the work you are doing supports Logos.
> Build. Protect. Share. Belong.
@@ -0,0 +1,107 @@
# Cultural Lanes
This is how Logos stays a culture, not a process:
- **Beliefs:** what we hold to be true.
- **Practices:** what we do regularly to uphold those truths.
- **Norms:** what gets enforced to avoid drift.
Practices and norms evolve, while beliefs do not.
Note: These lanes are not demographics; there is no fundamental split between co-contributors and core contributors, or between technical and non-technical.
## Technical
For protocol builders, app developers, cryptographers, researchers, node operators, technical writers, auditors, maintainers, and co-developers in the movement.
### Beliefs
- Logos sovereignty is fundamental; platform dependency undermines it.
- Privacy is a precondition for the mission, not a feature toggle.
- Open source is not a preference, it is a mode of thinking and relating to others.
- Software's longevity is extended via modularity. Every component should be usable, extendable, and forkable.
- Politics is downstream from infrastructure. What we make possible, or impossible, is the argument.
- Shipping code is not the finish line. "Done" means software is in someone's hands.
### Practices
- Working in the open by default: issues, pull requests, and decisions visible.
- Giving co-developers communication paths and frameworks that respect their privacy.
- Documenting properly to get our co-developers started.
- Working with co-developers in the open: debugging together, mentoring newcomers, reviewing PRs promptly, crediting by handle.
- Dogfooding what we build regularly, in real conditions, with other members of the movement.
- Shipping in small, steady increments rather than batched releases.
- Writing the specification alongside the implementation, not after. A protocol without a clear spec is incomplete, no matter how good the code is.
### Norms
- Read documentation and use existing tooling before reaching out. Exhaust your own means first.
- Keep contributions laser focused: modular, well-tested code that solves a specific, user-backed problem is the goal.
- Point out problems and gaps. A well-documented issue that defines a problem is a contribution.
- Favour minimal claims and testable demos.
- Do not confuse roadmaps with shipped reality.
- Verify before amplifying.
- Let contribution outrank credentials.
## Non-technical
For local organisers, Circle stewards, civic groups, educators, advocacy partners, community hosts, civil-liberties allies, and people building parallel institutions in the real world.
### Beliefs
- We build better alternatives instead of fighting to fix legacy systems.
- The parallel society only works with a self-sufficient parallel economy.
- Better systems are possible when people coordinate together to regain agency.
- Technology becomes useful when it solves real-world problems.
- Lasting change needs a culture of civic duty, not just good tools.
- Community is a result, not a strategy.
### Practices
- Forming self-funded Circles to organise communities to build parallel institutions.
- Winning small, documenting the win, publishing guidance others can follow.
- Teaching peers skills so newcomers become contributors.
- Publishing field notes after each session.
- Committing to follow-up actions with named owners.
- Telling and sharing stories in person or online.
### Norms
- For every collective activity, a field note on the [Forum](https://forum.logos.co/) for others to learn from.
- Privacy is the default. Always ask people for consent to show their face. If not, blur.
- Open every session by stating the privacy posture.
- Preserve economic sovereignty; do not build dependency on external funds.
- No one speaks for the whole movement, only for their own work.
- Guiding the room or a Circle means offering orientation rather than authority.
## Way of life
For all of us. Culture makes the parallel society somewhere people actually want to live; it is the glue that binds us together.
### Beliefs
- Life in the parallel society must be human, warm, meaningful, and IRL.
- Human connection is our immune system. Nobody sticks with something they don't enjoy.
- A movement with no art or music is just a meeting.
- Association is more valuable than knowledge.
- Direct connection beats mediation.
- Isolated people are easy to capture. Connected people are not.
### Practices
- Shared meals at no-phone tables.
- Making art and music together, or hosting events for others to enjoy.
- Walk-and-talks instead of screen meetings.
- Self-improvement and mental hygiene.
- Sports and dance for discipline and communion.
- Deep conversation over small talk.
- Right-to-repair and maker workshops.
- Making and sharing memes that align the culture.
### Norms
- No VIP theatre.
- No influencer capture.
- No turning people into content.
- No forced intimacy or compulsory disclosure.
- No phones on the dancefloor.
@@ -0,0 +1,35 @@
# Eight Truths
These are strategic truths that govern the direction of Logos. They are distinct from the [Four Checks](/field-guide/four-checks) (which govern daily output). The Eight Truths govern the long view.
## 1\. Logos builds sovereign infrastructure
For private coordination, civil society, and credible autonomy. If it drifts into lifestyle, spectacle, or financial speculation, it has failed.
## 2\. One stack, one language
Blockchain, Messaging, Storage, and Circles must feel like one system without flattening what each does.
## 3\. Surveillance is the precursor to force
Privacy is defence, not preference. Without it, every other freedom is conditional.
## 4\. Technical and non-technical build together
Technical and non-technical are operating contexts, not audiences ranked by importance. A protocol that only ships software is half built, a movement that only hosts events is half real.
## 5\. Circles are proof
They are how the parallel society gets implemented: self-funded, working solutions to real issues, not community theatre or meetups that lead to no action.
## 6\. Building is the argument
Our response to cheap cynicism is not blind positivity. It is optimism grounded in tools that work and people who take action.
## 7\. Learn, adapt, reproduce, or die
Reproduce what works. Measure by follow-up, not impressions.
## 8\. Sovereignty is economic
A community that depends on central funds is someone else's project. The parallel society generates its own business.
+131
View File
@@ -0,0 +1,131 @@
# Events
An "As Logos" event is a working space, not a brand activation. People come to learn, build, connect, or leave with something they did not have before. Indoors or on the street, the event states its privacy posture, runs hands-on work in the open, and looks like a movement at work.
This page is the kit for planning one. Each event space is built from zones (its functional areas), the items inside them, and is one of three sizes. Event types come first, then the zones and how they scale.
## Event types
Each event type sets three things: its name format, the zones it builds from by default, and the guidance it follows.
| Name format | What it is | Mode | Minimum zones |
| --- | --- | --- | --- |
| Parallel Society \[year\] | Annual flagship. The full system in one space. | Standalone | All seven |
| Logos LAN / \[City\] | Workshops, developer zones, hackspaces, build sessions. | Standalone or adjunct hosted inside another event (e.g. Dark Prague) | Threshold, Table, Wall |
| Logos Circle / \[City\] | Flat conversation format. Runs the Circle format. | Standalone | Threshold, Circle |
| Logos Pop-Up Circle / \[City\] | One-time Circle for spreading the concept of Circles and recruiting volunteers and stewards. | Adjunct to a larger event (e.g. Devconnect) | Circle only |
| Logos Action Not Permission / \[City\] | One-time local activist initiative, built around a Circle. | Standalone or adjunct to event or Circle | Variable |
## Zones
Seven zones make up the physical layer for each event, each holding a set of items. A smaller event might use three zones and a couple of items, while a large one uses all of them. How many zones you use scales with the event, while the operating principles stay the same.
Example layout, full size. [Download](assets/img/event-zone-system.png).
| Zone | Purpose | Items |
| --- | --- | --- |
| **Threshold** | Entry, orientation, consent | Welcome Table, A-Frame Sign, Card Rack, Privacy Poster, Lambda Way Finding |
| **Table** | Hands-on work, building, debugging | Install Table, Debug Station, Power Spine, Screen |
| **Wall** | Display, reading, print distribution | Display Surface, Field Notes Board, Print Table |
| **Circle** | Flat conversation, no hierarchy | Circle Seating |
| **Stage** | Presentations, talks, demos | Stage Platform, Audience Seating |
| **Kitchen** | Shared meal, no phones, no pitching | Communal Table, Prep + Drinks |
| **Quiet** | Reading, writing, 1:1 conversation | Reading Nook, Writing Desks, 1:1 Conversation |
## Items
Twenty numbered items make up the full kit. Each belongs to exactly one zone.
### Threshold
| # | Item | Dimensions | Description |
| --- | --- | --- | --- |
| 1 | Welcome Table | W1200 × D600 mm | Trestle or folding table, entry zone |
| 2 | A-Frame Sign | W600 × D400 mm | Double-sided, privacy rules, directions/way finding |
| 3 | Card Rack | W600 × D400 mm | Zines, setup cards, field note blanks |
| 4 | Privacy Poster | W420 × D594 mm | A2 printed, posted at every entrance |
| 20 | Lambda way finding | 200 mm ø | Floor sticker or hanging mark |
### Table
| # | Item | Dimensions | Description |
| --- | --- | --- | --- |
| 5 | Install Table | W2400 × D600 mm | Long bench, power for laptops, 4 stations |
| 6 | Debug Station | W1200 × D600 mm | Monitor + bench, 2 seats |
| 7 | Power Spine | W100 × L9600 mm | Central cable tray, floor-mounted |
| 8 | Screen | W2400 × D200 mm | Monitor or projection surface |
### Wall
| # | Item | Dimensions | Description |
| --- | --- | --- | --- |
| 9 | Display Surface | W2400 × D100 mm | Wall-mounted rail or ledge |
| 10 | Field Notes Board | W1200 × D900 mm | Pin board, A4 or A5 notes pinned |
| 11 | Print Table | W1800 × D700 mm | Cards, zines, handouts for taking |
### Circle
| # | Item | Dimensions | Description |
| --- | --- | --- | --- |
| 12 | Circle Seating | 3600 mm ø | Chairs in ring, no hierarchy, flat |
### Stage
| # | Item | Dimensions | Description |
| --- | --- | --- | --- |
| 13 | Stage Platform | W2400 × D1200 mm | Raised 200 mm, speaker + podium |
| 14 | Audience Seating | W2400 × D2400 mm | Rows of chairs, flat, no VIP |
### Kitchen
| # | Item | Dimensions | Description |
| --- | --- | --- | --- |
| 15 | Communal Table | W3000 × D900 mm | Long table, individual seats, shared meal, no phone zone. |
| 16 | Prep + Drinks | W2400 × D600 mm | Counter, fridge, bins |
### Quiet
| # | Item | Dimensions | Description |
| --- | --- | --- | --- |
| 17 | Reading Nook | W2400 × D1800 mm | Lounge chairs, bookshelf, quiet |
| 18 | Writing Desks | W1200 × D600 mm | Individual desks, wall-facing |
| 19 | 1:1 Conversation | W1800 × D1200 mm | Two chairs + low table, no capture |
## Sizes
Three standard sizes. Pick the one that fits your space and headcount, read what goes where, and build.
### Minimal
<table><tbody><tr><td><strong>Grid</strong></td><td>6 × 4 cells</td></tr><tr><td><strong>Dimensions</strong></td><td>7.2 m × 4.8 m</td></tr><tr><td><strong>Zones</strong></td><td>Threshold, Table, Wall</td></tr><tr><td><strong>Capacity</strong></td><td>1530 people</td></tr><tr><td><strong>Use</strong></td><td>Side event, meetup, single-space workshop</td></tr></tbody></table>
### Standard
<table><tbody><tr><td><strong>Grid</strong></td><td>10 × 8 cells</td></tr><tr><td><strong>Dimensions</strong></td><td>12 m × 9.6 m</td></tr><tr><td><strong>Zones</strong></td><td>All seven</td></tr><tr><td><strong>Capacity</strong></td><td>Approx. 50100 people</td></tr><tr><td><strong>Use</strong></td><td>Conference day, full workshop, community gathering</td></tr></tbody></table>
### Full
<table><tbody><tr><td><strong>Grid</strong></td><td>14 × 10 cells</td></tr><tr><td><strong>Dimensions</strong></td><td>16.8 m × 12 m</td></tr><tr><td><strong>Zones</strong></td><td>All seven, doubled stations</td></tr><tr><td><strong>Capacity</strong></td><td>Approx. 100300 people</td></tr><tr><td><strong>Use</strong></td><td>Multi-day event, large gathering, festival footprint</td></tr></tbody></table>
## Grid
All events use the event-industry grid. In most cases, that means one cell = approximately 1.2 m × 1.2 m, with some variation. This is the standard unit used by event production companies, marquee suppliers, and venue planners worldwide. Every item dimension is a multiple of this grid.
## Privacy protocol
Every event states our privacy posture before it begins. Print it, post it, say it out loud.
Template: [Event Privacy Protocol](/field-guide/event-privacy-protocol)
## Rules
These apply at every size:
1. **Privacy poster at every entrance.** Same format, every time.
2. **Lambda as way finding, not branding.** Small marks that say "you're in the right place" not banners.
3. **No sponsor logos or brand marks competing for wall space.**
4. **Manual feel.** Printed cards, handwritten maps, workshop tables. Avoid screens unless the work requires them.
5. **Signage looks like field documentation, not marketing collateral.**
6. **No VIP sections, no badge hierarchy, no speaker greenrooms.**
7. **Kitchen is a no-phone zone.** Shared meals build trust without extraction.
8. **Quiet zone has no content capture.** No cameras, no recording, no live broadcasting.
@@ -0,0 +1,42 @@
# Expression
The Credo, the Four Checks, and everything above live in the work, not in this guide. Expression is where Logos becomes tangible.
Every output we make is in one of two registers. The register is a property of the work, not of the person who makes it. This means registers are not ranks; the same contributor can produce outputs in both registers simultaneously.
| Register | What it applies to | What applies |
| --- | --- | --- |
| **As Logos** | The work ships on a Logos-owned channel, or is funded or commissioned by Logos. | The full system: visual tokens, voice, language rules, name formats, event kit |
| **For Logos** | Everything else made in or around the movement, by anyone. | The Four Checks |
When speaking as Logos, use the full system. When speaking for Logos, align with the [Four Checks](/field-guide/four-checks).
## The lambda
The lambda belongs to the movement. Draw it, print it, wear it, remix it. You do not need permission to use it. However, always remember that Logos outputs should be recognised by their substance, which is ensured by holding them up to the Four Checks.
## Making it ours without a rule book
When producing outputs in the "For Logos" register, there are no strict visual rules. However, work should stay recognisable in the way a tradition does, not the way a franchise does.
**The lineage:** Our aesthetic descends from traditions that are creative, resourceful, and break the status quo: think zine and xerox culture, early internet aesthetics, ASCII art, videogames, 3D printing, repair cafes, and field documentation, among others. If the work sits naturally in that lineage and follows the Four Checks, it will read as Logos.
If in doubt, consider the following:
- Manual, not glossy.
- Infrastructure, not consumer app.
- Tools, not toys.
- Field documentation, not marketing collateral.
- Way-finding, not decoration.
The tokens, type, and palette in the [Visual System](/field-guide/visual) are available if you find them useful. Using them can help to align your outputs with Logos' visual identity but is not strictly necessary.
## The contexts
Whatever the register, expressions fall into three potentially overlapping contexts. The examples are for guidance and not a complete list.
| Context | What it covers | Examples |
| --- | --- | --- |
| **Comms** | Language, design assets, campaigns | Social posts, blog posts, web copy, field notes, agency briefs, this guide |
| **Artefacts** | Software, tools, platforms, interfaces | Logos Basecamp, stack modules, EcoDev outputs, logos.co, repos |
| **IRL** | Events, spaces, printed matter, signage | Workshops, Circles, privacy rules, zines, brochures |
@@ -0,0 +1,66 @@
# The Four Checks
These four checks are how you prove your work in practice. If any check fails, align before shipping the output.
> Build. Protect. Share. Belong.
## Build
Did we make something useful?
Examples:
- Functional code in someone's hands.
- A self-funded Circle activity.
- A release or merged contribution.
- A winnable issue solved.
- A micro-institution doing real work.
- A guide or documentation someone can follow.
- A working setup: a wallet, a node, a knowledge graph.
- An explainer video someone can learn from.
- A contribution path for running a node or hosting an event.
## Protect
Did we protect people, privacy, and the mission?
Check:
- No work that breaks the Credo.
- No faces, names or unnecessary doxing without consent.
- No framing Logos as a brand, product, ecosystem, or campaign.
- No leader the work can't survive without.
- No slide into reform-from-within or escapism.
- No drift into lifestyle or spectacle.
- No vague privacy claims without procedure.
- No vague censorship-resistance claims without procedure.
## Share
Did we leave something others can use?
Good outputs leave behind:
- A documented fix others can apply.
- A sanitised field note, published on the [Forum](https://forum.logos.co/).
- An issue reported, not just discovered and ignored.
- A playbook for an activity another Circle can run as-is.
- A tactic that worked, with a well documented post-mortem.
- A clear route to contribution, not a dead end.
- A contact path for someone to reach out if needed.
- A translation that widens access.
## Belong
Did we make it recognisably ours?
Marks of belonging:
- Building and discussing in the open, as much as possible.
- Using language that does not distinguish between builders and users.
- The lambda used where the work happens, not as decoration.
- The Credo or the call to action: "Build the parallel".
- Outputs with enough substance that they still read as Logos even without the lambda.
- A Circle running its own node or dogfooding Logos technologies.
- Making things that are functional, not glossy. Tools, not toys.
- Outputs should sit in Logos' cultural lineage.
@@ -0,0 +1,95 @@
# Glossary
Terms used across the field guide. Use these consistently.
### Artefact
A built surface: a website, tool, dashboard, or hub. One of the three expression contexts, along with Comms and IRL.
### Circle
A local, self-organising group that takes action on real issues where its members live. How the parallel society gets implemented: self-funded, working solutions, not meetups or community theatre. Flat by design, peers not rank.
### Contribution path
Every public surface must point toward work. A page without a contribution path is incomplete.
### Contributor bridges
Phrases that move people from passive support into active contribution: "Tools not permission." / "Action not permission."
### Credo
Build the parallel. Prove it in practice. Keep it human. The three-line statement of what Logos does.
### Cypherpunk
Someone who defends privacy and freedom in practice, by building, running, teaching, and using the tools rather than by rhetoric. A practice, not an identity or costume.
### Field note
A sanitised account of what happened, what was learned, and what comes next. Published when safe.
### Four Checks
Build. Protect. Share. Belong. The quick test of whether an output supports Logos. Run before shipping.
### Lambda
The operator mark. Used where work happens: usernames, terminal prompts, patches, field manuals. Not decoration.
### Legacy names
Older docs, repos, or historical references may use Nomos, Waku, or Codex. Use current Logos module names in new public-facing work. See Stack language under Language.
### Logos Basecamp
The user-facing, local-first launcher for the Logos stack. Runs every module on self-controlled hardware from one interface.
### Logos Blockchain
The privacy-preserving blockchain module. Previously known as Nomos.
### Logos Core
The modular, plugin-based runtime that lets developers build private apps which discover and load the stack modules they need.
### Logos Messaging
The private peer-to-peer communication module. Previously part of Waku.
### Logos stack
The unified modular stack that includes Logos Blockchain, Logos Messaging, Logos Storage, and supporting runtime components.
### Logos Storage
The decentralised storage module. Formerly known as Codex.
### Parallel economy
The self-sustaining economic activity of the parallel society: businesses and value created independent of the existing system, so communities never depend on central funds.
### Parallel society
What Logos builds: sovereign institutions, sound money, and civic virtue, made outside the existing order rather than reforming it from within.
### Privacy posture
The stated rules for a space, event, or output: what is recorded, what requires consent, what is blurred by default, what is not shared. Operational, not decorative.
### Register
Whether work is As Logos (ships on a Logos channel or is funded or commissioned by Logos, and follows the full system) or For Logos (everything else, follows the Four Checks). A property of the work, not the person.
### Way of life
Logos as embodied operating culture, not taste or costume. The shared practice that brings every expression back to autonomy, fellowship, skill, privacy, and contribution.
### Winnable issue
A real, solvable local problem a Circle takes on to create agency and build legitimacy.
### Zones
The seven functional areas an event space is built from: Threshold, Table, Wall, Circle, Stage, Kitchen, and Quiet. How many you use scales with the event, the principles stay the same.
@@ -0,0 +1,50 @@
# How Logos Works
Logos puts together a technology stack and a social movement to form a parallel society.
The stack provides the infrastructure: decentralised, private-by-default tools for communication, storage, and coordination. The movement builds local institutions on the stack and encourages community organisation and action, problem solving, skill building, mutual aid, and a culture of civic duty.
In this way, Logos produces:
- **Sovereign individuals**: free to think, speak, transact, and exit without permission.
- **Sound money**: free from debasement and financial censorship, supporting a growing parallel economy.
- **Private coordination**: revealing oneself becomes a real choice, protecting free association.
- **Healthy communities**: full of purpose and capable of solving their own problems.
- **A culture of civic virtue**: people of enough moral character to sustain what they build.
## What the stack includes
- **Logos Blockchain**: privacy-preserving, decentralised compute and consensus.
- **Logos Messaging**: private, censorship-resistant communication between parties.
- **Logos Storage**: privacy-preserving file sharing and retrieval using content-addressed data, enabling distributed storage.
- **Logos Basecamp**: the user-facing, local-first launcher for the Logos stack, running all modules on self-controlled hardware from a unified interface.
- **Logos Core**: a modular, plugin-based runtime to enable developers to build decentralised, privacy-preserving apps that dynamically discover and load the modules they need.
Note: These are not products competing for market share. They are infrastructure for people who need secure channels for coordination and do not trust existing platforms to provide them.
Older documentation and repos may refer to these modules by their legacy names: Nomos (Blockchain), Waku (Messaging), and Codex (Storage). See [Stack Language](/field-guide/language) for details.
## What the social movement does
The social movement builds the things people need as the system fails: a community that supports them, the agency to solve their own problems, and sovereign technology to act with. Together, they seed institutions and an economy independent of the old order. This is done through:
- **Circles**: local, self-organising groups taking action on issues that matter.
- **Winnable issues**: real problems solved to create agency and build legitimacy.
- **The Logos stack**, which ensures communities and what they build remain sovereign.
- **Economic activity** that makes the parallel society self-sustaining.
- **Coalitions** with aligned organisations to share knowledge, resources, and capacity.
- **Skill building** that grows newcomers into capable contributors.
- **Human connections** that regenerate a sense of belonging and purpose.
- **Civic duty** practised through service, integrity, and self-reliance.
For a full breakdown of how the social movement works, see [logos.co/movement](https://logos.co/movement).
## Why privacy?
Privacy is the condition that makes free association possible.
Free association is the condition that makes civil society possible.
Civil society cannot thrive on infrastructure designed for surveillance, coercion, and extraction.
Privacy is a requirement, not a philosophical position or a feature.
+47
View File
@@ -0,0 +1,47 @@
# Logos Field Guide
Logos is a movement to build a parallel society grounded in sovereign institutions, sound money, and civic virtue. We bring people together to find solutions where the existing system fails.
Our tools and communities do not merely signal privacy, autonomy, and liberty, but actively enhance our ability to live them, free from capture.
> Build the parallel. Prove it in practice. Keep it human.
## The Four Checks
Use the following checklist to determine whether what you produced supports the mission. If it does not build, protect, share, or belong, adapt or reconsider it.
| Check | Question |
| --- | --- |
| **Build** | Did we make something useful? |
| **Protect** | Did we protect the mission? |
| **Share** | Did we leave something others can use? |
| **Belong** | Did we make it recognisably ours? |
### How to use this guide
This guide is for anyone making, publishing, building, designing, or shipping anything under Logos. It is a living document, subject to revision and updates. Always check that your outputs align with the latest version.
Remember, this is a cultural guide for alignment, not a compliance manual. It is not headquarters issuing commands.
## Start here
| Need | Go to |
| --- | --- |
| I am new to Logos | [How Logos Works](/field-guide/how-logos-works) |
| I want to know why Logos exists | [Why Logos?](/field-guide/why-logos) |
| I want to know what Logos is not | [What Logos Is Not](/field-guide/what-logos-is-not) |
| I want to know who Logos is for | [Who Logos Is For](/field-guide/who-logos-is-for) |
| I want to understand Logos' values | [Eight Truths](/field-guide/eight-truths) |
| I want to know what we stand for | [Credo](/field-guide/credo) |
| I need the high-level rules | [The Four Checks](/field-guide/four-checks) |
| I need guidance for my place in the movement | [Cultural Lanes](/field-guide/cultural-lanes) |
| I am making something | [Expression](/field-guide/expression) |
| I am communicating as Logos | [The Full System](/field-guide/the-full-system) |
* * *
## Keyboard shortcuts
- Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters.
- Press <kbd>?</kbd> to show this help.
- Press <kbd>Esc</kbd> to close any open menu.
@@ -0,0 +1,98 @@
# Language
## Voice
How Logos sounds in writing when communicating in the "As Logos" register.
- **Declarative:** We make statements, not suggestions. No hedging.
- **Sparse:** Every word earns its place. No filler, no repetition.
- **Precise:** We name things concisely and carefully. Vague language is a failure of thinking.
- **Dry:** Wit exists but is understated. We never wink at the camera.
## House phrases
Public slogans. Use regularly:
- Build the parallel.
- The parallel is built, not announced.
- Start where you live.
- Privacy is a civic primitive.
- Private by default. Built for real life.
- Run what you depend on.
- Prove it in code.
- Global protocols. Local action.
- Coordination without surveillance.
- Civil society needs private infrastructure.
- Free association needs private communication.
- Tools not permission.
- Freedom, not costume.
- Proof, not hype.
- Contribution, not status.
- No label required.
## Operating verbs
The work loop, in plain imperatives:
- Run the tools.
- Verify the claim.
- Publish the field note.
- Close with commits.
- Make peers more capable.
## Avoid
### Marketing hype
- Next generation of human freedom
- Unlock the future / limitless anything
- Empower communities
- Revolutionary / groundbreaking / world-class / best-in-class (without proof)
- Privacy revolution (unless explaining the mechanism)
- Join the revolution
- Seamless experience
- Unstoppable future
- Redefine web3 (web3 as an identity marker)
- Vibrant ecosystem
- Community (as a decorative noun)
- Trustless community
- Onboarding the masses
### Tribalism and cosplay
- Cheerful outlaw
- Privacy lifestyle as costume
- Cyberpunk vibes
- Only for libertarians
- True believers only
- Join the tribe
- Follow the leader
- Crush the enemy
- The chosen few
## Rewrite examples
| Weak | Better |
| --- | --- |
| Empowering the next generation of decentralised communities | Building tools for people deploying private, voluntary institutions |
| Revolutionary technology for human freedom | Private messaging, storage, transactions, and governance for civil society |
| Join the movement | Run a node. Join a Circle. Build an app. Host a session. |
| Seamless web3 experience | A stack for private coordination, still experimental in places, ready for builders to test |
| The future of governance | Governance experiments with privacy, credible exit, and voluntary participation |
| Community-powered ecosystem | Contributors, Circles, builders, and operators maintaining shared infrastructure |
## Stack language
Use current Logos module names in public-facing work.
| Current name | Legacy name | Use legacy only when |
| --- | --- | --- |
| Logos Blockchain | Nomos | Referring to repo names, older docs, technical history, or migration context |
| Logos Messaging | Waku | Referring to legacy work, older docs, upstream history, or specific technical components |
| Logos Storage | Codex | Referring to repo names, older docs, technical history, or migration context |
### Do not write
- Waku/Codex/Nomos stack
- Logos Network State, unless quoting older material
- Codex, Waku, or Nomos as default public names
@@ -0,0 +1,8 @@
# Templates
These are ready-made starting points for the documents you might need to produce. Copy the one you need, replace the `{{ }}` placeholders with your details, and delete the italic guidance as you fill it in.
Two kinds for now:
- **Field note**: the write-up you post to the Forum after an event. One per event type.
- **Privacy protocol**: the poster you display at the entrance.
@@ -0,0 +1,7 @@
# The Full System
When the work ships on a Logos official channel, or under the Logos name, it must follow full system guidance for the "As Logos" register. This includes:
- Visual.
- Language.
- Spaces & Events.
+80
View File
@@ -0,0 +1,80 @@
# Visual
When we build an Artefact (a website, a tool, a dashboard, a hub) in the "As Logos" register, it should look like it belongs to the same family as [logos.co](https://logos.co/). Not identical but unmistakably the same system. One system covers everything: Artefacts, Comms (social cards, decks, printed matter), and print.
## The source
The system is authored in Figma. From it we generate one file that every surface imports:
```
logos-design/assets/tokens.css
```
Tokens are never hard coded: to change one, update Figma first, then regenerate tokens.css.
- **Figma file**: `4Rsufbuu6KjR1cab3eq063`
- **Guidelines file**: `logos-guidelines-figma` repo, components, frames, screenshots
- **Design reference**: `logos-design` repo, colour, typography, marks, art direction, playground
It contains:
### Colour
| Token | Value | Use |
| --- | --- | --- |
| `--c-ink` | `#152521` | Default text, canvas ground (dark mode) |
| `--c-paper` | `#f5f5ef` | Background, foreground on dark |
| `--c-signal` | `#ffd328` | CTAs, highlights, interactive accent |
| `--c-slate` | `#475651` | Body text on paper |
| `--c-fog` | `#dbddd7` | Borders, dividers, soft neutral |
| `--c-grey` | `#848e88` | Secondary text, metadata |
| `--c-steel` | `#5f797c` | Links (hover), teal accent |
| `--c-moss` | `#616e69` | Dark green-grey, subtle UI |
| `--c-tan` | `#a18863` | Illustration, warm accent |
| `--c-rust` | `#6d3d30` | Deep warm accent |
| `--c-plum` | `#48373f` | Deep cool accent |
Use semantic aliases in components: `--bg`, `--fg`, `--fg-muted`, `--fg-subtle`, `--rule`, `--link`.
Dark theme inverts: ink becomes ground, paper becomes foreground. See `[data-theme="dark"]` in tokens.css.
### Typography
| Role | Family | Fallback |
| --- | --- | --- |
| Display headlines | Rhymes Display | Times New Roman, Times |
| Editorial body | Rhymes Text | Iowan Old Style, Georgia |
| UI / interface | Public Sans | Inter, system-ui |
| Callouts | Peclet | Public Sans |
| Code / data | Fira Mono / Fira Code | SF Mono, Menlo |
Use the `--font-*` tokens. Do not hard code font names.
### Grid
- 12 columns, 1440px frame
- Column: 102.67px
- Gutter: 16px
- Margin: 16px
- Magazine editorial variant: 6 columns, 20px gap
### Spacing
4px base scale: `--sp-1` (4px) through `--sp-10` (128px).
## The visual test
Hold your product next to [logos.co](https://logos.co/). Then ask:
1. **Same palette?** Only the tokens above, no colours outside them.
2. **Same typeface?** Rhymes for editorial, Public Sans for UI, Fira for code.
3. **Same density?** Tight tracking, generous white space, no cramped layouts.
4. **Same feel?** Infrastructure, not consumer app. Tools, not toys. Manual, not glossy.
5. **Lambda used correctly?** Way-finding mark, not decorative wallpaper. It has a purpose or it is not there.
If any answer is no, fix it and run the test again before shipping.
## What not to do
- Do not diverge and plan to "align later". Always start off aligned.
- Do not use the lambda as a loading spinner, background pattern, or favicon.
@@ -0,0 +1,35 @@
# What Logos Is Not
If you catch yourself drifting towards any of these, stop and re-read this field guide.
## Not a reform movement
Logos does not fix existing institutions from within. Reform from inside is destined to fail. The parallel is built outside the existing order, not as another version of it.
## Not escapism
The parallel society is not retreat. It is a moral challenge orientated towards renewal, not withdrawal. We build alternatives through real work in real places, not a separate world.
## Not just a tech project
Code is necessary but not sufficient. The stack fails without humans aligned with its values. The parallel society needs people of enough character to sustain what we build.
## Not corporate
Logos is a movement made up of the sum of all its people, hardware, software, and cognitive artefacts. We build it together, without permission, towards a common goal.
## Not a brand
Logos is a way of life, a practice and not a costume. It does not sell a vibe or perform rebellion. The work is infrastructure, institutions, and culture. If the output looks good but routes to nothing actionable, it has failed.
## Not a web3 ecosystem
Logos does not compete for "ecosystem" status. It builds tools with people who need them. If they work, people will use them. If they do not, no amount of branding will fix it.
## Not a community-building campaign
Community is a result, not a strategy. Logos enables community through useful tools, real-world impact, and a strong culture. It does not manufacture it through campaigns, influencers, or engagement farming.
## _The quick test_
_Logos outputs should be recognisable by their substance, not their branding. To assess this, mentally replace the lambda (λ) in the output with another organisation's logo. If the new output could align with the other organisation, it needs reworking._
@@ -0,0 +1,41 @@
# Who Logos Is For
Logos is not for everyone.
It is not for spectators who are waiting for the system to fix itself from within.
It is not for people who wait for permission to transact, to speak, or to build.
It is not for people who think freedom is something the state grants you.
It is not for those who are still putting up the sign, performing obedience to ideas, or getting caught up in identity politics.
It is not for keyboard warriors, status seekers, and trend chasers.
It is not for anyone wanting rights without responsibility or freedom without duty.
It is not for those who prefer the comfort of centralised control or the safety of staying silent.
It is not for people too sedated by algorithmic feeds, engineered addictions, dopamine loops, and endless scrolling.
It is not for cynics who thrive on posturing or complaining while doing nothing to build something better.
It is not for those who think crypto is a get-rich-quick scheme or a career wave to chase.
Logos is for people who are done waiting for permission.
For those who want to act, ship, produce, and connect.
For those who believe free people need sovereign infrastructure and understand that this is one of the revolutionary promises of crypto.
Logos is for the cypherpunks, cryptoanarchists, and libertarians who have had enough of empty rhetoric and want working solutions.
For everyone ready to live with intention online and offline in pursuit of real agency, real community, and real optimism about what's possible.
For those who organise their lives around purpose, service, and virtue rather than greed and status.
For those who want to live the alternative, not just argue for it.
The door is open.
The posture is not negotiable.
@@ -0,0 +1,19 @@
# Why Logos?
Civil society is in decline across the world. Our institutions are failing. Our money is debased.
People are atomised, indebted, and increasingly unable to provide for themselves or their families. Our attention is harvested by algorithmic feeds engineered for compulsion, and our mental health pays the price. Reform from within cannot reverse this because the system selects for compliance, and centralisation inevitably leads to corruption.
Logos exists to build the decentralised infrastructure and living ecosystem that makes a better society possible for anyone willing to reclaim their agency, online and IRL. In this way, Logos is built for exit when the existing order no longer holds.
Our code and [Credo](/field-guide/credo) stem from our name's origins. To the ancient Greeks, Logos meant "word", "reason", or "rational principle", and often referred to the underlying order that makes the world intelligible. Our use of the lambda (λ) represents that lineage.
### What this means for you
The decline is personal too: savings buy less every year, corruption hollows out local institutions, hours vanish into feeds engineered against you, we say what's safe instead of what's true, and young people are lonelier than ever.
As this process evolves, the people who thrive will have a community that supports them, the agency to identify and solve their own problems, and sovereign tools that protect them and their money.
We build those here, for ourselves, without permission: communities that solve real problems where they live, skills that make us capable and self-reliant, and a parallel economy that doesn't depend on a system designed against us.
> Build the parallel. Prove it in practice. Keep it human.
+42
View File
@@ -0,0 +1,42 @@
{
"schemaVersion": 1,
"language": "en",
"title": "Logos Field Guide",
"version": "v0.1",
"sections": [
{
"section": "Start",
"items": [{ "slug": "index", "num": "00", "title": "Logos Field Guide" }]
},
{
"section": "Foundations",
"items": [
{ "slug": "how-logos-works", "num": "01", "title": "How Logos Works" },
{ "slug": "why-logos", "num": "02", "title": "Why Logos?" },
{ "slug": "what-logos-is-not", "num": "03", "title": "What Logos Is Not" },
{ "slug": "who-logos-is-for", "num": "04", "title": "Who Logos Is For" },
{ "slug": "eight-truths", "num": "05", "title": "Eight Truths" },
{ "slug": "credo", "num": "06", "title": "Credo" },
{ "slug": "four-checks", "num": "07", "title": "The Four Checks" },
{ "slug": "cultural-lanes", "num": "08", "title": "Cultural Lanes" }
]
},
{
"section": "Expression",
"items": [
{ "slug": "expression", "num": "09", "title": "Expression" },
{ "slug": "the-full-system", "num": "10", "title": "The Full System" },
{ "slug": "visual", "num": "11", "title": "Visual" },
{ "slug": "language", "num": "12", "title": "Language" },
{ "slug": "events", "num": "13", "title": "Events" }
]
},
{
"section": "Appendix",
"items": [
{ "slug": "glossary", "num": "14", "title": "Glossary" },
{ "slug": "templates", "num": "15", "title": "Templates" }
]
}
]
}
+2 -1
View File
@@ -19,7 +19,8 @@
"href": "https://free.technology/jobs",
"external": true
},
{ "label": "Brand Guidelines", "href": "/brand-kit" }
{ "label": "Brand Guidelines", "href": "/brand-kit" },
{ "label": "Field Guide", "href": "/field-guide" }
],
"socialLinks": [
{
+1
View File
@@ -108,6 +108,7 @@
{ "label": "Manifesto", "href": "/manifesto" },
{ "label": "Community Forum", "href": "https://forum.logos.co/" },
{ "label": "Brand Kit", "href": "/brand-kit" },
{ "label": "Field Guide", "href": "/field-guide" },
{ "label": "Book", "href": "/book" }
]
},
@@ -0,0 +1,118 @@
# Field Guide — Design Spec
**Issue:** [logos-co/logos-web#65](https://github.com/logos-co/logos-web/issues/65) — Create and add Field Guide
**Date:** 2026-06-26
**Branch:** `feat/field-guide`
## Problem
The team built a standalone Logos Field Guide (a 16-chapter brand/comms guide) hosted at
`https://logos-brand-protocol.vercel.app/index.html`. It needs to live on the main site at
`logos.co/field-guide`, and be discoverable from:
- Footer → "Field Guide" (under "Brand Guidelines")
- Global nav → Resources → "Field Guide"
The reference site is a purpose-built reading experience: a left chapter sidebar, prev/next pager,
per-page reference label, and keyboard navigation (←/→). The content is prose-heavy: headings,
paragraphs, blockquotes, GFM tables, lists, keyboard hints, and inter-chapter links.
## Decisions
Confirmed with the user during brainstorming:
1. **Independent port** — preserve the guide's own reading experience (sidebar + pager), not a
full re-build into marketing-page components, and not a link-out to the external site.
2. **Site header retained, guide chrome dropped** — keep the logos.co global nav header so the
guide feels part of the site. Drop the reference site's own header (theme toggle, GitHub, print).
3. **Content stored as data in `content/`** — consistent with the existing content single-source
approach; CMS-migratable later.
4. **Light theme only** — drop the reference site's Paper/Ink theme toggle; match logos.co's
light design (`brand-dark-green` on light).
## Architecture
### Routing & build
- New route: `apps/web/app/[locale]/field-guide/[[...slug]]/page.tsx` (optional catch-all).
- `/field-guide` → index chapter (`index`, num `00`)
- `/field-guide/<slug>` → that chapter
- `generateStaticParams` enumerates all 16 chapter slugs across active locales — required because
production builds with `output: 'export'` (static export, no server).
- Unknown slug → `notFound()`.
- `constants/routes.ts`: add `fieldGuide: '/field-guide'`. All hrefs reference this constant.
- `app/sitemap.ts`: add the field-guide index + every chapter path to the indexable routes.
### Content storage (`content/field-guide/en/`)
- `manifest.json` — the table of contents and guide metadata:
- guide `title`, `version`
- `sections`: ordered list of `{ section, items: [{ slug, num, title }] }`
- This is the single source for the sidebar, pager order, page-ref label, and
`generateStaticParams`.
- `chapters/<slug>.md` — one Markdown file per chapter (16 files). Bodies are ported from the
reference site's HTML, converted to GFM Markdown (tables, blockquotes, lists, `kbd` via inline
code or HTML, inter-chapter links rewritten to `/field-guide/<slug>`).
Storing bodies as Markdown (not block-JSON) keeps porting faithful and low-friction, and
`react-markdown` + `remark-gfm` are already dependencies in `apps/web`.
### Content package (`packages/content`)
- `src/schemas/field-guide.ts` — zod schema for `manifest.json`
(`fieldGuideManifestSchema`, with `schemaVersion`, `language`, guide meta, sections/items).
- `src/loaders/field-guide.ts`:
- `getFieldGuideManifest(locale)` — reads + validates `manifest.json`.
- `getFieldGuideChapter(locale, slug)` — reads the chapter Markdown; throws
`ContentNotFoundError` for unknown slugs (so the route can `notFound()`).
- `getFieldGuideSlugs(locale)` — flat slug list for `generateStaticParams`.
- `src/loaders/_fs.ts` — add a `readText(filePath)` helper (mirrors `readJson`, returns the raw
string, throws `ContentNotFoundError` on ENOENT).
- Export new loaders/schema from the package barrels.
### Rendering components (`apps/web/components/sections/field-guide/`)
- `FieldGuideShell` (client component) — the reading layout:
- left sidebar: TOC grouped by section, with chapter number + title, active item highlighted
- main column: the rendered chapter + a page-ref eyebrow (`<num> · <title>`)
- bottom pager: prev / next chapter links derived from manifest order
- mobile: hamburger toggles the sidebar (backdrop overlay)
- keyboard: ←/→ navigate between chapters (ignored while focus is in an input)
- `FieldGuideContent` — wraps `react-markdown` (+ `remark-gfm`) with a component map binding
Markdown elements (`h1``h3`, `p`, `table`/`thead`/`tbody`/`tr`/`th`/`td`, `blockquote`,
`ul`/`ol`/`li`, `hr`, `code`, `a`) to logos.co design tokens. Internal links
(`/field-guide/...` and other site routes) render via the i18n `Link`; external links open in a
new tab with `rel="noopener"`.
The page component (server) loads the manifest + the requested chapter, resolves prev/next, and
renders `FieldGuideShell` with `FieldGuideContent` inside. The global `SiteHeader` already wraps
all `[locale]` pages; no guide-specific header is added.
### Link integration
- `content/site/en/footer.json``mainLinks`: add `{ "label": "Field Guide", "href": "/field-guide" }`
immediately after "Brand Guidelines".
- `content/site/en/navigation.json` → "Explore" panel → "Resources" `links`: add
`{ "label": "Field Guide", "href": "/field-guide" }` next to "Brand Kit".
### Metadata
- `messages/en.json``pages.fieldGuide`: title + description for SEO.
- Per-chapter `<title>` uses the chapter title from the manifest
(`<Chapter title> — Logos Field Guide`).
## Testing
- `packages/content`: unit tests for the field-guide schema (valid/invalid manifest) and loader
(manifest load, chapter load, unknown-slug → `ContentNotFoundError`).
- Integrity test: every `manifest.json` item has a matching `chapters/<slug>.md`, and no orphan
Markdown files exist.
- Component: `FieldGuideContent` renders Markdown elements with the mapped components; internal
links use the i18n `Link`.
## Out of scope
- CMS (Strapi) modelling — content lives as files now; migration is a later step.
- Localisation beyond English — content is English-only; the route renders the same content under
every active locale (matching how other content-driven pages behave today).
- Paper/Ink theme toggle, print, and GitHub chrome from the reference site.
@@ -0,0 +1,93 @@
import assert from 'node:assert/strict'
import { readdirSync } from 'node:fs'
import { resolve } from 'node:path'
import { before, describe, it } from 'node:test'
import {
ContentNotFoundError,
flattenFieldGuideItems,
getFieldGuideChapter,
getFieldGuideManifest,
getFieldGuideSlugs,
} from '../index'
import { setContentRoot } from '../_fs'
const activeLocale = 'en'
const contentRoot = resolve(process.cwd(), '../../content')
before(() => {
setContentRoot(contentRoot)
})
describe('field guide loaders', () => {
it('loads the manifest with ordered, well-formed chapters', async () => {
const manifest = await getFieldGuideManifest(activeLocale)
assert.ok(manifest.title)
assert.ok(manifest.version)
assert.ok(manifest.sections.length > 0)
const items = flattenFieldGuideItems(manifest)
assert.ok(items.length > 0)
const slugs = new Set<string>()
for (const item of items) {
assert.match(item.num, /^\d{2}$/, `bad num for ${item.slug}`)
assert.ok(item.title, `missing title for ${item.slug}`)
assert.equal(slugs.has(item.slug), false, `duplicate slug ${item.slug}`)
slugs.add(item.slug)
}
})
it('loads a Markdown body for every manifest chapter', async () => {
const slugs = await getFieldGuideSlugs(activeLocale)
for (const slug of slugs) {
const body = await getFieldGuideChapter(activeLocale, slug)
assert.ok(body.trim().length > 0, `empty chapter body for ${slug}`)
assert.ok(
body.startsWith('#'),
`chapter ${slug} should start with a heading`
)
}
})
it('has no orphan chapter files outside the manifest', async () => {
const slugs = new Set(await getFieldGuideSlugs(activeLocale))
const chaptersDir = resolve(
contentRoot,
'field-guide',
activeLocale,
'chapters'
)
const fileSlugs = readdirSync(chaptersDir)
.filter((name) => name.endsWith('.md'))
.map((name) => name.replace(/\.md$/, ''))
assert.equal(
fileSlugs.length,
slugs.size,
'chapter file count must match manifest item count'
)
for (const fileSlug of fileSlugs) {
assert.equal(
slugs.has(fileSlug),
true,
`orphan chapter file "${fileSlug}.md" has no manifest entry`
)
}
})
it('raises ContentNotFoundError for an unknown chapter slug', async () => {
await assert.rejects(
getFieldGuideChapter(activeLocale, 'does-not-exist'),
(error: unknown) => error instanceof ContentNotFoundError
)
})
it('rejects inactive locales instead of silently falling back', async () => {
await assert.rejects(
getFieldGuideManifest('fr'),
/locale "fr" is not active/
)
})
})
+17
View File
@@ -112,6 +112,23 @@ export const readJson = async <S extends ZodTypeAny>(
return result.data
}
/**
* Reads a raw UTF-8 text file (e.g. Markdown chapter bodies). Mirrors
* `readJson`'s not-found handling so callers can `instanceof
* ContentNotFoundError` to decide between `notFound()` and re-throwing.
*/
export const readText = async (filePath: string): Promise<string> => {
try {
return await readFile(filePath, 'utf-8')
} catch (err) {
if (isFsNotFound(err)) {
throw new ContentNotFoundError(filePath)
}
const reason = err instanceof Error ? err.message : String(err)
throw new Error(`failed to read ${filePath}: ${reason}`, { cause: err })
}
}
export const listDirectories = async (parent: string): Promise<string[]> => {
if (!existsSync(parent)) return []
const entries = await readdir(parent, { withFileTypes: true })
@@ -0,0 +1,55 @@
import { assertActiveLocale } from '../locales/registry'
import {
type FieldGuideItem,
type FieldGuideManifest,
type Language,
fieldGuideManifestSchema,
} from '../schemas/index'
import { ContentNotFoundError, contentPath, readJson, readText } from './_fs'
const FIELD_GUIDE_DIR = 'field-guide'
export const getFieldGuideManifest = async (
locale: Language
): Promise<FieldGuideManifest> => {
assertActiveLocale(locale)
return readJson(
contentPath(FIELD_GUIDE_DIR, locale, 'manifest.json'),
fieldGuideManifestSchema
)
}
/** Flattens the manifest's grouped sections into pager/static-param order. */
export const flattenFieldGuideItems = (
manifest: FieldGuideManifest
): FieldGuideItem[] => manifest.sections.flatMap((section) => section.items)
/** Slug list for `generateStaticParams`. */
export const getFieldGuideSlugs = async (
locale: Language
): Promise<string[]> => {
const manifest = await getFieldGuideManifest(locale)
return flattenFieldGuideItems(manifest).map((item) => item.slug)
}
/**
* Reads a chapter's Markdown body. Validates the slug against the manifest so
* an unknown slug raises `ContentNotFoundError` (route → `notFound()`) rather
* than leaking a filesystem path or reading outside the chapters directory.
*/
export const getFieldGuideChapter = async (
locale: Language,
slug: string
): Promise<string> => {
assertActiveLocale(locale)
const slugs = await getFieldGuideSlugs(locale)
if (!slugs.includes(slug)) {
throw new ContentNotFoundError(
contentPath(FIELD_GUIDE_DIR, locale, 'chapters', `${slug}.md`)
)
}
return readText(
contentPath(FIELD_GUIDE_DIR, locale, 'chapters', `${slug}.md`)
)
}
+1
View File
@@ -3,3 +3,4 @@ export * from './site'
export * from './builders-hub'
export * from './circles'
export * from './pages'
export * from './field-guide'
@@ -0,0 +1,36 @@
import { z } from 'zod'
import { languageSchema, schemaVersion, slugSchema } from './common'
/**
* One entry in the Field Guide table of contents. `num` is the display index
* shown beside the title (e.g. "00", "07") — a zero-padded string, not a
* number, so leading zeros survive.
*/
export const fieldGuideItemSchema = z.object({
slug: slugSchema,
num: z.string().regex(/^\d{2}$/, 'num must be a two-digit string'),
title: z.string().min(1),
})
export type FieldGuideItem = z.infer<typeof fieldGuideItemSchema>
export const fieldGuideSectionSchema = z.object({
section: z.string().min(1),
items: z.array(fieldGuideItemSchema).min(1),
})
export type FieldGuideSection = z.infer<typeof fieldGuideSectionSchema>
/**
* The Field Guide manifest: guide metadata plus the ordered chapter list.
* It is the single source for the sidebar, the prev/next pager order, the
* page-reference label, and static-param generation. Chapter bodies live as
* sibling Markdown files (`chapters/<slug>.md`), not in this manifest.
*/
export const fieldGuideManifestSchema = z.object({
schemaVersion: schemaVersion(1),
language: languageSchema,
title: z.string().min(1),
version: z.string().min(1),
sections: z.array(fieldGuideSectionSchema).min(1),
})
export type FieldGuideManifest = z.infer<typeof fieldGuideManifestSchema>
+1
View File
@@ -4,3 +4,4 @@ export * from './builders-hub'
export * from './circles'
export * from './pages'
export * from './custom-sections'
export * from './field-guide'