[{"data":1,"prerenderedAt":1044},["ShallowReactive",2],{"navigation_docs":3,"-concepts-how-it-works":111,"-concepts-how-it-works-surround":1039},[4,20,30,66,82,89,96],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fgetting-started","1.getting-started",[10,15],{"title":11,"path":12,"stem":13,"icon":14},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F1.installation","i-lucide-download",{"title":16,"path":17,"stem":18,"icon":19},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F2.quick-start","i-lucide-rocket",{"title":21,"icon":22,"path":23,"stem":24,"children":25,"page":6},"Concepts","i-lucide-compass","\u002Fconcepts","2.concepts",[26],{"title":27,"path":28,"stem":29,"icon":22},"How it works","\u002Fconcepts\u002Fhow-it-works","2.concepts\u002F1.how-it-works",{"title":31,"icon":32,"path":33,"stem":34,"children":35,"page":6},"Essentials","i-lucide-book-open","\u002Fessentials","3.essentials",[36,41,46,51,56,61],{"title":37,"path":38,"stem":39,"icon":40},"Sources","\u002Fessentials\u002Fsources","3.essentials\u002F1.sources","i-lucide-layers",{"title":42,"path":43,"stem":44,"icon":45},"Filament UI","\u002Fessentials\u002Ffilament-ui","3.essentials\u002F2.filament-ui","i-lucide-layout-dashboard",{"title":47,"path":48,"stem":49,"icon":50},"Refining the timeline","\u002Fessentials\u002Frefining-the-timeline","3.essentials\u002F3.refining-the-timeline","i-lucide-filter",{"title":52,"path":53,"stem":54,"icon":55},"Customization","\u002Fessentials\u002Fcustomization","3.essentials\u002F4.customization","i-lucide-paintbrush",{"title":57,"path":58,"stem":59,"icon":60},"Caching","\u002Fessentials\u002Fcaching","3.essentials\u002F5.caching","i-lucide-database",{"title":62,"path":63,"stem":64,"icon":65},"Configuration","\u002Fessentials\u002Fconfiguration","3.essentials\u002F6.configuration","i-lucide-settings",{"title":67,"icon":68,"path":69,"stem":70,"children":71,"page":6},"Recipes","i-lucide-chef-hat","\u002Frecipes","4.recipes",[72,77],{"title":73,"path":74,"stem":75,"icon":76},"CRM person feed","\u002Frecipes\u002Fcrm-person-feed","4.recipes\u002F1.crm-person-feed","i-lucide-users",{"title":78,"path":79,"stem":80,"icon":81},"Audit log for admins","\u002Frecipes\u002Faudit-log-for-admins","4.recipes\u002F2.audit-log-for-admins","i-lucide-shield",{"title":83,"path":84,"stem":85,"children":86,"icon":88},"Testing","\u002Ftesting","5.testing\u002F1.index",[87],{"title":83,"path":84,"stem":85,"icon":88},"i-lucide-flask-conical",{"title":90,"path":91,"stem":92,"children":93,"icon":95},"Troubleshooting","\u002Ftroubleshooting","6.troubleshooting\u002F1.index",[94],{"title":90,"path":91,"stem":92,"icon":95},"i-lucide-life-buoy",{"title":97,"path":98,"stem":99,"children":100,"page":6},"Community","\u002Fcommunity","7.community",[101,106],{"title":102,"path":103,"stem":104,"icon":105},"Contributing","\u002Fcommunity\u002Fcontributing","7.community\u002F1.contributing","i-lucide-heart-handshake",{"title":107,"path":108,"stem":109,"icon":110},"License","\u002Fcommunity\u002Flicense","7.community\u002F2.license","i-lucide-scale",{"id":112,"title":27,"body":113,"description":1030,"extension":1031,"links":1032,"meta":1033,"navigation":1034,"path":28,"seo":1035,"stem":29,"__hash__":1038},"docs\u002F2.concepts\u002F1.how-it-works.md",{"type":114,"value":115,"toc":1020},"minimark",[116,120,125,136,159,163,193,210,374,381,441,477,484,493,543,563,567,686,690,700,780,783,824,828,841,850,856,859,949,955,959,1016],[117,118,119],"p",{},"This page is the canonical reference for the package's mental model: the pipeline, the building blocks, the type taxonomy, and the dedup\u002Fpriority rules. Read it once before configuring sources, writing renderers, or debugging missing entries.",[121,122,124],"h2",{"id":123},"the-pipeline","The pipeline",[126,127,133],"pre",{"className":128,"code":130,"language":131,"meta":132},[129],"language-text","$record->timeline()             [TimelineBuilder]\n    ↓ resolves\nTimelineSource(s) per source    [resolve(subject, Window)]\n    ↓ yields\nTimelineEntry stream            [filter → dedup → sort]\n    ↓ paginated\nLengthAwarePaginator → Renderer → Blade view\n","text","",[134,135,130],"code",{"__ignoreMap":132},[117,137,138,139,142,143,146,147,150,151,154,155,158],{},"A call to ",[134,140,141],{},"$record->timeline()"," returns a fluent ",[134,144,145],{},"TimelineBuilder",". Each registered source is asked to ",[134,148,149],{},"resolve()"," entries inside a shared ",[134,152,153],{},"Window",". The combined stream is filtered, deduplicated, sorted, and either paginated or returned whole. Renderers turn each ",[134,156,157],{},"TimelineEntry"," into HTML at view time.",[121,160,162],{"id":161},"core-building-blocks","Core building blocks",[117,164,165,169,170,173,174,177,178,181,182,185,186,189,190,192],{},[166,167,168],"strong",{},"Subject."," Any Eloquent model implementing ",[134,171,172],{},"Relaticle\\ActivityLog\\Contracts\\HasTimeline",". In practice you get this for free by using the ",[134,175,176],{},"Relaticle\\ActivityLog\\Concerns\\InteractsWithTimeline"," trait, which provides ",[134,179,180],{},"timeline()",", ",[134,183,184],{},"paginateTimeline()",", and ",[134,187,188],{},"forgetTimelineCache()",". The subject is passed into every source's ",[134,191,149],{}," call.",[117,194,195,198,199,202,203,206,207,209],{},[166,196,197],{},"Source."," A class implementing ",[134,200,201],{},"Relaticle\\ActivityLog\\Contracts\\TimelineSource",". Sources own the data: they query the database (or any other store) and ",[134,204,205],{},"yield"," ",[134,208,157],{}," instances. The package ships four built-ins, registered via the builder's helpers:",[126,211,215],{"className":212,"code":213,"language":214,"meta":132,"style":132},"language-php shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","$record->timeline()\n    ->fromActivityLog()                                    \u002F\u002F ActivityLogSource\n    ->fromActivityLogOf(['comments'])                      \u002F\u002F RelatedActivityLogSource\n    ->fromRelation('invoices', fn ($s) => $s->title(...))  \u002F\u002F RelatedModelSource\n    ->fromCustom(fn ($subject, $window) => yield ...);     \u002F\u002F CustomEventSource\n","php",[134,216,217,240,256,282,335],{"__ignoreMap":132},[218,219,222,226,230,233,237],"span",{"class":220,"line":221},"line",1,[218,223,225],{"class":224},"sMK4o","$",[218,227,229],{"class":228},"sTEyZ","record",[218,231,232],{"class":224},"->",[218,234,236],{"class":235},"s2Zo4","timeline",[218,238,239],{"class":224},"()\n",[218,241,243,246,249,252],{"class":220,"line":242},2,[218,244,245],{"class":224},"    ->",[218,247,248],{"class":235},"fromActivityLog",[218,250,251],{"class":224},"()",[218,253,255],{"class":254},"sHwdD","                                    \u002F\u002F ActivityLogSource\n",[218,257,259,261,264,267,270,274,276,279],{"class":220,"line":258},3,[218,260,245],{"class":224},[218,262,263],{"class":235},"fromActivityLogOf",[218,265,266],{"class":224},"([",[218,268,269],{"class":224},"'",[218,271,273],{"class":272},"sfazB","comments",[218,275,269],{"class":224},[218,277,278],{"class":224},"])",[218,280,281],{"class":254},"                      \u002F\u002F RelatedActivityLogSource\n",[218,283,285,287,290,293,295,298,300,303,307,310,313,316,319,322,324,326,329,332],{"class":220,"line":284},4,[218,286,245],{"class":224},[218,288,289],{"class":235},"fromRelation",[218,291,292],{"class":224},"(",[218,294,269],{"class":224},[218,296,297],{"class":272},"invoices",[218,299,269],{"class":224},[218,301,302],{"class":224},",",[218,304,306],{"class":305},"spNyl"," fn",[218,308,309],{"class":224}," ($",[218,311,312],{"class":228},"s",[218,314,315],{"class":224},")",[218,317,318],{"class":224}," =>",[218,320,321],{"class":224}," $",[218,323,312],{"class":228},[218,325,232],{"class":224},[218,327,328],{"class":235},"title",[218,330,331],{"class":224},"(...))",[218,333,334],{"class":254},"  \u002F\u002F RelatedModelSource\n",[218,336,338,340,343,345,348,350,353,355,357,360,362,364,368,371],{"class":220,"line":337},5,[218,339,245],{"class":224},[218,341,342],{"class":235},"fromCustom",[218,344,292],{"class":224},[218,346,347],{"class":305},"fn",[218,349,309],{"class":224},[218,351,352],{"class":228},"subject",[218,354,302],{"class":224},[218,356,321],{"class":224},[218,358,359],{"class":228},"window",[218,361,315],{"class":224},[218,363,318],{"class":224},[218,365,367],{"class":366},"s7zQu"," yield",[218,369,370],{"class":224}," ...);",[218,372,373],{"class":254},"     \u002F\u002F CustomEventSource\n",[117,375,376,377,380],{},"See ",[378,379,38],"a",{"href":38}," for full source configuration.",[117,382,383,206,386,389,390,393,394,181,397,181,400,181,403,181,406,181,409,412,413,415,416,415,419,422,423,181,425,181,428,181,431,181,434,181,437,440],{},[166,384,385],{},"Entry.",[134,387,388],{},"Relaticle\\ActivityLog\\Timeline\\TimelineEntry"," — an immutable ",[134,391,392],{},"readonly"," value object. It carries ",[134,395,396],{},"id",[134,398,399],{},"type",[134,401,402],{},"event",[134,404,405],{},"occurredAt",[134,407,408],{},"dedupKey",[134,410,411],{},"sourcePriority",", optional ",[134,414,352],{},"\u002F",[134,417,418],{},"causer",[134,420,421],{},"relatedModel",", plus presentation hints (",[134,424,328],{},[134,426,427],{},"description",[134,429,430],{},"icon",[134,432,433],{},"color",[134,435,436],{},"renderer",[134,438,439],{},"properties","). Sources construct entries; the builder, dedup, sort, and renderer only consume them.",[117,442,443,198,446,449,450,452,453,456,457,460,461,463,464,466,467,469,470,473,474,476],{},[166,444,445],{},"Renderer.",[134,447,448],{},"Relaticle\\ActivityLog\\Contracts\\TimelineRenderer",". Given a ",[134,451,157],{},", it returns a ",[134,454,455],{},"View"," or ",[134,458,459],{},"HtmlString",". Renderers are looked up by the entry's ",[134,462,436],{}," field (explicit), then its ",[134,465,402],{},", then its ",[134,468,399],{},", falling back to ",[134,471,472],{},"DefaultRenderer",". See ",[378,475,53],{"href":53},".",[121,478,480,481,483],{"id":479},"the-window-value-object","The ",[134,482,153],{}," value object",[117,485,486,489,490,492],{},[134,487,488],{},"Relaticle\\ActivityLog\\Timeline\\Window"," is the read-only context passed to every source's ",[134,491,149],{},". It carries:",[494,495,496,511,528],"ul",{},[497,498,499,502,503,506,507,510],"li",{},[134,500,501],{},"from"," \u002F ",[134,504,505],{},"to"," — the date range set via ",[134,508,509],{},"->between($from, $to)"," (both nullable).",[497,512,513,516,517,520,521,524,525,476],{},[134,514,515],{},"cap"," — the per-source over-fetch limit. The builder computes ",[134,518,519],{},"cap = perPage * (page + buffer)"," for paginated reads, and uses a hard ",[134,522,523],{},"10000"," ceiling for ",[134,526,527],{},"->get()",[497,529,530,502,533,502,536,502,539,542],{},[134,531,532],{},"typeAllow",[134,534,535],{},"typeDeny",[134,537,538],{},"eventAllow",[134,540,541],{},"eventDeny"," — the active filters, mirrored so sources can push them down into queries (otherwise the builder applies them post-yield).",[117,544,545,546,548,549,552,553,556,557,559,560,476],{},"Sources should respect ",[134,547,515],{}," to keep memory bounded — ",[134,550,551],{},"RelatedActivityLogSource",", for example, calls ",[134,554,555],{},"->limit($window->cap)"," on its underlying query. The builder constructs the ",[134,558,153],{}," via ",[134,561,562],{},"makeWindow($cap)",[121,564,566],{"id":565},"type-taxonomy","Type taxonomy",[568,569,572,577,591,608,620,639,675],"callout",{"color":570,"icon":571},"warning","i-lucide-alert-triangle",[117,573,574],{},[166,575,576],{},"Two distinct \"type\" axes exist. Do not confuse them.",[117,578,480,579,582,583,586,587,590],{},[166,580,581],{},"entry-type"," axis (",[134,584,585],{},"$entry->type",") has ",[166,588,589],{},"3 values today",":",[494,592,593,598,603],{},[497,594,595],{},[134,596,597],{},"activity_log",[497,599,600],{},[134,601,602],{},"related_model",[497,604,605],{},[134,606,607],{},"custom",[117,609,480,610,582,613,616,617,590],{},[166,611,612],{},"source-priority config",[134,614,615],{},"source_priorities"," config keys) has ",[166,618,619],{},"4 keys",[494,621,622,626,631,635],{},[497,623,624],{},[134,625,597],{},[497,627,628],{},[134,629,630],{},"related_activity_log",[497,632,633],{},[134,634,602],{},[497,636,637],{},[134,638,607],{},[117,640,641,642,645,646,206,649,652,653,656,657,660,661,664,665,668,669,671,672,674],{},"Critically: RelatedActivityLogSource emits entries with ",[134,643,644],{},"type='activity_log'"," (",[166,647,648],{},"not",[134,650,651],{},"'related_activity_log'","). Filtering with ",[134,654,655],{},"->ofType(['related_activity_log'])"," will never match anything. To distinguish own-log entries from related-log entries today, inspect ",[134,658,659],{},"$entry->relatedModel"," (it's ",[134,662,663],{},"null"," for ",[134,666,667],{},"ActivityLogSource"," entries and an Eloquent model for ",[134,670,551],{}," entries) after calling ",[134,673,527],{}," — there is no builder-level filter for source-of-origin.",[117,676,376,677,679,680,476],{},[378,678,91],{"href":91}," (\"Type filter doesn't match anything\") and ",[378,681,685],{"href":682,"rel":683},"https:\u002F\u002Fgithub.com\u002Frelaticle\u002Factivity-log\u002Fissues\u002F11",[684],"nofollow","issue #11",[121,687,689],{"id":688},"source-priorities","Source priorities",[117,691,692,693,696,697,699],{},"Defaults live in ",[134,694,695],{},"config\u002Factivity-log.php"," under ",[134,698,615],{},". Higher priority wins on dedup ties.",[701,702,703,719],"table",{},[704,705,706],"thead",{},[707,708,709,713,716],"tr",{},[710,711,712],"th",{},"Source",[710,714,715],{},"Default priority",[710,717,718],{},"Config key",[720,721,722,737,750,765],"tbody",{},[707,723,724,729,732],{},[725,726,727],"td",{},[134,728,667],{},[725,730,731],{},"10",[725,733,734],{},[134,735,736],{},"source_priorities.activity_log",[707,738,739,743,745],{},[725,740,741],{},[134,742,551],{},[725,744,731],{},[725,746,747],{},[134,748,749],{},"source_priorities.related_activity_log",[707,751,752,757,760],{},[725,753,754],{},[134,755,756],{},"RelatedModelSource",[725,758,759],{},"20",[725,761,762],{},[134,763,764],{},"source_priorities.related_model",[707,766,767,772,775],{},[725,768,769],{},[134,770,771],{},"CustomEventSource",[725,773,774],{},"30",[725,776,777],{},[134,778,779],{},"source_priorities.custom",[117,781,782],{},"Override per-call by passing the second argument to any builder helper:",[126,784,786],{"className":212,"code":785,"language":214,"meta":132,"style":132},"$record->timeline()->fromCustom($resolver, priority: 100);\n",[134,787,788],{"__ignoreMap":132},[218,789,790,792,794,796,798,801,803,806,809,811,815,817,821],{"class":220,"line":221},[218,791,225],{"class":224},[218,793,229],{"class":228},[218,795,232],{"class":224},[218,797,236],{"class":235},[218,799,800],{"class":224},"()->",[218,802,342],{"class":235},[218,804,805],{"class":224},"($",[218,807,808],{"class":228},"resolver",[218,810,302],{"class":224},[218,812,814],{"class":813},"sBMFI"," priority",[218,816,590],{"class":224},[218,818,820],{"class":819},"sbssI"," 100",[218,822,823],{"class":224},");\n",[121,825,827],{"id":826},"dedup-behavior","Dedup behavior",[117,829,830,831,833,834,836,837,840],{},"Entries sharing a ",[134,832,408],{}," collapse to a single entry: the one with the highest ",[134,835,411],{}," wins. On equal priority, ",[166,838,839],{},"first-seen wins"," (sources are resolved in the order they were registered).",[117,842,843,844,846,847,590],{},"The default ",[134,845,408],{}," is generated by ",[134,848,849],{},"AbstractTimelineSource::dedupKeyFor()",[126,851,854],{"className":852,"code":853,"language":131,"meta":132},[129],"{class}:{id}:{occurredAt-iso}\n",[134,855,853],{"__ignoreMap":132},[117,857,858],{},"Override per builder:",[126,860,862],{"className":212,"code":861,"language":214,"meta":132,"style":132},"$record->timeline()\n    ->dedupKeyUsing(fn (TimelineEntry $entry): string => \"{$entry->type}:{$entry->event}:{$entry->occurredAt->toDateString()}\");\n",[134,863,864,876],{"__ignoreMap":132},[218,865,866,868,870,872,874],{"class":220,"line":221},[218,867,225],{"class":224},[218,869,229],{"class":228},[218,871,232],{"class":224},[218,873,236],{"class":235},[218,875,239],{"class":224},[218,877,878,880,883,885,887,889,891,893,896,899,902,904,907,909,911,913,916,918,921,923,925,927,929,931,933,935,937,939,941,944,947],{"class":220,"line":242},[218,879,245],{"class":224},[218,881,882],{"class":235},"dedupKeyUsing",[218,884,292],{"class":224},[218,886,347],{"class":305},[218,888,645],{"class":224},[218,890,157],{"class":813},[218,892,321],{"class":224},[218,894,895],{"class":228},"entry",[218,897,898],{"class":224},"):",[218,900,901],{"class":819}," string",[218,903,318],{"class":224},[218,905,906],{"class":224}," \"{$",[218,908,895],{"class":228},[218,910,232],{"class":224},[218,912,399],{"class":228},[218,914,915],{"class":224},"}",[218,917,590],{"class":272},[218,919,920],{"class":224},"{$",[218,922,895],{"class":228},[218,924,232],{"class":224},[218,926,402],{"class":228},[218,928,915],{"class":224},[218,930,590],{"class":272},[218,932,920],{"class":224},[218,934,895],{"class":228},[218,936,232],{"class":224},[218,938,405],{"class":228},[218,940,232],{"class":224},[218,942,943],{"class":235},"toDateString",[218,945,946],{"class":224},"()}\"",[218,948,823],{"class":224},[117,950,951,952,476],{},"Disable dedup entirely with ",[134,953,954],{},"->deduplicate(false)",[121,956,958],{"id":957},"lifecycle","Lifecycle",[960,961,962,968,983,994,1005],"ol",{},[497,963,964,965,476],{},"The builder calls each registered source's ",[134,966,967],{},"resolve($subject, $window)",[497,969,970,971,974,975,415,977,415,979,415,981,476],{},"Yielded entries pass through ",[134,972,973],{},"passesFilters()"," — ",[134,976,532],{},[134,978,535],{},[134,980,538],{},[134,982,541],{},[497,984,985,986,989,990,993],{},"Dedup is applied if enabled (default: ",[134,987,988],{},"true",", overridable in config via ",[134,991,992],{},"deduplicate_by_default",").",[497,995,996,997,1000,1001,1004],{},"The collection is sorted — ",[134,998,999],{},"sortByDateDesc()"," is the default; ",[134,1002,1003],{},"sortByDateAsc()"," flips it.",[497,1006,1007,1008,1011,1012,1015],{},"Results are returned via ",[134,1009,1010],{},"paginate(perPage, page)"," (the standard Filament\u002FLivewire path) or ",[134,1013,1014],{},"get()"," (capped at 10000 entries).",[1017,1018,1019],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":132,"searchDepth":242,"depth":242,"links":1021},[1022,1023,1024,1026,1027,1028,1029],{"id":123,"depth":242,"text":124},{"id":161,"depth":242,"text":162},{"id":479,"depth":242,"text":1025},"The Window value object",{"id":565,"depth":242,"text":566},{"id":688,"depth":242,"text":689},{"id":826,"depth":242,"text":827},{"id":957,"depth":242,"text":958},"The mental model and vocabulary behind the timeline pipeline.","md",null,{},{"icon":22},{"description":1036,"ogImage":1037,"title":27},"Mental model, vocabulary, and pipeline behind relaticle\u002Factivity-log timelines.","\u002Fpreview.png","Tp5s8cYAncNAhZ3HLr8DxnbZY1LiIGnaR_4ET-2ikZg",[1040,1042],{"title":16,"path":17,"stem":18,"description":1041,"icon":19,"children":-1},"Working timeline in 5 minutes — Person model, spatie log, infolist render.",{"title":37,"path":38,"stem":39,"description":1043,"icon":40,"children":-1},"The four built-in source types and how to register custom ones.",1780504149910]