This site is published by Medrecords AI, which makes 1 of the products it covers. We say which one wherever it appears. How we handle that.

Best AI Medical Timeline

Build your own medical timeline from a chronology export

By Ahmed Jemaa, Co-Founder and CEO of Medrecords AI. Updated .

Short version: export your cited chronology to a spreadsheet, keep 6 columns (start, end, lane, label, page, note), save as CSV, and paste it into the HTML file below. It draws lanes, duration bars, gaps over your threshold and a key date line, and lists undated rows. It runs in your browser from your own disk, so no patient data is uploaded anywhere.

Limits: Tool facts come from each vendor's own website, read 2026-11-12; we have not used those products. The case on this site is synthetic, with no real patient.

When to draw your own

Most record review tools give you a cited table, not a drawn timeline (see the tools page). Drawing your own makes sense when:

Don't draw your own if you'd be retyping dates from a PDF. Retyping is where errors start. Work from an export (Excel, CSV or Word table) of rows that already carry page cites.

The 6 columns

ColumnWhat goes in itRule
startDate of service, YYYY-MM-DDLeave empty for undated records; they go to a list, not the chart
endEnd of a span (drug, admission, work status)Empty for single events. If the end is unknown, leave it empty and say so in note
laneVisits, Imaging, Procedures, Medications, Work status, or 1 lane per provider4 to 7 lanes. Same spelling every row
labelShort name: "Lumbar MRI", "Gabapentin 600 mg"No commas, since the template splits on them
pagePage cite in the fileEvery row has 1. A row without a page doesn't go in
noteAnything the reader should know"end not recorded", "signed 9 days later"

Split a dose change into 2 rows that meet on the change date. Use 1 row per same-day event, so a day with 3 visits draws 3 marks you can hover.

The template: 1 HTML file, no upload

Copy the code into a text file, save it as timeline.html, and open it in your browser. It needs no internet connection and stores nothing. The sample rows come from our synthetic case (no real patient).

