Agent skill

Olm Architecture

by OpenLitterMap in OpenLitterMap/openlittermap-web

OpenLitterMap v5 architecture reference. An agent skill from OpenLitterMap/openlittermap-web.

GPL-3.0Auto-check passedBackend & APIs

Install Olm Architecture

skills CLI
$ npx skills add OpenLitterMap/openlittermap-web --skill olm-architecture -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install OpenLitterMap/openlittermap-web olm-architecture --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/OpenLitterMap/openlittermap-web.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.ai/skills/olm-architecture .claude/skills/olm-architecture && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
olm-architecture
GitHub stars
134
Token cost
~5.2k tokens
SKILL.md length
1,736 words
Files
1
Skills in repo
16
Repo updated
First seen
Licence
GPL-3.0

At a glance

OpenLitterMap v5 architecture reference. An agent skill from OpenLitterMap/openlittermap-web.

  • Works in 4 steps: School team — always is_public = false… → Explicit is_public param in upload request → User's public_photos default → …
  • Working on OLM backend code
  • SKILL.md covers Core Principle: Every Tag…, The Tag Pipeline, VerificationStatus Enum and The Atomic Approve Pattern, plus 16 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Olm Architecture is an agent skill from OpenLitterMap/openlittermap-web. OpenLitterMap v5 architecture reference. Use this skill whenever working on OLM backend code, Laravel controllers, services, events, tests, Redis, metrics, tags, photos, teams, admin, leaderboards, or any part of the OpenLitterMap codebase. Also trigger when the user mentions MetricsService, VerificationStatus, PhotoTags, AddTagsToPhotoAction, TagsVerifiedByAdmin, rewardXpToAdmin, school pipeline, teacher approval, clustering, or any OLM-specific concept. This skill should be used BEFORE writing any OLM code to…

Its SKILL.md is about 5.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Backend development. It works with Redis and Laravel. The repository describes itself as: https://opengeospatialdata.springeropen.com/articles/10.1186/s40965-018-0050-y. The licence is GPL-3.0.

When your agent uses it

  • Working on OLM backend code
  • Laravel controllers
  • Any part of the OpenLitterMap codebase
  • The user mentions MetricsService

Example prompts

  • “/olm-architecture”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. School team — always is_public = false (enforced by PhotoObserver, cannot be overridden)
  2. Explicit is_public param in upload request
  3. User's public_photos default
  4. Falls back to true

What it can do on your machine

Read from SKILL.md and the folder at commit ac688aa. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are php, json and sql).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Olm Architecture loads about 5.2k tokens when it runs. Until then it costs about 154 tokens; SKILL.md has 1,736 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~154
When it runs · the whole SKILL.md, loaded when a task matches
~5.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from OpenLitterMap/openlittermap-web at commit ac688aa, republished under its GPL-3.0 licence (© OpenLitterMap). 1,736 words, ~5,217 tokens.

