Skip to content

Contribute a Docs tab to the projects hub, and move slug generation onto locale_slug - #39

Open
mdon wants to merge 4 commits into
BeamLabEU:mainfrom
mdon:main
Open

Contribute a Docs tab to the projects hub, and move slug generation onto locale_slug#39
mdon wants to merge 4 commits into
BeamLabEU:mainfrom
mdon:main

Conversation

@mdon

@mdon mdon commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

A per-project Docs tab contributed through the hub's extension contract.

Depends on the projects hub PR

This contributes a tab to the projects hub through
phoenix_kit_project_extensions/0 — the hub's duck-typed, one-way contract,
so there is no package dependency in this direction. The consuming side is
BeamLabEU/phoenix_kit_projects#35, which in turn depends on
BeamLabEU/phoenix_kit#692. Merge those first, or the tab simply never
appears.

Verification

mix test — 1566 tests, 0 failures; mix precommit — exits 0.


Also on this branch: slug generation moved onto locale_slug

Pushed to the same branch, so it rides along with the work above. Separate concern, noted
here because a reviewer reads this description before the commits.

This module had its own hand-rolled slugifier that deleted every non-ASCII character, so a
Cyrillic or Greek name produced an empty slug and German lost its umlauts and ß:

input before after
Видеопродакшн "" videoprodakshn
Καλημέρα "" kalimera
Größe Fußball gre-fuball grosse-fussball

An empty slug is worse than a wrong one — callers read it as "no slug yet" and regenerate
on every save. It now delegates to PhoenixKit.Utils.Slug, backed by the
locale_slug package, so there is one
implementation for the whole ecosystem rather than a copy per repo.

Stored slugs are not rewritten; generation only runs when the slug is blank.

⚠️ This part requires the phoenix_kit release carrying the locale-aware Slug
(BeamLabEU/phoenix_kit#692). The rest of this PR does not.

mdon and others added 3 commits August 5, 2026 12:04
phoenix_kit_project_extensions/0 (the hub's duck-typed provider
contract, mirroring the OG-variables pattern of cross-module surface
declarations): a 'publishing_docs' extension whose Docs tab config-links
ONE publishing group per project. Groups are slug-keyed across this
package (there is no get_group_by_uuid), so the config stores the SLUG;
the unconfigured state lists group names + slugs to copy.

Read-only: the group's PUBLISHED entries (metadata title with slug
fallbacks, published_at/date) with link-outs to the publishing admin
editor and a New-entry CTA, capped at 25 with an honest showing-N-of-M
line. Off-router tab LV per the hub contract; every context call
rescues to the empty state so a publishing hiccup can't crash the host
project page.
publishing_group.ex derived its slug with an ASCII-only pipeline, so a Cyrillic
or Greek group name produced an EMPTY slug. Now delegates to
PhoenixKit.Utils.Slug (backed by locale_slug).

SlugHelpers already delegated to core, so this closes the one place that did
not.

Stored slugs are not rewritten. Requires the phoenix_kit release carrying the
locale-aware Slug (BeamLabEU/phoenix_kit#692). Verified against local core:
1563 tests, 0 failures.
@mdon mdon changed the title Contribute a Docs tab to the projects hub Contribute a Docs tab to the projects hub, and move slug generation onto locale_slug Aug 9, 2026
Caught by the upstream review of phoenix_kit_dashboards#5, which found the same
defect there and had to repair it after merge.

PhoenixKit.Utils.Slug.slugify/2 defaults :transliterate to FALSE on every core
released so far. So `Slug.slugify(text)` strips every non-ASCII character —
exactly what the local pipeline this change replaced did. The delegation was
correct and the behaviour was unchanged.

My verification missed it because I tested against local core, where I had made
transliteration the default. Against the core these modules actually resolve, it
was inert. That is the difference between "the code is right" and "the shipped
artifact is right", and only the second one matters.

Forward-compatible: once core ships the locale-aware Slug, :transliterate is
accepted and ignored, so this stays correct.

The pinning tests are rewritten to assert only what holds at EVERY core version.
Asserting output was the second half of the same mistake: each module resolves a
different core (posts' lockfile pins 1.7.189, which predates the :transliterate
option entirely), so a literal expected slug merges red.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant