ᚨ Development Conventions
Every realm in Yggdrasil is governed by a REGLAS_YGGDRASIL.md file — a living document that defines the rules of that realm. "Reglas" is Spanish for "rules," chosen intentionally to reflect the bilingual context of the BrierStudios team.
REGLAS_YGGDRASIL.md
Each project's REGLAS_YGGDRASIL.md contains:
1. Realm Declaration
# REGLAS_YGGDRASIL — Midgard
**Realm:** Midgard (Personal Apps)
**Proyecto:** brierstudios-site
**Versión:** 1.0.0
2. Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Repositories | kebab-case with realm prefix | vana-lilith-discord |
| Files | kebab-case | personality-engine.ts |
| Components | PascalCase | NeonButton.tsx |
| Functions | camelCase | parseRealmConfig() |
| Constants | UPPER_SNAKE_CASE | MAX_RETRY_ATTEMPTS |
| CSS Classes | kebab-case with BEM | hero__title--glow |
| Environment Vars | UPPER_SNAKE_CASE with realm prefix | VANA_DISCORD_TOKEN |
| Branch Names | realm/type/description | vana/feature/personality-engine |
3. Commit Messages
Follow the Conventional Commits specification with a realm prefix:
vana(core): add personality switching pipeline
- Implement personality.yml parser
- Add trait resolution engine
- Write integration tests for personality engine
Refs: VANA-123
Format: <realm>(<scope>): <description>
Common scopes:
core— Core functionalityui— Visual changesdocs— Documentationtest— Test additions/changesci— CI/CD pipelineperf— Performance
4. Branch Strategy
main (production)
├── develop (staging)
│ ├── <realm>/feature/<description>
│ ├── <realm>/fix/<description>
│ └── <realm>/experiment/<description>
└── hotfix/<description>
Rules:
mainis always deployable- All feature branches branch from
developand merge back via PR muspel/prefixed branches have relaxed review requirementsasgard/prefixed branches require 2+ approvals
5. Required Files
Every project must include:
├── REGLAS_YGGDRASIL.md # Conventions (this file)
├── .yggdrasil.yml # Project manifest
├── README.md # Project description and setup
├── CHANGELOG.md # Version history
├── LICENSE # License (MIT unless specified)
└── tests/ # Test directory (never empty)
6. Code Review Rules
| Realm | Min. Reviewers | Auto-Merge | Merge Strategy |
|---|---|---|---|
| Asgard | 2 | ᚻ Never | Squash |
| Vanaheim | 1 | ᛏ If CI passes | Squash |
| Alfheim | 1 | ᛏ If CI passes | Squash |
| Svartalfheim | 1 | ᛏ If CI passes | Merge commit |
| Muspelheim | 0 | ᛏ Always | ANY |
| Niflheim | 1 | ᛏ If CI passes | Squash |
| Helheim | N/A | N/A | Read-only |
| Jotunheim | 2 | ᚻ Never | Squash |
| Midgard | 1 | ᛏ If CI passes | Squash |
TypeScript Conventions
Strict Mode
All projects use TypeScript strict mode:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true
}
}
Import Style
Use named imports. No wildcard imports.
// ᛏ Good
import { YggdrasilBus } from '@brierstudils/yggdrasil-core';
import type { RealmConfig } from '@brierstudils/yggdrasil-core';
// ᚻ Bad
import * as Core from '@brierstudils/yggdrasil-core';
Error Handling
All errors must be typed. Use Result pattern for expected failures.
// ᛏ Good — typed Result
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
function deployToRealm(realm: Realm): Result<DeploymentId, DeployError> {
// ...
}
// ᚻ Bad — untyped throw
function deployToRealm(realm: Realm) {
throw new Error('failed'); // what kind of error?
}
Environment Variables
All env vars must be validated at startup using Zod or similar:
import { z } from 'zod';
const envSchema = z.object({
REALM: z.enum(['asgard', 'vanaheim', 'alfheim', 'svartalfheim', 'muspelheim', 'niflheim', 'helheim', 'jotunheim', 'midgard']),
DISCORD_TOKEN: z.string().min(1),
NODE_ENV: z.enum(['development', 'staging', 'production']),
});
const env = envSchema.parse(process.env);
Testing Conventions
Test File Naming
src/
personality-engine.ts
personality-engine.test.ts ← Unit test
personality-engine.integration.test.ts ← Integration test
Coverage Requirements
| Realm | Minimum Coverage | Enforcement |
|---|---|---|
| Asgard | 100% | CI blocks on miss |
| Vanaheim | 80% | Warning at 70% |
| Alfheim | 70% | Warning at 60% |
| Midgard | 70% | Warning at 60% |
| Muspelheim | None | None |
| Others | 80% | CI blocks on miss |
Test Structure
describe('PersonalityEngine', () => {
// Setup per describe block, not per test
const engine = new PersonalityEngine(LILITH_PROFILE);
describe('resolveTrait()', () => {
it('should return the correct trait value', () => {
expect(engine.resolveTrait('curious')).toBe(true);
});
it('should return undefined for unknown traits', () => {
expect(engine.resolveTrait('nonexistent')).toBeUndefined();
});
});
});
Documentation Conventions
- Language: English for content, Spanish-neutral terms for conventions (e.g., "Reglas")
- Format: MDX with frontmatter (
title,description,sidebar_position) - Admonitions: Use Docusaurus admonitions for callouts (tip, info, warning, caution)
- Code blocks: Always include language identifier and optional title
- Links: Prefer relative links over absolute URLs
- Images: Store in
static/img/with descriptive filenames
Linting & Formatting
The Yggdrasil CLI enforces conventions via yg lint:
# Check all conventions
yg lint
# Auto-fix what's possible
yg lint --fix
# Include realm-specific checks
yg lint --realm-check
# Run on specific realm
yg lint --realm asgard --strict
The linter checks:
- File naming conventions
- Commit message format
- Required files existence
- Test coverage thresholds
- Import style (no wildcards)
- TypeScript strict mode
REGLAS_YGGDRASIL.mdcompleteness
Reglas son reglas. Even in the Nine Realms. ᚨᛊ