Field Meanings — Working Draft

Anatomy of a Part

What each identifying field across the Smart Manual is supposed to mean, what the app actually does with it, and where those two have come apart.

Smart Manual 12 areas Components traced in full 31 August 2026
Working draft

Written so the conversation has something specific to argue over. Components are traced field by field as the worked example; the other areas follow at the depth their problems warrant. Nothing in it is settled.

Start here

What this is and how to move around it

Different people at CFC and at Rock Agile have been using words like UID, title, part number and description to mean different things. That is not anyone's fault - the Smart Manual has never had a written record of what its fields are for, so everyone reasonably filled in the gaps their own way.

This document closes that gap. It goes through every field that identifies or describes something, sets what the field is supposed to mean against what the software actually does with it, and marks the places where those two have come apart. It ends with one coherent proposal for what the whole set should look like.

It is a working draft, built for a conversation rather than for signing off. Once the questions in it are settled, a finished reference follows.

Why a site

The question that started this was a small one: is the UID field used for such-and-such? We expected to answer it in a paragraph.

Tracing it properly turned up a great deal more than we anticipated - not just about UID, but about how several fields relate to each other, and how what is written down has drifted from what the software does. It became clear fairly quickly that a linear document would be difficult to hold in your head, and that burying the important parts in the middle of the detail would defeat the purpose.

So we built this instead. It keeps everything in one place, lets you jump straight to whatever you need, and gives the detail somewhere to live without obscuring the point. It also gives us a shared reference to work from during the discussion rather than a file being emailed back and forth.

Three ways to read this, depending on your time

  1. Ten minutes. Read Findings, then The proposal. That is the whole argument: here is what is wrong, here is what right would look like. Everything in between is the evidence for it.
  2. Coming to decide something. Start with What good looks like, which ends with the open questions we need answers to. Each question links back to the detail behind it if you want to check our reasoning before answering.
  3. Checking a specific field. Go straight to the area that holds it. Every field entry shows its written description on the left and what the software actually does on the right, so you can see exactly where the two disagree.

The eight sections

Each one is a separate page. Use the list on the left to move between them.
SectionLengthWhat is in it
02 · FindingsShortThe three things that most need attention, with the numbers behind each. If you read nothing else, read this.
03 · ComponentsLongThe worked example, traced field by field. Opens with a summary table you can scan; every row links down to the full entry. This is where the collision-risk comparison of the different identifiers lives.
04 · ManualsMediumITMs. The only place a name is genuinely protected against duplicates, plus the download-filename problem.
05 · CategoriesMediumThree generations of naming running at once, and a translation split that is the wrong way round.
06 · Other areasMediumBOMs, schematics, machine states, assemblies, photos, troubleshooting, documents, videos, companies and download packages.
07 · Behind the scenesMediumBehavior that applies system-wide rather than to one area, and which explains most of the surprises elsewhere. The per-manual vocabulary explanation is here.
08 · What good looks likeMediumOur opinion on the right end state, and the open questions we need CFC to settle.
09 · The proposalMediumThe complete redesigned field set, area by area, with every field marked as kept, renamed, split, fixed or removed - and what getting there would involve.

Two conventions worth knowing before you start

The coloured tags. Every field carries one. As intended means the software does what the description says. Diverges means it does not. Unused means the field does nothing at all. By design means it is deliberately left alone. In the proposal section the tags change to describe the change itself - Renamed, Removed and so on.

The small grey text on the right of each list. Those are references into the code - the exact file and line that produces the behavior being described. They are there so any claim in this document can be checked rather than taken on trust. You can safely ignore them; nothing depends on reading them.

Quoted italic text is always lifted word for word from the descriptions that ship inside the CSV import templates. We have not paraphrased any of them.

What we found

Three things worth your attention

These hold across every area we looked at, not just components.

4 different written
meanings for the
single field "UID"

The written field descriptions no longer match the product

Every field has a written description - the explanatory row inside the CSV templates. On components, twelve of the sixteen describe behavior the app does not have. The pattern repeats everywhere else.

UID is the clearest case. It exists in four areas and is described two incompatible ways: on components as the schematic tag number, and everywhere else as something "auto-generated if blank". Neither is true - it cannot be filled in at all, and nothing is ever generated. Elsewhere the gaps are smaller but the same shape: Slug is described as filled in "if blank" when it is rebuilt on every save, and Component Description is described as a short summary when it is in fact the large heading on the component sheet.

5 different fields that
could each be called
"the identifier"

Nothing has ever settled which field is a record's real name

On a component there are five candidates: internal id, UID, Slug, Brand/Part Number and Title. In conversation people reach for UID or part number. The app opens every component page by internal id, sorts and de-duplicates by Title, and never reads UID at all.

Only two names anywhere in the system are actually protected against duplicates: a manual's Title and a company's Title. Everything else - BOMs, documents, videos, categories, machine states - permits duplicates freely, and several of those unprotected titles are what imports match on.

Slug is the sharpest edge and the one we would fix first. When a schematic, photo, assembly or BOM links to a specific component, the Slug is the piece of the web address after the # that tells the browser where to land. It is rebuilt from the Title on every save. Rename a component and every link that pointed at it stops landing on it - the page still opens, the reader arrives in the wrong place, and there is no record of the old value.

Worth saying clearly

The internal id is not part of this problem and should stay exactly as it is. Every record in every serious system carries a plain sequential number like this, and it is good practice.

The two do different jobs. The internal number lets the software find one exact record instantly - short, never changes, never shared. A human-readable identifier like P-105.2 does the opposite job: it has to mean something to an engineer reading a schematic, which makes it longer, slower to match on, and fragile, because people edit and mistype it. Keeping both is the standard arrangement, and when two things do get mixed up by human error, the internal number is the thread back.

The open question is only which field is the human-readable identifier sitting alongside it.

6 CSV columns that
do not survive being
exported and re-imported

The CSV round trip does not round trip

Export a BOM, edit it, import it back, and you do not get the BOM you started with. Slug is overwritten. UID and Parent UID come out empty. Order ID, Category Order ID and Shared are read from your file and then dropped.

