Welcome 👋
Neo's grid can put a clickable icon in a cell: an icon, an icon with a link, or a LinkedIn profile link built from a bare handle. Each of these columns decides what the cell shows in one method, applyRecordConfigs(config, record). They have small, testable rules (formatters, URL building, hiding empty cells) and no tests.
This is a good first issue for Hacktoberfest 2026. It needs Node.js and a clone of this repository: no Docker, no AI setup.
[!IMPORTANT]
Reserved for first-time Neo.mjs contributors. The maintainer team will not claim, edit, or implement this issue through 2026-10-31. Comment here to claim it, and ask anything on this issue.
Set up once: follow Set up the engine from a clone, including npm run bundle-browser-deps: without it the unit suite selects zero tests.
Where things live
- Sources:
src/grid/column/Icon.mjs, IconLink.mjs, LinkedIn.mjs
- New test file:
test/playwright/unit/grid/column/IconColumns.spec.mjs
- Pattern to copy:
test/playwright/unit/grid/column/Component.spec.mjs (creating a column with Neo.create() and a dataField). A plain object works as the record for these methods.
What to cover
| Column |
Case |
applyRecordConfigs(config, record) returns |
Icon |
no cellIconCls on the column |
cellIconCls is the record value; hidden is true when that value is falsy |
Icon |
a fixed cellIconCls on the column |
that cellIconCls; still hidden when the record value is falsy |
IconLink |
no formatters |
url is the record value; label is record[labelField], or null without a labelField; cellIconCls comes from the column |
IconLink |
urlFormatter |
url is urlFormatter(value, record) |
IconLink |
labelFormatter |
label is labelFormatter(x, record), where x is the labelField value if one is set, else the record value |
LinkedIn |
a bare handle, e.g. 'jane-doe' |
url is 'https://www.linkedin.com/in/jane-doe/' |
LinkedIn |
a value starting with http |
kept as it is |
LinkedIn |
defaults |
cellIconCls is 'fa-brands fa-linkedin' |
| all three |
a key passed in config |
wins over the derived one (it is spread last) |
Done when
Out of scope
The icon components themselves, and click handling in a real grid.
While you wait for review
You just pinned one small piece of a multi-threaded application engine: in Neo.mjs your app's code runs inside a web worker, and the main thread only paints. Two things worth ten minutes:
- See the part nobody expects. Run
npm run build-themes -- -n -e dev -t all and npm run server-start, open apps/workstation/, and drag a tab out of the browser window. It becomes its own OS window, still running, with the same component instances and the same worker. Benefits: Introduction explains why that is possible.
- Your coding agent can go much further here. The skills this repository's AI maintainers work with are published on npm as NEO_INLINE_CODE_54, and they need no Knowledge Base and no Memory Core. With Claude or GPT beside you, the
help wanted issues are within reach after this one.
Maintainer notes
Curated under #18985 (Hacktoberfest 2026). Found work: no unit or component spec names these three modules on dev (2026-09-23); the rows follow the three methods line by line.
Live latest-open sweep: the latest 20 open issues at 2026-09-23T14:24Z; no equivalent (IconLink and LinkedIn column title searches return closed history only). A2A: no claim on this scope. Memory Core: no prior decision.
Origin Session ID: 3be453e4-8b04-4865-be62-4cff34f4e0c6
Welcome 👋
Neo's grid can put a clickable icon in a cell: an icon, an icon with a link, or a LinkedIn profile link built from a bare handle. Each of these columns decides what the cell shows in one method,
applyRecordConfigs(config, record). They have small, testable rules (formatters, URL building, hiding empty cells) and no tests.This is a good first issue for Hacktoberfest 2026. It needs Node.js and a clone of this repository: no Docker, no AI setup.
Set up once: follow Set up the engine from a clone, including
npm run bundle-browser-deps: without it the unit suite selects zero tests.Where things live
src/grid/column/Icon.mjs,IconLink.mjs,LinkedIn.mjstest/playwright/unit/grid/column/IconColumns.spec.mjstest/playwright/unit/grid/column/Component.spec.mjs(creating a column withNeo.create()and adataField). A plain object works as the record for these methods.What to cover
applyRecordConfigs(config, record)returnsIconcellIconClson the columncellIconClsis the record value;hiddenistruewhen that value is falsyIconcellIconClson the columncellIconCls; stillhiddenwhen the record value is falsyIconLinkurlis the record value;labelisrecord[labelField], ornullwithout alabelField;cellIconClscomes from the columnIconLinkurlFormatterurlisurlFormatter(value, record)IconLinklabelFormatterlabelislabelFormatter(x, record), wherexis thelabelFieldvalue if one is set, else the record valueLinkedIn'jane-doe'urlis'https://www.linkedin.com/in/jane-doe/'LinkedInhttpLinkedIncellIconClsis'fa-brands fa-linkedin'configDone when
test/playwright/unit/grid/column/IconColumns.spec.mjsexists, following the pattern file's setup.test(...)per table row.src/.npm run test-unit -- test/playwright/unit/grid/column/IconColumns.spec.mjspasses.npm run test-unitpasses.Out of scope
The icon components themselves, and click handling in a real grid.
While you wait for review
You just pinned one small piece of a multi-threaded application engine: in Neo.mjs your app's code runs inside a web worker, and the main thread only paints. Two things worth ten minutes:
npm run build-themes -- -n -e dev -t allandnpm run server-start, openapps/workstation/, and drag a tab out of the browser window. It becomes its own OS window, still running, with the same component instances and the same worker. Benefits: Introduction explains why that is possible.help wantedissues are within reach after this one.Maintainer notes
Curated under #18985 (Hacktoberfest 2026). Found work: no unit or component spec names these three modules on
dev(2026-09-23); the rows follow the three methods line by line. Live latest-open sweep: the latest 20 open issues at 2026-09-23T14:24Z; no equivalent (IconLinkandLinkedIn columntitle searches return closed history only). A2A: no claim on this scope. Memory Core: no prior decision.Origin Session ID: 3be453e4-8b04-4865-be62-4cff34f4e0c6