use-app-config
Skill61 starsChanged 56 days agoMITView on GitHub
Everything about APP-CONFIG — what the application IS: name, description, brand, logo and images, icons and PWA, author, SEO and OpenGraph, structured data, analytics, currency, the `nav` branch, and the open list of social networks (`seo.socialLinks`). Use when the owner says "change the site name", "put my logo in", "add my Instagram", "the footer shows the wrong Telegram", "set the description for search", "our Twitter is stale", or anything about the site's identity or its accounts. ALSO use BEFORE hard-coding any name, address, handle, brand string or profile URL into a component — every one of them already has a home here, and a hard-coded copy is invisible to the panel and to the owner.
- Sends data out
1 other project uses a version of this.
Adopted by
Most recently taken up by
- Fractera/Agent-Engineering-Infrastructureword for word, first seen Nov 8, 2026
Other versions1 project uses a version of this.
Word for word · 1
- Fractera/Agent-Engineering-Infrastructure★ 61100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository88 other files it gives its agents.
- app/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- adopt-suggested-skillSkill
- ai-elementsSkill
- ai-sdkSkill
- answer-elementSkill
- ask-elementSkill
- audit-broken-charactersSkill
- blocks-of-the-nodeSkill
- build-product-with-ownerSkill
- content-factorySkill
- core-build-returnSkill
- core-scheduleSkill
- create-elementSkill
- create-multilingual-content-entrySkill
- design-and-settings-of-elementsSkill
- element-powerSkill
- expand-site-languageSkill
- explain-this-projectSkill
- extract-design-systemSkill
- find-skillsSkill
- handle-block-requestSkill
- handle-needSkill
- help-in-browserSkill
- humanizerSkill
- integratorSkill
- know-the-architectSkill
- manage-app-settingsSkill
- node-typeSkill
- own-agentsSkill
- persist-env-var-with-rebuildSkill
- place-page-in-menuSkill
- provider-rulesSkill
- release-templateSkill
- review-pageSkill
- route-to-elementSkill
- self-reviewSkill
- shadcnSkill
- shape-the-needSkill
- skill-creatorSkill
- study-for-elementSkill
- supervise-elementSkill
- translate-pendingSkill
- ultracode-sessionSkill
- use-agentic-ragSkill
- use-ai-generationSkill
- use-aioSkill
- use-auth-providersSkill
- use-authSkill
- use-browserSkill
- use-channelsSkill
- use-chatSkill
- use-code-shapeSkill
- use-databaseSkill
- use-dataSkill
- use-deep-memorySkill
- use-deploySkill
- use-designSkill
- use-development-stepsSkill
- use-domainSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 132
Never suggest a redeploy to make a config change take effect.
- Distinctive: line 136
Every site name, support address, brand string, profile URL or handle written into a component is invisible to the panel: the owner edits …
- Distinctive: line 141
If a value genuinely has no home here, add the field (section 2) — do not inline it.
- Very specific: line 146
Check the markup, not only the pixels: sameAs, OpenGraph, the Twitter card and the manifest all read this config, and each can go stale on …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
use-app-config
Informational, not binding. Know a better way for the case in front of you — do it your way and say so. You are trusted with the creative work on this project.
The file is APP-CONFIG/app-config.json in the project root. The panel (:3002) writes it,
this application (:3000) reads it — per request. A saved change shows on the next page load:
no rebuild, no redeploy.
import { getAppConfig } from "@/config/app-config" // server only — it touches fsReading a file does not make a route dynamic. Pages stay static; force-dynamic would break that
and is not used here.
🔒 This layer only READS. It never writes. The panel owns the file. A helper here once created it from the defaults on first read — two writers, and the panel stopped being the single answer to "what is this app called".
🔒 A missing file is normal, and so is a partial one. The JSON holds only the owner's
decisions; config/app-config.defaults.ts answers for everything else, deep-merged underneath.
Seeing {} and concluding "empty, so it cannot be working" cost a whole session on 2026-08-18.
1. APP-CONFIG or PLATFORM-CONFIG — decide before you touch anything
The split is the owner's, and it is sharp:
| Question | Config | Example |
| Does this capability EXIST at all? | PLATFORM-CONFIG | "I don't want to see socials" → switch socials |
| WHAT is in it? | APP-CONFIG | "my Telegram is @aifa_dev" → seo.socialLinks |
Get this backwards and you offer the owner the wrong tool. Before the socials switch existed,
the icon row appeared merely because records existed — the only way to hide it was to delete the
data, which is not what "hide it" means. See use-platform-config.
2. A field lives in FOUR places
Changing a VALUE is ordinary work. Adding a FIELD is not: three of the four omissions are silent.
| # | Where | Miss it and |
| 1 | config/app-config.defaults.ts — the type | the build fails, loudly. The only honest failure. |
| 2 | config/app-config.defaults.ts — the default | an owner who never spoke gets undefined |
| 3 | config/app-config.schema.ts | validation strips the unknown key on save — silently |
| 4 | APP-CONFIG/{schema,defaults}.json | check:config-schemas fails the build on the server |
Number four is generated, never hand-written: npm run build:config-schemas. The fifth place —
the form in the panel (bridges/app/app/[lang]/app-settings/_lib/fields.ts) — is in another
repository, and a field absent there exists but cannot be edited by the owner.
3. Social networks — a record carries its RULE, not just a value
{ id: "telegram", name: "Telegram", urlTemplate: "https://t.me/{value}", value: "aifa_dev", icon: "/api/media/…/file" }The address is computed, not guessed. That is the whole point: every network spells its
profile differently — t.me/<handle>, wa.me/<number>, and a LinkedIn PERSONAL profile is
/in/, not /company/. A free text field knows none of this and silently builds a dead link.
import { resolveSocialLinks, socialHref, socialUrls, twitterHandle } from "@/config/app-config.defaults"resolveSocialLinks(cfg.seo) is the single place that decides what to show. Pass it cfg.seo,
never cfg.seo.social:
🔒 socialUrls(cfg.seo.social) compiles, runs, and is wrong. The function keeps a
compatibility path for that older call shape, so it answers with the four legacy keys only and the
open list never reaches the caller. That is exactly how sameAs came to tell machines
twitter.com/fractera — a starter default belonging to nobody — while the footer correctly showed
the owner's Telegram. Nothing throws. It is found only by reading the rendered sameAs.
🔒 "No branch" and "empty branch" are different states. socialLinks absent means the owner
never opened the constructor, and the four legacy seo.social keys still answer. socialLinks: []
means he removed every record on purpose, and resurrecting the legacy four would overrule a human
decision. The resolver tests Array.isArray, not .length — do not "simplify" that back.
🔒 The legacy four are read VERBATIM, bugs included. linkedin builds /company/, which is
wrong for a personal profile. Fixing the rule retroactively is forbidden: live servers hold values
entered under that rule, and changing the template would silently point a working link somewhere
else. New records get their rule from the model and inherit none of this.
Icons are copied INTO the project, never linked from a foreign CDN. The panel downloads the
SVG once (api/config/social-icon, source cdn.simpleicons.org, licence CC0-1.0 verified at the
source) and stores it in the media library; the record keeps /api/media/<id>/file. A CDN link
would put every visitor of every page on someone else's host and leave holes when
offlineCache serves the page offline. lucide carries almost no brand marks — that is why
BrandX in the footer is drawn by hand.
sameAs is not gated by the socials switch, and that is deliberate. Hiding the row is a
layout decision; sameAs is the site's claim to machines that these accounts are its own.
4. Language: which fields are translated, and how
Five fields are per-language — name, description, seo.titleTemplate, seo.keywords,
og.siteName. The main value is the field itself; other languages live in i18n.<path>.<lang>.
Everything else (logo, colours, coordinates, analytics ids, handles) does not depend on language,
and giving it a translation would be work with no reader.
Machine values are never translated: ids, slugs, enum values, urlTemplate.
5. Making a change visible
- Saving from the panel purges the app's ISR cache — the change shows on the next load.
- Editing the file by hand purges nothing: the page keeps its old HTML until the ISR window expires, up to ten minutes. That is the entire content of "I changed it and nothing happened".
curl -X POST http://127.0.0.1:3000/api/revalidate \
-H "Content-Type: application/json" -H "x-agent-identity: agent" -d '{}'A browser tab can also hold a page from before the purge. Fetch with cache: 'reload', or hard
reload, before declaring anything broken — a stale tab has produced more than one false verdict.
Never suggest a redeploy to make a config change take effect.
6. Do not hard-code identity
Every site name, support address, brand string, profile URL or handle written into a component is
invisible to the panel: the owner edits the setting, nothing moves, and the value rots where no
one looks for it. The Twitter card read seo.social.twitter directly for exactly this reason and
lost the author for every owner who used the constructor.
If a value genuinely has no home here, add the field (section 2) — do not inline it.
7. Before you call it done
- Change the value in the panel, not in the file, and confirm it in a browser.
- Check the markup, not only the pixels:
sameAs, OpenGraph, the Twitter card and the manifest all read this config, and each can go stale on its own. - Count elements, not words. Grepping the HTML for
twitterproves nothing — the word lives insameAs, in class names, in comments. Count<a href=…>. Measuring by words once produced the confident verdict "the socials gate is broken" about a gate that worked. npm run check:types, andcheck:config-schemasif you touched a type or a default.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