The importer also only ever creates. Updating by import is not supported today, and cannot be until we settle which field is the reliable identifier - there is nothing dependable to match an incoming row against. That is what limits everything else here: there is currently no supported way to apply an agreed convention to the manuals already in the system.

The same pattern holds in every area. Manuals offer nine import columns that are ignored, including the two that set up a manual's entire vocabulary. Machine states offer one with a blank description. In each case the template promises more than the importer delivers.

Components

Component fields at a glance

Status compares the written description of each field against what the app actually does with it. Nothing here says the current behavior is wrong - only whether it matches what the description promises.

FieldStatusThe short version
Identifiers
internal idAs intendedThe app's own reference number. Not shown anywhere, not a problem, and should stay.
UIDUnusedDescribed as the schematic tag number. Cannot be filled in by anyone, shown nowhere, never read.
Brand/Part NumberAs intendedBehaves as described. May be the same concept UID was meant to capture.
TitleDivergesDescribed as the display title. Actually fills the BOM's Item Number column, and is what makes a component unique.
SlugDivergesDescribed as auto-filled if blank. Rebuilt from the Title on every save, breaking existing links.
Parent UIDDivergesA column named UID that the importer matches on Title instead. Exports empty.
Descriptions
Component DescriptionDivergesDescribed as a concise summary. Actually the component sheet's page heading, and it prints twice.
BOM DescriptionDivergesShares one renameable label with Component Description, on two different pages.
Safety Notes, Function, eBook Link, Image FooterAs intendedFree text, behave as described, no role in identifying anything.
Grouping and ordering
CategoryDivergesFree text typed onto the component. Unrelated to the Categories elsewhere in the app, despite the shared name.
Order ID, Category Order IDDivergesDescribed as importable. Both are ignored on import, for two different reasons.
SharedDivergesDescribed as importable. Ignored on import.
TagsDivergesDescribed as used for filtering and search. BOM search does not look at them.
Linked media
Video LabelsDivergesGives one video a different name on every component that links it. Exporting it currently fails.
Image, Annotated Image, Annotation DataBy designDescribed as "leave blank" on import; the importer correctly leaves them alone.

Components

Component fields, one by one

Quoted text on the left is the description that ships in the parts CSV template. The small grey references on the right point to the exact place in the code, so any claim here can be checked.

Identifiers

The fields that could each be called a component's name, plus the one that resolves parents. The internal id is covered above and needs no changes.

What these fields are actually for, and which ones can be trusted

It is worth stating the purpose plainly, because it shapes the answer. These identifier fields exist so that data can be brought in - so a BOM can be built in Excel, using the numbering a manufacturer or a plant already uses, and imported without anyone retyping it.

That means accepting outside identifiers is not a compromise, it is the whole point. A number that means something to the engineer who wrote the spreadsheet is far more useful than one the Smart Manual invented. The only hard requirement is that whatever we accept has to reliably point at one component - otherwise an import cannot tell whether a row is a new component or an edit to an existing one.

Not all of these fields are equally good at that. Ranked by how likely two different components are to end up with the same value:

IdentifierCollision riskWhy
Internal id None Assigned by the system, never reused, guaranteed unique. Also meaningless to a human, which is why it cannot be the only answer.
Brand + Part Number together Very low A manufacturer does not reuse its own part numbers. The pair is what makes it dependable - and this pairing is already how the Brand/Part Number field is described.
Part Number alone Moderate Manufacturers reuse each other's numbering constantly. The same short number from two different vendors is two entirely different components. Nothing currently stops duplicates.
Title High Typed by hand, and only guaranteed unique within a single BOM. The same title in two BOMs is two different components, and the system is fine with that.
Slug Highest Inherits every Title collision and adds more, because punctuation and spacing are stripped out. "Pump, Hydraulic" and "Pump / Hydraulic" become the same value.
UID Unknown No rule prevents duplicates, and the field is empty everywhere, so there is no evidence either way.

Our suggestion is that Brand + Part Number becomes the identifier that imports match on, and that the pair is required and enforced unique. It is the only candidate that is both meaningful to the people writing the spreadsheets and reliable enough to match on. We can build that enforcement.

Two things follow that CFC should weigh before agreeing. It becomes a requirement: every component would need both a brand and a part number, and the system would start refusing duplicates - which will surface existing collisions in the current data that nobody has had to resolve until now. And because part numbers can differ per language, the uniqueness rule has to cover both places a part number is stored, not just one.

There is also a scope question we cannot answer for you: should a brand and part number be unique across the entire Smart Manual, or only within one manual? Unique everywhere is what would let one component be shared across several BOMs without being duplicated, which is what the existing Shared setting is reaching for. That is our recommendation, but it is a judgment about how CFC thinks about parts, not a technical one.

UID text · added February 2026 · empty everywhere Unused
Described as

"Unique Identifier. This unique number should be displayed as a tag next to the specific component's symbolic representation on a schematic. A UID in the ITM usually consists of an alphabetical prefix, e.g. 'P-' indicating the subsystem the component is associated with, followed by a unique number, e.g. '105' as indicated on a schematic and/or bill of materials. And sometimes a numeric suffix indicating a unique component of a given quantity, e.g. '.2'."

What the app does

Nothing at all. It is never shown on a schematic, in the BOM, on the component sheet, or anywhere in the admin screens.

There is no screen where it can be typed in, and the importer does not save it, so a populated UID column in an import file has no effect. The field is empty for every component in the system.

Nothing searches or matches on it, and nothing prevents two components from being given the same value if one were ever entered.

Where it appears
  • As a column in the CSV export, always blankpart.rb:188
  • In the import-failure email, as a fallback label when a failed row has no Titlecsv_import_notification.html.erb:65
The likely explanation

The thing this description names is real and is in the data. A tag of the form the description itself gives as an example - P-105.2, prefix plus schematic number plus suffix - exists on components today, stored in the Title field.

Our suspicion, which needs your confirmation, is that UID and Brand/Part Number were two names for the same idea all along, and that UID was only ever meant for components. If so, this field should go away.

Also applies elsewhere

The same field was added to components, categories, machine states and ITMs in one go, and behaves identically - which is to say not at all - on all four. See The UID field.

Brand/Part Number text · translated per language As intended
Described as

"This is the Brand or Manufacturer of the component followed by its part number. Typically this information is as presented by the manufacturer."

