type
concept
created
Mon Apr 06 2026 02:00:00 GMT+0200 (Central European Summer Time)
updated
Mon Apr 06 2026 02:00:00 GMT+0200 (Central European Summer Time)
sources
raw/notes/systemPatterns
tags
routing frontend architecture

Slug-Based URLs

abstract
Human-readable URLs using property name slugs and unit numbers instead of numeric IDs and UUIDs.

URL Format

Page Old URL New URL
Property detail /property-management/42 /property-management/ashford-farms-ii
Unit detail /property-management/42/buildings/15/units/d4d48f48-... /property-management/ashford-farms-ii/units/1535

How It Works

Slugify Function

A shared slugify() utility in property.service.ts converts property names to URL-safe slugs:

"Ashford Farms II" → "ashford-farms-ii"
"Aspen at Brookfield" → "aspen-at-brookfield"

Route Definition

// app.routes.ts
{ path: 'property-management/:propertySlug/units/:unitId', ... }
{ path: 'property-management/:id', ... }

Property Detail Resolution

Property detail accepts both IDs and slugs (backward compatible). It fetches all properties and matches:

  1. First by property.id === param
  2. Fallback by slugify(property.name) === param

Unit Detail Resolution

The unit-detail component detects whether the unitId param is a UUID or a unit number:

Backend Endpoint

server.js provides /api/units/by-name/:propertySlug/:unitNumber:

  1. Fetches all properties, finds one whose slugified name matches
  2. Queries units_unit by property_id + unit_number
  3. Falls through to the standard UUID detail handler

Navigation Flow

Properties list (slugified links)
  → Property detail (resolves by ID or slug)
    → Unit square click → goToUnit() uses slugify(property.name) + unit_number
      → Unit detail (resolves by UUID or property-slug + unit-number)
        → Back button uses slugify(property.name) to return

Key Files

File Role
src/app/core/services/property.service.ts slugify() utility + getUnitByName() API
src/app/app.routes.ts Route: /:propertySlug/units/:unitId
src/app/features/properties/unit-detail.component.ts UUID vs unit-number detection in ngOnInit()
src/app/features/properties/property-detail.component.ts goToUnit() uses slug + unit number
src/app/features/properties/properties.component.ts Property card links use slug
server.js /api/units/by-name/ endpoint

Enforcement

This is a non-negotiable project rule (CLAUDE.md rule #11). It is enforced at three layers:

Layer File What it says
Project rules CLAUDE.md Rule #11: slug-based URLs only, never raw IDs/UUIDs
Frontend agent agents/angular-frontend.md Routing section: slug patterns, slugify() usage, backward-compat resolution
Backend agent agents/django-backend.md URLs section: every entity needs a by-name resolution endpoint

For any new entity that gets its own detail page, you must:

  1. Choose a human-readable identifier (name slug, number, code — never database ID)
  2. Add a by-name endpoint in server.js (or Django) to resolve the slug
  3. Use slugify() in frontend navigation
  4. Handle both slug and UUID in the component for backward compatibility

Sources

Related