<!doctype html>
<html lang="en"><head><meta charset="utf-8"><title>Offline medical timeline</title>
<style>
body{font:14px system-ui,sans-serif;margin:24px;color:#1d2321;background:#fff}
textarea{width:100%;height:160px;font:12px monospace}
svg text{font:11px system-ui,sans-serif}
</style></head><body>
<h1>Offline medical timeline</h1>
<p>Paste CSV with the header row below, then press Draw. Nothing leaves this file.</p>
<textarea id="csv">start,end,lane,label,page,note
2024-03-04,,Visits,ED visit,12,
2024-03-04,2024-04-15,Medications,Ibuprofen 600 mg,13,
2024-05-06,,Imaging,Lumbar MRI,58,
2024-07-15,,Procedures,ESI 2,97,
2024-11-04,,Visits,PCP visit,112,
,,Undated,Pain diagram,207,no date on page</textarea>
<p><label>Key date <input id="key" value="2024-03-04"></label>
<label>Flag gaps over <input id="gap" type="number" value="60"> days</label>
<button id="go">Draw</button></p>
<svg id="out" width="100%" viewBox="0 0 900 300" role="img" aria-label="Timeline"></svg>
<ul id="undated"></ul>
<script>
var NS="http://www.w3.org/2000/svg";
function day(s){return Date.UTC(+s.slice(0,4),+s.slice(5,7)-1,+s.slice(8,10))/864e5}
function el(t,a,txt){var n=document.createElementNS(NS,t);for(var k in a)n.setAttribute(k,a[k]);if(txt)n.textContent=txt;return n}
function draw(){
 var lines=document.getElementById("csv").value.trim().split("\n").slice(1);
 var rows=lines.map(function(l){var c=l.split(",");return {s:c[0],e:c[1],lane:c[2],label:c[3],page:c[4]}});
 var dated=rows.filter(function(r){return r.s}),und=rows.filter(function(r){return !r.s});
 var svg=document.getElementById("out");svg.innerHTML="";
 var lanes=[];dated.forEach(function(r){if(lanes.indexOf(r.lane)<0)lanes.push(r.lane)});
 var lo=Math.min.apply(0,dated.map(function(r){return day(r.s)}))-7;
 var hi=Math.max.apply(0,dated.map(function(r){return day(r.e||r.s)}))+7;
 var x=function(d){return 130+(d-lo)/(hi-lo)*750};
 var H=40+lanes.length*40;svg.setAttribute("viewBox","0 0 900 "+(H+20));
 lanes.forEach(function(l,i){svg.appendChild(el("rect",{x:130,y:30+i*40,width:750,height:32,fill:"#eef3f1"}));
  svg.appendChild(el("text",{x:4,y:50+i*40},l))});
 var contact=dated.map(function(r){return day(r.s)}).sort(function(a,b){return a-b});
 var g=+document.getElementById("gap").value;
 for(var i=1;i<contact.length;i++){var d=contact[i]-contact[i-1];if(d>g){
  svg.appendChild(el("rect",{x:x(contact[i-1]),y:24,width:x(contact[i])-x(contact[i-1]),height:H-20,fill:"#f4c542","fill-opacity":".3"}));
  svg.appendChild(el("text",{x:x(contact[i-1])+4,y:H+12},d+" days"))}}
 var k=document.getElementById("key").value;if(k){var kx=x(day(k));
  svg.appendChild(el("line",{x1:kx,x2:kx,y1:20,y2:H,stroke:"#1d2321","stroke-dasharray":"4 3"}))}
 dated.forEach(function(r){var y=30+lanes.indexOf(r.lane)*40,m;
  if(r.e){m=el("rect",{x:x(day(r.s)),y:y+9,width:Math.max(3,x(day(r.e))-x(day(r.s))),height:14,rx:3,fill:"#2e7d32"})}
  else{m=el("circle",{cx:x(day(r.s)),cy:y+16,r:6,fill:"#1565c0"})}
  m.appendChild(el("title",{},r.s+(r.e?" to "+r.e:"")+": "+r.label+", p. "+r.page));svg.appendChild(m)});
 var u=document.getElementById("undated");u.innerHTML="";
 und.forEach(function(r){var li=document.createElement("li");li.textContent="Undated: "+r.label+", p. "+r.page;u.appendChild(li)});
}
document.getElementById("go").onclick=draw;draw();
</script></body></html>

Template written for this site on 2026-11-12. Free to copy and change. It handles simple CSV only: no commas or quotes inside fields.

Steps from export to figure

  1. Export the cited table. From your review tool, export to Excel or CSV. If you only get Word or PDF, copy the table into a spreadsheet.
  2. Trim to 6 columns. Keep start, end, lane, label, page and note. Drop narrative text; the figure needs labels, not paragraphs.
  3. Fix spans. Give every medication and work-status row an end date, or leave it empty and write "end not recorded" in the note.
  4. Save as CSV and paste. Open timeline.html, paste over the sample rows, set the key date and gap threshold, and press Draw.
  5. Check it. Run the 12-point checklist, then print in grayscale to confirm lanes still read.
  6. Save the figure with its table. Print to PDF and attach the CSV or the cited table, so every mark can be traced.

Other ways to draw it, and the privacy catch

OptionGood forPrivacy catch
This templateLanes, bars, gaps, key date; offlineNone: the file never leaves your machine
Excel stacked bar chartDuration bars (a hidden first series as the offset)Fine on a covered device; no swimlane labels without work
Lucen Timeline (formerly Office Timeline)Polished PowerPoint figure with swimlanes; imports from ExcelA project tool; keep it to de-identified data unless your IT covers it
PrecedenQuick web timelines; free plan allows 10 events per timelineWeb service with no BAA described; de-identified data only
TimelineJSSlide-style interactive storyRequires publishing the Google Sheet to the web: never with patient data

Tool facts from each vendor's site, read 2026-11-12. Sources are on the tools page.

Questions about drawing a medical timeline

Can I make a medical timeline in Excel?

Yes, as a stacked bar chart: 1 hidden series for the start date and 1 visible series for the duration. It handles bars well and single events poorly. The HTML template above does both.

Is it safe to use an online timeline maker with patient records?

Only if the service signs a BAA with you. The general timeline makers we looked at don't describe 1. Use de-identified data or an offline file.

What date should a timeline use for a late-signed note?

The date of service. Put the signing date in the note column if the delay matters.