What the app does

Behaves as described. It appears in the BOM list, in its own section on the component sheet, and in brackets beside each subcomponent link. It is one of the two fields the BOM search box looks at.

The one caveat is visibility. Whether this column appears in the BOM at all, and what it is called on screen, are both settings on the manual rather than properties of the field. The CSV calls it Brand/Part Number; a given manual may label it anything.

Nothing currently stops two components carrying the same value, and a part number on its own is not reliably unique - manufacturers reuse each other's numbering freely. That is why our recommendation is the brand and the number together rather than the number alone.

Where it appears
  • BOM list, in its own column, on components and subcomponents alikeparts/index.html.erb:65, 108
  • Component sheet, in its own labelled sectionparts/show.html.erb:67–69
  • Component sheet, in brackets after each subcomponent linkparts/show.html.erb:88
  • The BOM search box, matched alongside Titlepart.rb:85
Open question

If this field and UID were always the same concept, this is the one that survives - it is populated, it is displayed, and it is searchable.

Title text · translated per language · must be unique within a BOM Diverges
Described as

"The full display title of the component."

What the app does

In the BOM list, Title is what fills the Item Number column - the column the UID description above says the tag number belongs in.

It is not the heading of the component sheet. On that page it appears only as the hidden text behind the image and inside subcomponent links.

It quietly carries four other jobs that nothing in its description implies: it is what makes a component unique within its BOM, it is what the Slug is rebuilt from, it is the fallback sort order, and it is what the importer uses to find parents, BOMs, documents and videos.

Where it appears
  • BOM list, Item Number column - public and admin, if the manual has that column switched onparts/index.html.erb:58
  • BOM list, indented subcomponent rowsparts/index.html.erb:102
  • Component sheet, as the image's alternative textparts/show.html.erb:98
  • Component sheet, as the wording of subcomponent linksparts/show.html.erb:87
  • The BOM search box, matched alongside Brand/Part Numberpart.rb:82–85
  • Sort order within a BOM, after Order IDpart.rb:78
  • The rule that stops two components in one BOM sharing a namepart.rb:73
  • Rebuilding the Slug, every time a component is savedhas_slug.rb
Impact

Two components in one BOM cannot share a Title. If schematic tag numbers are being entered as Titles, that rule has been quietly enforcing tag uniqueness by accident - and it is also why re-running an import produces errors instead of updates.

Also applies elsewhere

Title is translated, so the stored value may differ from what a reader sees in another language. See Fields that vary by language.

Slug text · translated per language · rebuilt on every save Diverges
Described as

"URL-friendly identifier (auto-generated from Title if blank)."

What the app does

Not "if blank". It is rebuilt from the Title every single time a component is saved, whatever was there before. Anything supplied in the CSV Slug column is overwritten immediately.

It does appear in web addresses, but not the part that identifies the component. It is the piece after the # - the part that tells the browser where to scroll to once the page has loaded.

Every link from a schematic, photo, mechanical assembly or the BOM to a specific component uses it to land the reader in the right place.

Where it appears
  • The landing point on the component sheet that incoming links aim atparts/show.html.erb:1
  • Links out to the schematic, second schematic, photo, mechanical assembly and BOM - as the # portion of each addressparts/show.html.erb:28–47
  • Behind the BOM list rows, used when expanding subcomponentsparts/index.html.erb:47
  • As a CSV column - exported, then ignored on the way back inhas_slug.rb
Impact

Renaming a component silently changes where links to it land. Anyone who bookmarked or shared a link to that component still reaches the page, but no longer arrives at the right spot on it. Nothing warns about this, and there is no record of the previous value.

We found this behavior during this analysis. It had not been identified before.

Also applies elsewhere

The same rebuilding happens on every other kind of record that has a Slug. See Slug rebuilding.

Parent UID CSV column only · sets the subcomponent relationship Diverges
Described as

"UID of the parent part if this component is a subcomponent of another."

What the app does

On import, this value is matched against the parent's Title, ignoring capitalisation. Matching on UID would fail for every row, since that field is empty everywhere.

On export, the column emits the parent's UID, which is blank. An exported file therefore cannot be re-imported with its subcomponent structure intact.

When no match is found, the warning reads Parent UID 'X' not found - where X is actually a Title.

Where it appears
  • The import preview screen, in the warnings listparts_csv_importer.rb:65–73
  • Linking subcomponents to parents after an import completesparts_csv_importer.rb:184, 187–188
  • As a CSV export column, reading the parent's empty UIDpart.rb:102–104
How this came about

When the importer was built on 25 February 2026, the UID field did not exist anywhere in the system - it arrived the following morning. Title was the only thing there was to match on. The work to switch this over was written down at the time and flagged as unfinished, then never scheduled.

Impact

Because matching is by Title, two components sharing a Title in different BOMs can attach to the wrong parent, and renaming a parent breaks any later import that refers to it.

Descriptions

Two fields with overlapping names that appear in different places under the same label.
Component Description long text · translated per language Diverges
Described as

"This description of a component is more concise and practical and succinctly describes its unique role in a system/subsystem."

What the app does

It is the large heading at the top of the component sheet. The page's headline is this description, not the Title.

It then appears a second time on the same page, as the body of the section underneath - the section headed by whatever the manual calls its "description" label.

It does not appear in the BOM list at all. That column shows BOM Description instead.

Where it appears
  • Component sheet, as the page headingparts/show.html.erb:5
  • Component sheet, again, as the body of the description sectionparts/show.html.erb:62
  • The CSV column named Component Descriptionpart.rb:196
Impact

Anyone writing a "concise and practical" description is unknowingly writing the page title, and it prints twice on the page.

BOM Description long text · translated per language Diverges
Described as

"This description of the component consists of more formal part nomenclature as it appears on a Bill of Materials. It is usually using the naming conventions of a given facility/organization or of the manufacturer of the component."

What the app does

Exactly what the description says - it fills the description column in the BOM list, in both the public and admin views, including on subcomponent rows.

The problem is the label above it. That column's heading comes from the manual's "description" setting, and the same setting also heads the component sheet section that shows Component Description. One renameable label, two different fields, two different pages.