Download SKILL.mdSave it as .claude/skills/olm-architecture/SKILL.md (or your agent's skills folder).
name
olm-architecture
description
OpenLitterMap v5 architecture reference. Use this skill whenever working on OLM backend code, Laravel controllers, services, events, tests, Redis, metrics, tags, photos, teams, admin, leaderboards, or any part of the OpenLitterMap codebase. Also trigger when the user mentions MetricsService, VerificationStatus, PhotoTags, AddTagsToPhotoAction, TagsVerifiedByAdmin, rewardXpToAdmin, school pipeline, teacher approval, clustering, or any OLM-specific concept. This skill should be used BEFORE writing any OLM code to avoid architectural mistakes. When in doubt about OLM patterns, read this skill.

OpenLitterMap v5 — Architecture Reference

This is the canonical reference for OLM's v5 architecture. Read this before writing any backend code.

Core Principle: Every Tag Change Flows Through MetricsService

Nothing writes metrics directly. Every tag creation, edit, or deletion flows through a pipeline that ensures metrics, leaderboards, Redis, and the database stay in sync.

The Tag Pipeline

User/Admin/Teacher tags a photo
    ↓
AddTagsToPhotoAction::run($userId, $photoId, $tags)  ← wrapped in DB::transaction()
    ├── Resolves tags:
    │   ├── Object tags: uses category_litter_object_id (CLO ID), auto-resolves category
    │   ├── Custom-only: $tag['custom'] = true, $tag['key'] = "dirty-bench"
    │   ├── Brand-only: $tag['brand_only'] = true
    │   └── Material-only: $tag['material_only'] = true
    ├── Creates PhotoTag + PhotoTagExtraTags rows
    ├── Calls GeneratePhotoSummaryService
    │   ├── Builds summary JSON from PhotoTags (numeric ID keys)
    │   ├── Calculates XP via XpScore enum multipliers
    │   └── Writes photo.summary, photo.xp, photo.total_tags
    ↓
updateVerification() — WHO tagged it?
    ├── Trusted user → verified = ADMIN_APPROVED, fires TagsVerifiedByAdmin
    ├── Non-trusted user → verified = UNVERIFIED (0), fires TagsVerifiedByAdmin
    │   (Photo NOT on map, but user gets immediate leaderboard credit)
    ├── School student → verified = VERIFIED (1), does NOT fire event
    │   (Waits for teacher approval — safeguarding invariant)
    ↓
TagsVerifiedByAdmin event (fires for ALL non-school users)
    → ProcessPhotoMetrics listener
        → MetricsService::processPhoto($photo)
            ├── Computes fingerprint from summary JSON
            ├── If new (processed_at null): creates metric rows
            ├── If re-edit (processed_at set): computes delta
            ├── Upserts metrics table (5 timescales × 4 location scopes × 2 user modes)
            ├── Updates Redis (stats hashes, XP ZSETs, bitmaps, HLLs)
            └── Sets photo.processed_at, processed_fp, processed_tags, processed_xp

Key distinction: TagsVerifiedByAdmin fires for ALL non-school users at tag time. Trusted users also get verified = ADMIN_APPROVED (photo visible on map). Non-trusted users stay at verified = 0 (photo NOT on map, but user IS on leaderboard). Only school students' photos wait for teacher approval.

VerificationStatus Enum

php
enum VerificationStatus: int
{
    case UNVERIFIED = 0;      // Uploaded, no tags (also: tagged by non-trusted non-school user)
    case VERIFIED = 1;        // Tagged by school student (awaiting teacher)
    case ADMIN_APPROVED = 2;  // Approved by admin/trusted/teacher
    case BBOX_APPLIED = 3;    // Bounding boxes drawn
    case BBOX_VERIFIED = 4;   // Bounding boxes verified
    case AI_READY = 5;        // Ready for model training
}

Critical rule: Use ->value >= VerificationStatus::ADMIN_APPROVED->value (not == 2) when checking if a photo is public-ready. Photos at BBOX_APPLIED+ are also approved.

The enum is cast on the Photo model: 'verified' => VerificationStatus::class. Use ->value for >=/< comparisons, direct enum for === equality.

The Atomic Approve Pattern

Used everywhere: admin approve, teacher approve, batch approve.

php
$updated = Photo::where('id', $photo->id)
    ->where('is_public', true)
    ->where('verified', '<', VerificationStatus::ADMIN_APPROVED->value)
    ->update(['verified' => VerificationStatus::ADMIN_APPROVED->value]);

if ($updated > 0) {
    event(new TagsVerifiedByAdmin(
        photo_id: $photo->id,
        user_id: $photo->user_id,
        country_id: $photo->country_id,
        state_id: $photo->state_id,
        city_id: $photo->city_id,
        team_id: $photo->team_id
    ));
    rewardXpToAdmin();
}

Why atomic: Prevents double-processing. If two admins approve simultaneously, the WHERE clause ensures only one succeeds. The second gets $updated = 0 and no event fires.

Always pass all 6 named constructor args to TagsVerifiedByAdmin. Missing args cause listener failures.

MetricsService

Single writer rule. Only MetricsService writes to the metrics table and Redis metric keys. No other code may increment/decrement counters. Never use DB::table('metrics')->increment() or Redis::hincrby() directly.

processPhoto($photo)
  • Computes fingerprint from summary JSON
  • If processed_at is null: first processing → doCreate() (creates metrics + increments users.xp)
  • If processed_at is set: re-processing → doUpdate() (computes delta, applies corrections to users.xp)
  • Upserts metrics table rows: 5 timescales × 4 location scopes × 2 (aggregate user_id=0 + per-user user_id>0)
  • Updates Redis via RedisMetricsCollector (inside DB::afterCommit)
  • Sets photo.processed_at, processed_fp, processed_tags, processed_xp
recordUploadMetrics($photo, $uploadXp)
  • Gated on $team->isSchool() check — school photos skip entirely (deferred to approval). The gate is a school team check, NOT an is_public check.
  • Private-by-choice photos (non-school, is_public = false by user preference) still get immediate upload XP
  • For non-school photos: writes 1 upload + upload XP to metrics/Redis, sets processed_at
  • At tag time, processPhoto() routes to doUpdate() (delta-based) since processed_at is set
deletePhoto($photo)
  • Must run BEFORE $photo->delete() — hard sequencing rule
  • Reverses all metrics that processPhoto created
  • Only runs if processed_at is not null
  • Clears all processed_* columns
  • Prunes zero-XP members from Redis leaderboard ZSETs
php
// CORRECT order
if ($photo->processed_at) {
    $this->metricsService->deletePhoto($photo);
}
$photo->delete(); // soft delete

// WRONG — metrics can't read a deleted photo
$photo->delete();
$this->metricsService->deletePhoto($photo); // too late

Photo Summary JSON

Every tagged photo has a summary JSON column — a flat array of tag entries, one per photo_tags row:

json
{
    "tags": [
        {
            "clo_id": 42,
            "category_id": 1,
            "object_id": 5,
            "type_id": 3,
            "quantity": 2,
            "picked_up": true,
            "materials": [1, 4],
            "brands": { "7": 1 },
            "custom_tags": [45]
        }
    ],
    "totals": {
        "litter": 3,
        "materials": 3,
        "brands": 1,
        "custom_tags": 0
    },
    "keys": {
        "categories": { "1": "alcohol" },
        "objects": { "5": "bottle" },
        "types": { "3": "beer" },
        "materials": { "1": "glass" },
        "brands": { "7": "heineken" }
    }
}

Structure: tags[] — each entry maps 1:1 to a photo_tags row. materials and custom_tags are ID arrays (set membership, qty = parent tag quantity); brands is an {id: quantity} map (independent quantities); totals.litter = sum of object quantities; keys is a reverse-lookup for display (empty sub-maps omitted). Generated by GeneratePhotoSummaryService from PhotoTag rows. If summary is null, the photo has no tags and cannot be approved.

PhotoTags (v5 Tag System)

sql
photo_tags (
    id, photo_id,
    category_id,                  -- FK → categories (auto-resolved from object)
    litter_object_id,             -- FK → litter_objects
    category_litter_object_id,    -- FK → category_litter_object pivot (CLO ID)
    litter_object_type_id,        -- FK → litter_object_types (e.g., "beer" in "beer bottle")
    custom_tag_primary_id,        -- for custom-only tags (no category/object)
    quantity, picked_up,
    created_at, updated_at
)

photo_tag_extra_tags (
    id, photo_tag_id,
    tag_type,      -- 'material' | 'brand' | 'custom_tag'
    tag_type_id,   -- FK → materials / brandslist / custom_tags_new
    quantity, index,
    created_at, updated_at
)

v4 vs v5: v4 stored tags in 16+ separate category tables (smoking_id, food_id, etc on photos). v5 uses the unified PhotoTags table. Legacy v4 endpoints and the ConvertV4TagsAction shim have been removed (2026-03-01). Mobile now uses v3 endpoints with CLO format. Category FK columns on photos are deprecated.

Frontend sends CLO IDs: The web frontend sends category_litter_object_id (pre-resolved from the search index). Backend auto-resolves category_id from the CLO pivot. Category need NOT be sent separately.

No unique constraint on photo_tags: There is no unique constraint on (photo_id, category_litter_object_id, litter_object_type_id). Duplicate CLO+type combinations are possible (each row is a separate PhotoTag). Extra-tag deduplication (materials/brands) is handled via upsert within a single PhotoTag row, not across rows. Do NOT add a unique constraint expecting one row per (photo, CLO, type) combination.

getNewTags() conditional inclusion: UsersUploadsController::getNewTags() conditionally includes category and object only when both resolve (i.e., when both category_id and litter_object_id are non-null). Extra-tag-only PhotoTags (brand/material/custom-only) return category: null and object: null.

Upload error contract: UploadPhotoRequest::failedValidation() returns { success: false, error: <code>, message: <string>, errors: {...} }. resolveErrorCode() maps validation failures to typed string codes: no_exif, no_gps, no_datetime, duplicate, invalid_coordinates, validation_error. Mobile clients should read the error field for programmatic handling.

School Privacy — The is_public Gate

Hard rule: School team photos have is_public = false until a teacher approves them.

php
// PhotoObserver::creating() — automatic privacy
if ($photo->team_id) {
    $team = Team::find($photo->team_id);
    if ($team && $team->isSchool()) {
        $photo->is_public = false;
    }
}

// ALL public-facing queries MUST use this:
Photo::public()  // →where('is_public', true)
// or:
->where('is_public', true)

School pipeline: student uploads → is_public = false → NO upload metrics (deferred) → teacher reviews in Facilitator Queue → teacher approves → is_public = true + verified = ADMIN_APPROVED → TagsVerifiedByAdmin fires → processPhoto() → doCreate() handles full XP (upload + tag) in one pass + increments users.xp.

Admin queue never sees school photos (WHERE is_public = true excludes them). Teachers are the sole approvers for their team via the Facilitator Queue (3-panel admin-like UI).

User Photo Visibility

Users can control the public visibility of their photos independently of the school pipeline.

users.public_photos (boolean, default true): A per-user default. New photos inherit this value unless overridden.

Visibility precedence (highest to lowest):

  1. School team — always is_public = false (enforced by PhotoObserver, cannot be overridden)
  2. Explicit is_public param in upload request
  3. User's public_photos default
  4. Falls back to true

Private-by-choice photos (non-school, is_public = false by user preference):

  • Hidden from map, clusters, and all public endpoints (same as any is_public = false photo)
  • Upload metrics are processed immediately (unlike school photos)
  • User appears on leaderboard with full XP credit

School photos (is_public = false enforced):

  • Hidden from map AND upload metrics are deferred until teacher approval
  • recordUploadMetrics() is skipped (school team check, not is_public check)

Per-photo toggle: PATCH /api/v3/photos/{id}/visibility — owner-only, requires auth:sanctum. Blocked for school team photos (403). PhotoObserver marks affected tiles dirty on is_public change so the map updates correctly.

Spatie Roles & Permissions

Laravel Permission 6, web guard.

RoleAccess
superadminEverything + trust management + Horizon
adminPhoto review, approve, edit tags, delete
helperTag editing only
school_managerManage school team, approve student photos (invite email sent on grant)

Check with: $user->hasRole('admin') or $user->hasRole('superadmin')

Admin middleware checks: hasRole('admin') || hasRole('superadmin')

Nav.vue isAdmin includes 'superadmin' role (not just 'admin' and 'helper').

Redis Key Patterns

All keys use hash tags {...} for Redis Cluster compatibility:

{g}:stats               → HASH (global stats: uploads, tags, litter, xp, ...)
{g}:lb:xp               → ZSET (global XP leaderboard, user_id → xp)
{g}:hll                  → HyperLogLog (contributor count)
{c:ID}:stats             → HASH (country stats)
{c:ID}:lb:xp             → ZSET (country leaderboard)
{s:ID}:stats             → HASH (state stats)
{s:ID}:lb:xp             → ZSET (state leaderboard)
{ci:ID}:stats            → HASH (city stats)
{ci:ID}:lb:xp            → ZSET (city leaderboard)
{u:ID}:stats             → HASH (per-user stats: uploads, xp, litter)
{u:ID}:bitmap            → Bitmap (activity tracking)

Key builder: RedisKeys::global() → {g}, RedisKeys::country($id) → {c:$id}, etc.

rewardXpToAdmin() updates both MySQL users.xp AND Redis {g}:lb:xp sorted set.

Redis is a derived cache. Rebuildable from the metrics table. Never treat Redis as source of truth.

Soft Deletes

Photo model uses SoftDeletes trait. $photo->delete() sets deleted_at, does not remove the row. Eloquent auto-applies global scope excluding soft-deleted records. Raw queries need explicit whereNull('deleted_at').

Teams

Types: community and school. Stored in team_types table (resolve via $team->getTypeNameAttribute()). Do NOT hardcode type IDs — they vary between environments.

School teams enforce extra safeguarding: MasksStudentIdentity trait masks student names as "Student N" (deterministic, based on team_user.id join order). Student identity never exposed publicly.

School teams must NOT be is_trusted — trust bypasses teacher approval entirely.

Key methods: $team->isSchool(), $team->isLeader($userId), $team->hasSafeguarding()

Show full SKILL.md (664 more words)Show less
Facilitator Queue (Teacher's Admin-like UI)

School team leaders have a 3-panel verification queue (same layout as admin queue):

  • Left: FacilitatorQueueFilters (status toggle, date range)
  • Center: PhotoViewer (reused from tagging v2)
  • Right: UnifiedTagSearch + ActiveTagsList (reused from tagging v2)
  • Keyboard: A=approve, D=delete, E=save edits, R=revoke, S/K/→=next, J/←=prev

Backend: TeamPhotosController returns new_tags (CLO format), accepts CLO-based tag edits, provides member stats with safeguarding.

Teams Frontend — TeamsHub

/teams route uses TeamsHub.vue (replaces old sidebar layout). Three states: no teams (create/join landing), active team (header + stats + tabs), no active team (team picker). Tabs: Overview, Photos, Map, Members, Settings, Leaderboard, Approval Queue (school), Participants (school+sessions). Privacy defaults: leaderboards = false for all new teams, safeguarding = true enforced for school.

SchoolManagerInvite Email

SchoolManagerInvite mailable queued when school_manager role is granted (artisan command or admin toggle). Two CTAs: Upload → /upload, Create Team → /teams/create. Not sent on revoke.

Level System

Config-driven thresholds in config/levels.php. 12 levels from "Noob" (0 XP) to "SuperIntelligent LitterMaster" (1M+ XP).

LevelService::getUserLevel($xp) returns: level, title, xp_into_level, xp_for_next, xp_remaining, progress_percent.

User model next_level accessor calls LevelService. Frontend reads user.next_level.title.

XP Calculation

AddTagsToPhotoAction::calculateXp() uses XpScore enum multipliers:

ActionXPNote
Upload5Base per photo
Object1Per item (special objects: small=10, medium=25, large=50, bagsLitter=10)
Brand3Per brand (uses brand's own quantity)
Material2Per material (uses parent tag's quantity — set membership)
Custom Tag1Per custom tag (uses parent tag's quantity)
Picked Up5Per object (×quantity) where photo_tags.picked_up=true. Objects only — no bonus for brand/material/custom-only tags

API Field Naming Convention

All list/leaderboard endpoints use: total_tags, total_photos, total_members, created_at, updated_at. Never use old names: total_litter, total_images, tags, photos, contributors, members.

Clustering

Grid-based, 9 zoom levels (0,2,4,6,8,10,12,14,16). Two tiers:

  • Global (zoom 0-6): single query across all verified photos
  • Per-tile (zoom 8-16): pre-computed tile keys, generated columns

Photos need verified >= ADMIN_APPROVED and is_public = true to appear in clusters.

PhotoObserver marks affected tiles dirty when photos are verified/moved. Team dirty tracking was removed — team clustering is on-demand only.

Testing Patterns

  • Base TestCase uses RefreshDatabase + Redis flush + TagKeyCache::forgetAll()
  • auth:sanctum routes: use actingAs($user) with NO guard arg
  • auth:api routes (legacy mobile): use actingAs($user, 'api')
  • Photo factory: set verified, is_public, summary, country_id explicitly
  • VerificationStatus assertions: compare enum directly or use ->value for ordering
  • Event::fake([TagsVerifiedByAdmin::class]) — fakes specific events, others still fire
  • Reset Spatie permissions cache: app()[PermissionRegistrar::class]->forgetCachedPermissions()
  • TeamType::create(['team' => 'community', 'price' => 0]) — price has no default

1033+ tests passing (1 skipped). See testing-patterns skill for full details.

Common Mistakes

  1. Forgetting is_public = true in admin/public queries — exposes school data
  2. Using ->verified == 2 instead of ->verified->value >= VerificationStatus::ADMIN_APPROVED->value — misses BBOX+ states and breaks due to enum cast
  3. Deleting before MetricsService — metrics can't reverse what they can't read
  4. Missing TagsVerifiedByAdmin constructor args — all 6 required (photo_id, user_id, country_id, state_id, city_id, team_id)
  5. Writing metrics directly instead of going through MetricsService — causes desync
  6. Forgetting whereNotNull('summary') in queue queries — untagged photos can't be approved
  7. Using old category relationships (Photo::smoking(), Photo::food()) — v4 deprecated
  8. Not wrapping tag edits in DB::transaction() — partial tag state causes summary corruption
  9. Gating summary generation behind trust check — summary MUST be unconditional (null summary = zero metrics at approval)
  10. Dispatching TagsVerifiedByAdmin for school students — breaks safeguarding invariant
  11. Using result_string or total_litter — deprecated write-only columns. Use summary and total_tags
  12. Treating Redis as source of truth — Redis is a derived cache from metrics table
  13. Using doesntHave('photoTags') for untagged filter — use WHERE verified = 0
  14. Mismatching actingAs() guard with route middleware — actingAs($user) for auth:sanctum, actingAs($user, 'api') for auth:api

Domain Documentation

Read the relevant file before working in that area:

DocumentCovers
readme/API.mdComprehensive API endpoint reference (source of truth)
readme/Tags.mdTag hierarchy, summary JSON, XP calculation
readme/Teams.mdTeams architecture, permissions, safeguarding, facilitator queue
readme/SchoolPipeline.mdSchool approval pipeline (critical data flow)
readme/Metrics.mdMetrics pipeline and aggregation
readme/Leaderboards.mdLeaderboard system (Redis ZSETs + MySQL)
readme/Admin.mdAdmin verification system, queue UI, roles
readme/Upload.mdPhoto upload pipeline
readme/Clustering.mdMap clustering system
readme/Locations.mdLocation and geography system
readme/Mobile.mdMobile app & v4-to-v5 tag conversion shim
readme/Profile.mdUser profile, settings, privacy, public profiles
readme/Email.mdEmail subsystem — campaign send + ledger, SNS suppression feedback loop, subscribe/unsubscribe

© OpenLitterMap, GPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .ai/skills/olm-architecture of OpenLitterMap/openlittermap-web.

Open the folder on GitHubat commit ac688aa

Compare with similar skills

Olm Architecture next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Olm Architecture compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Olm Architecture this skillOpenLitterMap/openlittermap-web134—~5.2kAutomated safety check: PassGPL-3.0
Configuring Horizoncoollabsio/coolify63k4 repos~898Automated safety check: PassMIT
Pulse DevelopmentMineTrax/minetrax1151 repos~1.7kAutomated safety check: PassMIT
AsyncTheBeardedBearSAS/claude-craft107—~741Automated safety check: PassMIT
Laravel Database ExpertHoangNguyen0403/agent-skills-standard571—~802Automated safety check: PassMIT
Laravel Sessions MiddlewareHoangNguyen0403/agent-skills-standard571—~830Automated safety check: NotesMIT

Similar skills

  • Configuring Horizon

    coollabsio/coolify

    A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.

    63k GitHub starsUsed in 4 repos~898 tokens
    Backend & APIsAuto-check passed
  • Pulse Development

    MineTrax/minetrax

    Handles Laravel Pulse setup, configuration, and custom card development.

    115 GitHub starsUsed in 1 repo~1.7k tokens
    Backend & APIsAuto-check passed
  • Async

    TheBeardedBearSAS/claude-craft

    Architecture async-first avec messaging et queues (Symfony Messenger, Laravel Queue, Ecotone).

    107 GitHub stars~741 tokensUpdated 24 days ago
    Backend & APIsAuto-check passed
  • Laravel Database Expert

    HoangNguyen0403/agent-skills-standard

    Optimize Laravel queries with subqueries, joinSub, Redis cache-aside patterns, and read/write connection splitting.

    571 GitHub stars~802 tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • Laravel Sessions Middleware

    HoangNguyen0403/agent-skills-standard

    Configure Redis session drivers, register security-header middleware, and prevent session fixation in Laravel.

    571 GitHub stars~830 tokensUpdated yesterday
    Backend & APIsAuto-check: notes
  • Geoflow

    yaojingang/GEOFlow

    Operate/develop GEOFlow CLI/Laravel/admin/API, topics/专题 and topic tasks, theme libraries/replication, sites/leads/Agent, channel sync and legacy yao-geoflow-cli/design/template migration.

    3.8k GitHub stars~722 tokensUpdated yesterday
    Backend & APIsAuto-check passed

More from OpenLitterMap/openlittermap-web

All 16 skills in this repo
  • Tailwindcss Development

    OpenLitterMap/openlittermap-web

    Styles applications using Tailwind CSS v3 utilities. An agent skill from OpenLitterMap/openlittermap-web.

    134 GitHub stars~713 tokensUpdated 24 days ago
    Auto-check passed
  • Achievements System

    OpenLitterMap/openlittermap-web

    AchievementEngine, AchievementRepository, milestone checkers, AchievementsSeeder, userachievements pivot, AchievementsController API, and achievement evaluation flow.

    134 GitHub stars~1.4k tokensUpdated 24 days ago
    Auto-check passed
  • Admin System

    OpenLitterMap/openlittermap-web

    AdminController, photo approval, tag editing, deletion, MetricsService integration, admin middleware, verification queue, and admin XP.

    134 GitHub stars~3.9k tokensUpdated 24 days ago
    Auto-check passed
  • API Endpoints

    OpenLitterMap/openlittermap-web

    REST API endpoints, route structure, auth guards, request/response contracts, error patterns, and the full API surface for web SPA and mobile clients.

    134 GitHub stars~4k tokensUpdated 24 days ago
    Auto-check passed
  • Clustering System

    OpenLitterMap/openlittermap-web

    ClusteringService, tile keys, dirty tiles/teams, clustering commands, ClusterController GeoJSON API, PhotoObserver dirty marking, and map cluster rendering.

    134 GitHub stars~2k tokensUpdated 24 days ago
    Auto-check passed
  • Leaderboard System

    OpenLitterMap/openlittermap-web

    LeaderboardController, Redis sorted sets for all-time XP rankings, per-user metrics rows for time-filtered rankings, rewardXpToAdmin, and leaderboard privacy.

    134 GitHub stars~2k tokensUpdated 24 days ago
    Auto-check passed

Works with

Questions about Olm Architecture

What does Olm Architecture do?

OpenLitterMap v5 architecture reference. An agent skill from OpenLitterMap/openlittermap-web. Olm Architecture is an agent skill from OpenLitterMap/openlittermap-web. OpenLitterMap v5 architecture reference.

When should I use Olm Architecture?

Olm Architecture fits situations like: working on OLM backend code; laravel controllers; any part of the OpenLitterMap codebase; the user mentions MetricsService.

How do I install Olm Architecture in Claude Code?

Run `npx skills add OpenLitterMap/openlittermap-web --skill olm-architecture -a claude-code`. Or copy the skill folder (.ai/skills/olm-architecture in OpenLitterMap/openlittermap-web) into .claude/skills/olm-architecture in your project. Claude Code loads it when a task matches its description.

How do I install Olm Architecture in Codex?

Run `npx skills add OpenLitterMap/openlittermap-web --skill olm-architecture -a codex`. Or copy the skill folder (.ai/skills/olm-architecture in OpenLitterMap/openlittermap-web) into .agents/skills/olm-architecture in your project. Codex loads it when a task matches its description.

Can I use Olm Architecture in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add OpenLitterMap/openlittermap-web --skill olm-architecture -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/olm-architecture, .gemini/skills/olm-architecture, .github/skills/olm-architecture and .opencode/skills/olm-architecture in your project.

What does Olm Architecture need to run?

SKILL.md names no scripts, command-line tools or credentials: Olm Architecture is instructions for the agent only.

Does Olm Architecture access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Olm Architecture safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Olm Architecture use?

Olm Architecture is published under the GPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Olm Architecture use?

About 5.2k tokens (SKILL.md is roughly 21k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Olm Architecture?

Skills that share tags, products or a category with Olm Architecture: Configuring Horizon (coollabsio/coolify, 63k stars), Pulse Development (MineTrax/minetrax, 115 stars), Async (TheBeardedBearSAS/claude-craft, 107 stars) and Laravel Database Expert (HoangNguyen0403/agent-skills-standard, 571 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Olm Architecture?

OpenLitterMap (a GitHub organization) maintains it in OpenLitterMap/openlittermap-web, which has 134 GitHub stars. The repository holds 16 skills in this directory. The repository was last updated on September 14, 2026.

Source: OpenLitterMap/openlittermap-web on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.