Conventions

This document defines how content and history are organized in Gitlas so that humans and AI agents produce consistent, predictable results.


Folder taxonomy

Top-level areas map to life domains. Keep the tree shallow and obvious.

work/        Professional context (projects, architecture, knowledge)
personal/    Private matters (finances, travel, health)
family/      Shared household (house, documents, insurance, planning)
templates/   Reusable page templates (do not store real content here)
attachments/ Binary files referenced by pages (images, PDFs, ...)
secrets/     Encrypted structured secrets (SOPS + age); values only
quartz/      Publishing configuration and theme

New subfolders are allowed when a clear category emerges. Prefer adding a subfolder over inventing deep nesting.


File naming

  • Use lowercase kebab-case: heat-pump.md, project-a.md.
  • No spaces, umlauts, or special characters in file names.
  • Use ISO dates (YYYY-MM-DD) and put the year last where a date matters: japan-2027.md, summer-vacation-2027.md.
  • One topic per file. Split large topics instead of growing one file forever.

Frontmatter schema

Every content page starts with YAML frontmatter. The base fields are required on all pages:

FieldTypeDescription
titlestringHuman-readable page title
categoryenumwork | personal | family
tagslist of stringsFree-form tags for search and grouping
createddateCreation date (YYYY-MM-DD)
updateddateLast meaningful update (YYYY-MM-DD)
statusenumdraft | active | planning | archived

Specialized templates extend the base with extra fields (e.g. travel adds period_start/period_end, insurance adds policy_number/ renewal_date). Extra fields are always additive; never remove a base field.


Templates

Pick the most specific template, then fill in the placeholders (<...>).

TemplateUse for
templates/page.mdGeneric page (default fallback)
templates/travel.mdTrips and travel planning
templates/maintenance-log.mdAssets with a service history
templates/insurance.mdInsurance policies and contracts

Templates live only in templates/ and must not contain real data.


Attachments

Binary files (images, PDFs, office documents) belong in attachments/ and are marked as binary in .gitattributes. Reference an attachment from a page using a relative link, e.g. [Policy PDF](../attachments/policy-2027.pdf).

Note: Git LFS is intentionally not enabled yet. Until it is, keep large binaries out of the repository. See below for how to enable it later.

Enabling Git LFS later (reference)

Introduce LFS once binary attachments actually grow, and only after the remote LFS story is sorted (see caveats). Steps:

# 1. Initialize LFS hooks for the clone
git lfs install --local
 
# 2. Track binary types (rewrites .gitattributes entries to filter=lfs)
git lfs track "*.png" "*.jpg" "*.jpeg" "*.gif" "*.webp" \
              "*.pdf" "*.zip" "*.docx" "*.xlsx" "*.pptx" "*.odt" "*.ods"
 
# 3a. For NEW files: just add + commit as usual.
# 3b. To move files ALREADY in history into LFS (rewrites history, needs a
#     force-push and coordination):
git lfs migrate import --include="*.png,*.pdf" --everything

Remote caveats (learned the hard way):

  • Forgejo serves LFS over HTTPS. In a corporate network the LFS client must trust the proxy/root CA, otherwise pushes fail with x509: certificate signed by unknown authority. Point Git at the correct CA:
    git config http.sslCAInfo /path/to/corporate-ca.pem
  • The local bare repo used for dual-push is not an LFS server. Pin LFS traffic to Forgejo so the bare push does not try (and fail) to upload objects:
    git config lfs.url https://<forgejo-host>/<owner>/<repo>.git/info/lfs
  • If you see “does not support the Git LFS locking API”, disable lock verification for that remote:
    git config lfs.<remote-lfs-url>.locksverify false

Because LFS interacts with remote/infra configuration, treat enabling it as a deliberate, coordinated change rather than a routine commit.


Secrets (SOPS + age)

Secrets never live in normal pages. They belong exclusively in secrets/ as structured files (.yaml / .json / .env) encrypted with SOPS and age. SOPS encrypts only the values; field names stay readable and greppable. The human-readable page references the secret by file name.

Reference status: the current setup is a template. .sops.yaml contains placeholder recipients and secrets/example.yaml holds fake values. No real key material or secret is stored yet.

Rules:

  • Real secrets go only into secrets/, never into content pages.
  • Files under secrets/ must be SOPS-encrypted before the first commit.
  • Keep one logical secret per file; name by topic (wifi.yaml, insurance-haftpflicht.yaml).

Activate encryption (once real age keys exist):

# 1. Put the real age recipients (age1...) into .sops.yaml
# 2. Encrypt / edit a file
sops --encrypt --in-place secrets/wifi.yaml
sops secrets/wifi.yaml            # edit decrypted, re-encrypts on save

Key revocation (on compromise)

Forward secrecy for new commits is straightforward; past ciphertext in Git history stays decryptable by the old key, so treat exposed secrets as burned.

  1. Remove the compromised recipient from .sops.yaml.
  2. Rotate every affected file’s data key and recipients:
    find secrets -type f -exec sops updatekeys -y {} \;
    find secrets -type f -exec sops -r -i {} \;   # rotate data keys
  3. Rotate the real-world secrets (change passwords, reissue tokens) — anything the old key could read is considered exposed.
  4. Optionally rewrite Git history to purge old ciphertext.

Commit messages

Commit messages follow Conventional Commits and are written in English, in the imperative mood.

<type>(<scope>): <short summary>
  • type: one of feat (new page or capability), docs (documentation), content (add/update knowledge content), fix (correction), refactor (restructure without changing meaning), chore (tooling, config, housekeeping).
  • scope (optional): the area or path, e.g. family/insurance, templates.
  • summary: concise, lower-case, no trailing period, imperative (“add”, not “added”/“adds”).

Examples:

content(personal/travel): add japan 2027 trip page
feat(templates): add insurance template
docs: document frontmatter schema
fix(family/house): correct heat pump service date
chore: mark binary attachments in gitattributes

For AI-assisted changes on shared repositories, prefer the review workflow: work on a topic/<name> branch and open a pull request instead of committing directly to main.