Where it appears
  • BOM list description column, public viewparts/index.html.erb:62, 105
  • BOM list description column, admin viewadmin/parts/index.html.erb:70, 125
  • The CSV column named BOM Descriptionpart.rb:199
Impact

Renaming the "description" label for a manual changes both at once. There is currently no way to call the BOM column one thing and the component sheet section another.

Also applies elsewhere

Column names and which columns appear are settings on each manual, not properties of the field. See Column names are set per manual.

Grouping and ordering

How components are sorted and gathered together within a BOM.
Category text · typed freely · not translated Diverges
Described as

"Category name for grouping within the BOM."

What the app does

Grouping works as described, but this is free text typed onto each component. It has no connection to the Categories elsewhere in the app - the ones with their own titles, display names and navigation, which are an entirely separate thing that happens to share the word.

The admin form offers suggestions drawn from values already used in that BOM, which limits drift but does not prevent it. Two spellings produce two groups.

Unlike nearly every other text field on a component, this one is not translated.

Where it appears
  • Grouping components within a BOM listschema.rb, parts indexes
  • The suggestion list in the admin component formpart.rb:115–121
  • The CSV column named Categoryparts_csv_importer.rb:94
Impact

"Category" means two unrelated things in this application depending on which screen you are looking at. This is the single most likely source of people talking past each other.

Order ID · Category Order ID · Shared two numbers and a yes/no · all ignored on import Diverges
Described as

"Numeric sort order within the BOM (0 = first)." / "Numeric sort order of the category grouping." / "true or false; makes the part available across multiple BOMs."

What the app does

All three work correctly inside the app. Order ID is the main sort order for every BOM list, Category Order ID puts the groups in sequence, and Shared makes a component available to more than one BOM.

None of the three are read by the importer, and the reasons differ. Category Order ID has a genuine structural obstacle: the grouping it would order is free text rather than a defined list, so there is no single thing to attach an order to. Two rows in the same file could give the same group different positions, and the importer would have no basis for choosing.

Order ID and Shared have no such obstacle. Both sit directly on the component and could be filled in from the file. They simply are not, and that is a straightforward gap rather than a design constraint.

Where it appears
  • The default sort order applied to every BOM listpart.rb:78
  • The filter that finds components shared across BOMspart.rb:81
  • CSV export columns - filled in on the way out, ignored on the way back inparts_csv_importer.rb:84–95
Impact

Anyone who exports a BOM, reorders it by editing the Order ID column, and imports it back will see no change to the ordering and no message explaining why.

Tags list of words · not translated Diverges
Described as

"Comma-separated list of tags for filtering and search."

What the app does

Tags appear in the BOM list, and the importer reads them correctly from a comma-separated list.

The BOM search box does not look at them. It searches Title and Brand/Part Number only, so searching for a tag returns nothing.

The Tags column is also the only BOM column with a fixed English heading. It cannot be renamed for a manual, cannot be switched off, and is not translated.

Where it appears
  • BOM list, in an always-visible Tags column, on components and subcomponentsparts/index.html.erb:42, 88, 132
  • Reading the comma-separated list during importpart.rb:177–184

Linked media

Videos and images attached to a component.
Video 1–3 Label text · stored on the link between component and video Diverges
Described as

"Editable title that will display under the Video icon on the Component Sheet. Since the video content may differ, e.g. technical information, safety warnings, troubleshooting procedures, etc., the title is editable to better describe the subject matter in the video."

What the app does

Works as intended, and the design behind it is deliberate. The label is stored on the connection between a component and a video rather than on the video itself, so one video can be named differently on every component that uses it. Where no label is set, the icon simply reads "Video".

The consequence for identification is that a video has no single name. It has its own title, plus a separate label for each component it appears on.

Separately, exporting these labels to CSV currently fails. The export asks the video for a label, but the label is not stored on the video - it is stored on the connection. Exporting a component that has at least one video should produce an error.

Where it appears
  • Component sheet, as the caption under each video iconpart_video.rb, display_label
  • Import, one label for each of up to three video slotsparts_csv_importer.rb:136–146
  • CSV export columns Video 1–3 Labelpart.rb:261–286
To be confirmed

The broken export is a straightforward defect rather than a question of meaning, and we found it by reading the code rather than by running it. Worth confirming against a real export before acting on it.

Manuals

ITMs

The top-level record. Everything else in the system hangs off one of these, which makes its identifiers the ones with the widest reach.

The one place a name is genuinely protected

A manual's Title must be unique across the entire Smart Manual - not per company, not per customer, globally. This is the only such rule in the whole system besides the one on company names. Everything else permits duplicates.

That is worth knowing for two reasons. It is the strictest naming rule anyone will run into, so it is the one most likely to reject a manual on import. And it is also the reason the duplicate-manual incident earlier this year was so disruptive: the rule protects against duplicate titles, not duplicate manuals, so copies created with slightly different names slipped past it.

FieldStatusThe short version
ITM TitleAs intendedCorrectly described as unique across the system. One of the few descriptions that is accurate.
UIDUnusedSame empty field as on components, but described completely differently here.
web address nameDivergesNot a stored field at all. Recalculated from the Title whenever a download package is built.
Labels, BOM ConfigDivergesOffered as import columns with no description at all, and ignored on import.
VersionDivergesDescribed as an importable number. Ignored on import; the system manages it.
Help Text, Published, Available, Overview Page, Help Button, Change RequestsAs intendedDescribed accurately and imported correctly.
ITM Image, seven Nav IconsBy designDescribed as "leave blank"; the importer correctly leaves them alone.
UID text · empty everywhere Unused
Described as

"Unique identifier (auto-generated if blank)."

What the app does

Nothing, exactly as on components. It cannot be filled in from any screen, the importer does not save it, and nothing reads it.

Note the description, though. On components, UID is described at length as the schematic tag number. Here it is described as something auto-generated. These are two incompatible ideas of what the field is, written into the same system, and neither one is what happens.

"Auto-generated if blank" is not true anywhere. Nothing generates it, so it is blank always.

Impact

The same field name carries a different written meaning in four different places. This is the clearest single piece of evidence that UID was added before anyone had settled what it was for - which matches what we know about how it came about.

web address name not stored · recalculated from the Title on demand Diverges
Described as

Not described anywhere. It is not a column, not a CSV field, and nobody is asked about it - but it determines a filename customers receive.

What the app does

A manual has no stored Slug. Instead a simplified version of its Title is calculated fresh each time it is needed - punctuation removed, spaces turned into hyphens.

It is used to name the offline download package: the folder it is built in, the .zip filename the customer receives, and the storage location the file is kept at.

Because it is recalculated rather than stored, renaming a manual changes the name of its download file. A package built before the rename is stored under the old name and looked for under the new one.

Impact

This is the same class of problem as the component Slug, with a different consequence: not a link that lands in the wrong place, but a download that cannot be found. It is the root of the download failure fixed in July.

Also applies elsewhere

There are three different ways of doing this in the system, and they disagree with each other. See Three ways of simplifying a name.

Labels · BOM Config the manual's whole vocabulary · varies by language Diverges
Described as

Both are offered as import columns with the description left entirely blank. Nobody filling in the template has any way to know what belongs in them.

What the app does

Between them these two settings control every renameable word in the manual - all 23 navigation and heading labels - and which BOM columns appear. They are described in full under Every manual has its own vocabulary.

Both are ignored on import. A new manual created by import gets the built-in defaults regardless of what the file contains.

Both also vary by language, which means a manual's vocabulary can differ per language - and so, therefore, can its BOM column headings.

Impact

Setting up a manual's vocabulary is one of the more tedious parts of creating one, and it is exactly the sort of thing bulk import should help with. Today it cannot, and the template gives no hint of that.

Categories

Categories

The sections a manual is divided into. After components, this is the area where naming has drifted furthest.

Three different systems for naming the same thing

A category has an internal Title used by the software to find it, and a Display Name shown to readers. That split is sound. The problem is that the internal Title has been done three different ways over the system's life, and all three are still live.

The original approach used the plain English name as the internal title - a category literally titled "Maintenance", "Multimedia", "Troubleshooting", "Home" or "Overview Videos".

A later approach replaced those with codes: def_cat_01 through def_cat_05, with the English name held separately as the Display Name. This is the better design, because it lets the reader-facing name change without breaking anything that looks the category up.

Both are still in use today. The software checks for the English name first, falls back to the code, and if neither exists it creates a new one using the old English name. So new manuals are still being given categories named the original way, even though the code-based approach replaced it.

There is a fourth wrinkle. One category's display name is not taken from its own Display Name field at all - the Overview Videos category reads its name from the manual's label settings instead. And a sixth code, def_cat_06 for a Bill of Materials category, exists in the software but was never connected to anything.

None of this is visible to anyone using the system. It surfaces as categories that behave slightly differently from one another for no apparent reason.

FieldStatusThe short version
TitleDivergesInternal name used to find the category. Three generations of convention still live at once.
Display NameDivergesThe name readers see - and the only user-facing name in the system that does not vary by language.
UIDUnusedEmpty. Described as "auto-generated if blank"; nothing generates it.
Parent Id, Order IdAs intendedDescribed accurately and imported correctly.
ImageBy designDescribed as "leave blank"; the importer correctly leaves it alone.
Title text · varies by language · uniqueness only partly enforced Diverges
Described as

"Internal system title used for routing and lookups."

What the app does

The description is accurate, and it is one of the better ones in the system. The trouble is everything around it.

When left blank, a Title is generated from the Display Name and made unique by adding _1, _2 and so on within the manual. That is sensible - but it is a fourth naming convention alongside the three described above.

The database rule protecting against duplicates covers only the five original English names. Categories using the newer codes, or any custom name, are not protected by it.

It varies by language, which is odd for a field explicitly described as internal. An internal name that changes depending on who is reading is not really internal.

Impact

A field described as being for the software's use is translated, while the field meant for readers is not. That is the wrong way round, and it is the clearest example in the system of a distinction that was designed correctly and then implemented backwards.

Display Name text · does NOT vary by language Diverges
Described as

"Name shown to users; derived from Title if blank."

What the app does

Not quite derived from the Title. When blank, it is filled from a built-in lookup that turns the code def_cat_01 into "Maintenance" and so on. For anything that is not one of those five known codes, it does fall back to the Title.

It is not translated. This is the name every reader sees in the navigation, and it is the same in every language, while the internal Title it sits beside is translated.

One category is an exception: the Overview Videos category ignores its own Display Name and takes its name from the manual's label settings instead.

Impact

A manual translated into another language will still show its section names in the original language. Given that the rest of the system translates carefully, this is likely to read as a bug the first time anyone notices it.

UID text · empty everywhere Unused
Described as

"Unique identifier (auto-generated if blank)."

What the app does

Nothing. Same as everywhere else: not fillable, not saved on import, never read.

Categories are one of the two places where this field was given a database index, implying it was meant to be searched on. It never was.

Everything else

The remaining areas

Fewer competing identifiers, so these need less space. Grouped by how they behave rather than where they sit in the app.

BOMs

The container components sit inside.

A name that acts as a key without being protected like one

A BOM has only a Title and a Description, and neither has any rule attached - no uniqueness, not even a requirement that a title be present.

That matters because the BOM Title is an identifier in practice. When importing components, the BOM Selector column matches an existing BOM by its title, ignoring capitalisation. If a manual has two BOMs with the same title, the import silently picks one of them, and there is no way to tell which.

BOMs are also the only content area in the system that does not vary by language at all. A BOM's title and description are the same in every language, while the components inside it translate normally.

FieldStatusThe short version
TitleDivergesUsed as the matching key on component import, but nothing requires it to be present or unique.
DescriptionDivergesA third thing called a description, alongside Component Description and BOM Description - and unrelated to both.

Schematics, machine states, assemblies, photos and troubleshooting

The visual pages. Similar shape, similar problems.
Area and fieldStatusThe short version
Schematic — TitleAs intendedRequired, translated, behaves normally. No uniqueness rule, but nothing depends on one.
Schematic — DescriptionDivergesDoes not vary by language, while the Title beside it does. Same issue on assemblies.
Machine State — UIDUnusedEmpty. One of the two places the field was added without even a database index.
Machine State — Dup OriginDivergesOffered as an import column with a completely blank description. Records which record something was copied from.
Machine State — ImageAs intendedThe one place an image genuinely can be imported, by public URL, exactly as described.
Mechanical Assembly — DescriptionDivergesSame as Schematic: untranslated description beside a translated title.
Photo — TitleAs intendedRequired alongside an image. No identity role.
Flowchart — OrderDivergesEvery troubleshooting flowchart is created with the same sort position, so their order is effectively arbitrary.

Documents and videos

Attached files. Two identity problems, both quiet.

Titles doing work nobody protected

Neither documents nor videos require a title, and neither prevents duplicates. Both are nonetheless matched by title when importing components - the Manufacturer Bulletin column finds a document by its title, and the three video columns find videos by theirs.

So a document title is an identifier in exactly the same way a BOM title is: load-bearing on import, unprotected in the database. Two documents with the same name in one manual make the outcome of an import unpredictable.

Videos have the additional wrinkle covered under Video Labels: a video's name on a component sheet is not its own title but a label stored on the connection, so one video has as many names as it has components.

Companies, download packages and linked manuals

Supporting areas, listed for completeness.
Area and fieldStatusThe short version
Company — TitleAs intendedRequired and unique across the system. One of only two such rules anywhere.
Company — SlugUnusedHas a strict no-duplicates rule in the database, can be typed in by hand, and is used nowhere. A dormant field, like UID but older.
Package — key, registration key, secret, storage keyAs intendedFour separate randomly-generated keys with four genuinely different jobs. Confusing to read, but each is correct.
Linked manual — web address nameDivergesStill uses the older calculation that produced the July download failure. The fix was applied to ordinary manuals only.

Behind the scenes

Behavior that applies everywhere

These are behaviors that apply across the whole system rather than to any one area, and they account for most of the surprises above.

Every manual has its own vocabulary

23 renameable labels · 8 column on/off settings · affects the whole manual

This one deserves more explanation than it has had, because it is the root of a lot of the confusion and it is not a mistake - it is a deliberate feature that carries a real cost.

Each manual carries 23 labels it can set for itself. These are not just BOM column headings. They rename the entire left-hand navigation - Home, Schematics, Mechanical Assembly, Photos, Bill of Materials, Troubleshooting, Documentation, Multimedia - along with the section headings on the schematic, machine state, assembly and troubleshooting pages. A separate set of eight settings decides which BOM columns appear at all.

The reason is sound. Each manual documents a different machine for a different customer, and those customers do not share vocabulary. What one plant calls an Item Number, another calls a Tag, a Balloon Number, or a Callout. A manual that speaks its reader's language is a better manual, and this is how the Smart Manual delivers that.

The cost is that a field's name no longer tells you which field it is. The column showing Title is called whatever that manual's "item number" label says. Two people looking at two manuals are looking at the same underlying field under two different names, and neither has any way to know. That is most of why this conversation was needed at all.

It also makes importing genuinely awkward. An import file has to use one fixed set of column names, because the importer needs to know what each column means. But the person filling in that file is working from a manual that calls those things something else. Today the CSV template uses fixed names regardless of what any manual calls them - a deliberate balancing act for a first iteration, which keeps imports predictable at the cost of the template not matching the screen the author is looking at. It was the right call to ship, but it is worth revisiting properly rather than treating it as settled.

This is also a good illustration of why we have suggested moving parts of this toward AI assistance. Solving it with conventional rules means choosing between two bad options: fix the vocabulary and lose the per-customer flexibility that makes these manuals good, or hand-maintain a mapping from every manual's wording to the underlying fields, which grows and breaks with every new manual. A system that can read a spreadsheet and work out that this customer's "Balloon No." column means the same thing as another's "Tag" handles that gracefully, without a rigid template and without anyone maintaining the mapping. This is precisely the kind of problem where a fuzzy match to intent beats a brittle set of rules.

One specific defect sits inside this design: the "description" label is used in two different places for two different fields, which is the collision described under BOM Description.

Fields that vary by language

11 areas of the app · 7 component fields

Components store separate values per language for Title, Slug, Brand/Part Number, Safety Notes, Function, Component Description and BOM Description.

What this means for the discussion: the value stored on the component is not necessarily the value a reader sees, and a field can hold different content in different languages. Any rule we agree on has to hold in every language, or fall back predictably.

Category and Tags are the exceptions. They are not translated.

Slug rebuilding

Everywhere a Slug exists

Anything with a Slug rebuilds it from its Title before every save - lower-cased, with punctuation and spaces turned into underscores. Hyphens are kept, which is what produced the recent download failure on names beginning with a dash.

No record of previous values is kept, so old links stop landing correctly the moment a title changes.

The UID field

Components · Categories · Machine States · Manuals

A single change on 26 February 2026 added UID to all four at once. None received a rule preventing duplicates, and two of the four were not set up for fast lookup either.

On all four, the field appears only in the CSV column list. Nothing displays it, nothing searches it, and no importer writes to it. It is empty in every record in the system.

The written descriptions do not agree with each other. On components, UID is described at length as the schematic tag number, with a worked example of its prefix, number and suffix. On manuals, categories and machine states it is described instead as a "unique identifier (auto-generated if blank)". Those are two different ideas of what the field is, and the second one describes behavior that does not exist anywhere - nothing is ever auto-generated.

Taken together, this is the strongest evidence available that the field was added before anyone had settled what it was for.

Three ways of simplifying a name

Components · Manuals · Linked manuals

Several places need a simplified version of a name - safe for a web address or a filename, with punctuation and spaces removed. The system does this in three different ways, and they produce different results from the same input.

Components keep hyphens and turn everything else into underscores, and the result is stored. Manuals strip hyphens entirely and turn spaces into hyphens, and the result is not stored at all - it is recalculated every time it is needed. Linked manuals use a third variant, close to the manual one but missing a correction.

That missing correction matters. It is the exact cause of the download failure fixed in July: a name beginning with punctuation produced a filename beginning with a hyphen, which the download machinery could not handle. The fix was applied to ordinary manuals. Linked manuals still carry the original version and remain exposed to the same failure.

None of these three is wrong on its own. Having three is the problem, because it means the same title produces different results depending on which part of the system is asking.

Importing can only create, never update

All CSV imports

The importer creates new components. It has no way to update an existing one. Re-importing a file whose components are already in the system runs into the rule that stops two components in a BOM sharing a Title, and those rows fail rather than updating.

This cannot be fixed before the identifier question is settled, because updating requires something dependable to match an incoming row against an existing component. That is the same decision as Q1 below.

Our view

What we think good looks like

This is our opinion on the right end state, not a proposal and not a quote. It is here so the discussion has a concrete position to push against. If CFC wants any of it built, that is a separate conversation.

01

Renaming a component should not quietly break links to it

Rebuilding the Slug is reasonable behavior; doing it silently is not. Ideally the app notices that a component is the target of schematic, photo or assembly links and says so before the name is saved. That removes the sharpest edge without changing how anything works.

02

Every field should have exactly one meaning, written down once

Where a description says a column is imported, importing it should work. Where a field is not used, it should not appear in the template. The Slug and Tags descriptions should say what actually happens. Parent UID should be called what it actually matches on.

03

A CSV should survive a round trip, exactly

Export a BOM, change nothing, import it back, and the result should be identical to what you started with. That is worth having mostly as a confidence check: if a file comes back unchanged, you know nothing was silently lost, and you can trust the import with real edits. It is not a feature anyone would use for its own sake, but it is the cheapest proof that the pipeline is honest.

04

Brand and part number together should be the identifier imports match on

It is the only candidate that is both meaningful to the people writing the spreadsheets and reliable enough to match on. Making it required and enforcing that the pair is unique is work we can do. It does mean the system would start refusing components without both, and start refusing duplicates - which will surface collisions in the existing data. That is the trade, and it is worth making.

05

Importing should be able to update, not only create

This is what makes any agreed convention applicable to the manuals that already exist. It follows directly from the item above: once there is a dependable identifier, matching an incoming row to an existing component becomes possible.

06

The BOM column and the component sheet section should be nameable separately

They show different fields and should be able to carry different names. Existing manuals would keep their current wording on both.

07

UID should either do its job or go away

If UID is genuinely the schematic tag number, it needs to be fillable, displayed, protected against duplicates, and used as the import key. If it was always another word for Brand/Part Number, it should be removed so it stops implying a promise the system does not keep. Whichever way it goes, it should mean the same thing in all four areas that have it.

08

Simplifying a name for a web address or filename should work one way, not three

Components, manuals and linked manuals each do this differently, which is why a fix applied to one of them left the others exposed. One shared approach, stored rather than recalculated, removes a whole category of problem - including the download failure that is still live on linked manuals.

09

Categories should settle on one naming convention

Three generations of internal naming are live at once, and new categories are still being created using the oldest of them. Consolidating on the code-based approach, and translating the name readers actually see rather than the internal one, would resolve most of the confusion in that area.

Underneath all of it: one definition per field

Every problem in this document has the same shape. A field has three names - the one the system uses internally, the one on the CSV column, and the one shown on screen - and each is written down in a different place. Nothing keeps them in step, so they drift, and the written description drifts along with them.

The system already has most of the answer. The CSV work introduced a list that pairs each field with a readable name and a written definition. That pattern simply does not go far enough today: only the CSV template reads it.

Ideally that one list becomes the single place a field is defined, carrying:

  • what the field is for, in one sentence
  • the CSV column name, and whether importing it actually works
  • the default on-screen name, which a manual's own settings adjust rather than replace
  • whether it varies by language, and whether duplicates are allowed

The CSV template, the help text in the admin screens, the BOM column headings and the finalized version of this document would all come from that one list. Three sets of names cannot drift apart once they share a single source, and a description cannot go stale without the field it describes changing too.

This builds on what is already in the system rather than replacing anything, and it can be done one area at a time.

Decisions

What we need to settle together

These are the questions the component findings force. The remaining areas will add to this list.

  1. Are UID and Brand/Part Number the same thing?

    This is the question everything else waits on. If they are the same, UID goes away and Brand/Part Number is the human-readable identifier. If they are genuinely different, we need to know what UID is for, because at the moment it cannot be filled in at all.

  2. Can brand and part number be required on every component, and unique?

    This is our recommended identifier for imports, and it is the one that makes updating by import possible. Agreeing to it means the system starts refusing components without both, and refusing duplicates - which will surface collisions already sitting in the data. We would also need to know whether that uniqueness should hold across the whole Smart Manual or only within one manual.

  3. Where does the schematic tag number belong?

    The written description says UID. The data says Title, which is what fills the BOM's Item Number column. Whichever answer is right, the other field needs a different job.

  4. Should the component sheet be headed by the description?

    Today it is, and the description then prints twice on the page. If the heading should be the Title or the part number instead, that is a small change that affects how every component sheet reads.

  5. Should the BOM column and the component sheet section share one name?

    They show different fields. Separating them is straightforward but changes settings on existing manuals.

  6. Should we rename Category on components?

    It collides with the Categories elsewhere in the app and means something entirely different. Renaming is cheap now and expensive once a convention is written down.

  7. Should Tags be searchable?

    The written description says they are. They are not.

  8. Should section names be translated?

    Today the name readers see for a category is the same in every language, while the internal name beside it does translate. If manuals are meant to work in more than one language, this is the wrong way round and worth correcting deliberately rather than as a bug fix.

  9. Do BOM, document and video names need to be unique?

    All three are used to match rows during import, and none is protected against duplicates. Two BOMs sharing a name in one manual makes an import's outcome unpredictable. Requiring uniqueness is straightforward, but it will surface existing duplicates that need resolving.

The proposal

How the fields should look

Everything above describes problems. This describes one coherent answer to all of them at once - the field set we would design if we were starting today, stated so CFC can react to a whole picture instead of a dozen separate decisions.

Five rules the whole design follows

Every change below comes from one of these. They are worth agreeing before the detail, because if the rules are right the specifics mostly follow.

  1. Every field has exactly one meaning, written down in exactly one place. The CSV column, the on-screen label and the help text all come from that one definition, so they cannot drift apart again.
  2. A name a person reads is translated. A name the software uses is not. Today this is backwards in places, most visibly on categories.
  3. Any name used to match an imported row is required and cannot be duplicated. If the software relies on it to find something, it has to be dependable.
  4. Nothing appears in an import template unless importing it actually works. No column that is read and dropped, and no column with a blank description.
  5. Addresses and filenames are generated once and never change. Renaming something should never break a link or a download.

Components

The area with the most change, because it had the most overlap.
FieldChangeWhat it would mean
TagRenamedWas Title. The schematic tag number - P-105.2 - which is what this field already holds. Fills the Item Number column, as it already does. Required, and unique within its BOM as it already is. This is a rename that makes the field honest about its job; the data does not move.
BrandSplit outThe manufacturer, on its own. Currently buried inside the combined Brand/Part Number field.
Part NumberTightenedThe manufacturer's number, on its own. Brand and Part Number together become the identifier imports match on - required, and unique across the system.
NameRenamedWas BOM Description. The formal nomenclature - "VALVE, DIR CTRL, 4/3". It already fills the BOM's description column; it also becomes the heading on the component sheet, which is a job it is better suited to than the field doing it today.
DescriptionRepurposedWas Component Description. Stays as written prose about the component's role, and stops being the page heading. It would appear once on the page instead of twice.
GroupRenamedWas Category. Same free-text grouping within a BOM, renamed so it stops colliding with the Categories that organise a manual. No behavior change.
Sort order · Group sort orderNow importedWas Order ID and Category Order ID. Both start working on import. Group sort order needs Groups to be a defined list per BOM rather than free text, which is a small addition.
SharedNow importedUnchanged in meaning; starts working on import.
TagsNow searchableBecomes searchable from the BOM search box, which is what its description has always claimed.
Safety Notes · Function · eBook Link · Image FooterUnchangedThese already work and already say what they mean.
Video labelsUnchangedStored on the link between component and video, which is the right design. The broken export gets fixed.
AnchorMade permanentWas Slug. Generated once when a component is first saved and never changed again, so renaming can never break an existing link. Removed from the import template - it is not an author's concern.
UIDRemovedIts job is done by Tag and by Brand + Part Number. It has never held a value.
internal idUnchangedStays exactly as it is, and stays invisible.
One judgment call

Making BOM Description into Name is our reading, not a certainty. The alternative is a genuinely new Name field, which would mean splitting every existing component's text by hand. We think the nomenclature already in BOM Description is the closest thing to a component's name that exists, so promoting it costs nothing and loses nothing. Worth confirming that reads right to CFC.

Manuals

Mostly already correct. Two real changes.
FieldChangeWhat it would mean
TitleUnchangedRequired and unique across the system. Already correct, and already described correctly.
Address nameMade permanentCurrently recalculated from the Title every time a download is built, which is why renaming a manual could break its download. Generated once and stored instead.
Vocabulary · Column setupNow importedWas Labels and BOM Config, both shipped with blank descriptions and both ignored on import. They get real descriptions and start working, so setting up a manual's wording can be done in bulk. The single "description" label splits into two, one for the BOM column and one for the component sheet.
VersionOff the templateManaged by the system. It should not be offered as something to fill in.
UIDRemovedEmpty, and described here in a way that contradicts the components description of the same field.
Help Text · Published · Available · Overview Page · Help Button · Change RequestsUnchangedAll accurate today.
Image · Navigation iconsUnchangedCorrectly marked as upload-only.

Categories

The translation split, corrected.
FieldChangeWhat it would mean
CodeRenamedWas Title. The internal handle the software uses to find a category. Settles on the code style throughout, stops being translated, and stops being something anyone types. The three competing conventions become one.
NameNow translatedWas Display Name. The only name a reader ever sees, and the only one that should be. It starts varying by language, which it does not today. The Overview Videos exception - where the name is pulled from the manual's settings instead - goes away.
Parent · Sort orderUnchangedBoth accurate and both working.
UIDRemovedEmpty, and the Code field does the job it was described as doing.
The unused sixth categoryRemovedA Bill of Materials category exists in the software but was never connected to anything. Either finish it or take it out; we would take it out.

Everything else

Smaller areas, mostly one change each.
Area and fieldChangeWhat it would mean
BOM — NameNow requiredWas Title. Imports already match BOMs by this, so it has to be dependable. Also starts varying by language, which it does not today.
BOM — DescriptionNow translatedThe only remaining "description" on a BOM once the component fields are renamed, so the three-way collision resolves itself.
Document — Name · Video — NameNow requiredBoth are used to match rows on import and neither is protected today. Unique within a manual is enough.
Schematic · Assembly — DescriptionNow translatedBoth sit beside a translated title and neither translates, so a translated manual shows them in the original language.
Machine State — UIDRemovedEmpty, unindexed, and described incorrectly.
Machine State — Dup OriginOff the templateRecords what a copy came from. System business, not an author's, and it ships with a blank description today.
Flowchart — Sort orderNow setEvery troubleshooting flowchart is currently created in the same position, so their order is arbitrary. New ones go to the end.
Company — TitleUnchangedRequired and unique. Already correct.
Company — SlugRemovedHas a strict no-duplicates rule, can be typed by hand, and is used nowhere at all.
Linked manual — Address nameUnifiedStill uses the older calculation that caused the July download failure. Adopting the same stored, frozen approach closes that off.
Package — the four keysUnchangedConfusing to read, but each of the four does a genuinely different job and each is correct.

What it would take to get there

A note on effort and sequencing, so the size of each change is visible. Most of the above is renaming and rewording, which moves no data and breaks nothing. Four changes are larger, and those are the ones worth deciding on deliberately.

  • Splitting Brand from Part Number. Existing combined values have to be separated. Much of it can be done automatically, but some will need a person to look at it.
  • Requiring Brand and Part Number, and enforcing uniqueness. This will surface components that are missing one or that collide with another. Those have to be resolved before the rule can be switched on - and that resolution is content work, not development work.
  • Translating names that do not translate today. Existing values carry over as the default language, so nothing breaks. But any manual already translated will have section names, BOM names and descriptions that need translating for the first time.
  • Freezing addresses. Existing anchors are kept as they are, so nothing that works today stops working. From then on they stop moving.

Nothing here has to happen at once. The rename and description work stands on its own and delivers most of the clarity. The identifier changes are what unlock importing updates, so they travel together. Translation and address work can follow whenever it suits.