A spreadsheet for working with sequences of SMPTE timecode. Edit timecodes like cells in Excel, copy/paste between this and your spreadsheet of choice, and use cascade mode to re-time a sequence by shifting every subsequent cell by the same delta.
- Spreadsheet-style grid with cell selection, arrow/Tab/Enter navigation, undo/redo, and clipboard copy/paste (TSV).
- Frame rates: 23.976, 24, 25, 29.97, 30, 50, 59.94, 60. Drop-frame supported on 29.97 and 59.94 with proper SMPTE math.
- View toggle: switch between timecode (
HH:MM:SS:FF/HH:MM:SS;FF) and raw frame counts. Underlying data is always stored as integer frames, so frame-rate switches are lossless. - Cascade mode (Off / Column / Row): when you edit a cell, every subsequent cell in the same column or row shifts by the same delta. One undo reverts the entire cascade.
- Lenient parsing: input accepts any mix of
:and;separators (00:00:01:00,00:00:01;00,00;00;01;00all work). Output is canonical for the current rate. - Paste-to-grow: pasting a range that overflows the grid auto-extends rows and columns.
- Add row / Add column buttons at the grid edges.
- CSV export in either timecode or frames format (RFC 4180 quoting,
\r\nline endings). - Autosaves to localStorage — your grid, frame rate, view mode, and cascade mode survive page reloads.
- No font/color/formatting controls — focused on timecode work.
- Vue 3 (Composition API,
<script setup>SFCs) - TypeScript (strict)
- Vite 8
- Tailwind CSS v4
- Vitest
npm install
npm run dev # http://localhost:5173
npm test # timecode unit tests (drop-frame round-trips etc.)
npm run build # production bundle in dist/Vite 8 wants Node 20.19+ or 22.12+. Older versions may still work but emit warnings.
The display name lives in a single constant — change it in src/config.ts:
export const APP_NAME = 'Mr. Timecode';The browser tab title, the header label, and the CSV export filename all read from APP_NAME. No other code identifiers reference the name.
src/
├── main.ts # entry, hydrates state and mounts Vue app
├── App.vue # toolbar + grid layout
├── config.ts # APP_NAME, defaults, supported frame rates
├── types.ts # FrameRate, ViewMode, CascadeMode, Cell, Grid
├── timecode/
│ ├── timecode.ts # parse/format, NDF + DF math
│ └── timecode.test.ts # unit tests
├── store/
│ ├── grid.ts # cells, dims, edit/paste/range ops
│ ├── settings.ts # frame rate, view mode, cascade mode
│ ├── history.ts # undo/redo snapshot stack
│ └── persistence.ts # localStorage hydrate + autosave
├── components/
│ ├── Toolbar.vue # frame rate / DF toggle / view / cascade / export
│ ├── Grid.vue # table render, selection, keyboard nav, paste
│ └── Cell.vue # editable cell
├── composables/
│ ├── useCascade.ts # apply delta to downstream cells
│ ├── useClipboard.ts # copy/cut/paste handlers
│ └── useCsvExport.ts # build CSV blob, trigger download
└── styles.css
| Key | Action |
|---|---|
↑ ↓ ← → |
Move selection |
Tab / Shift+Tab |
Move right / left |
Enter |
Start edit, or commit and move down |
Shift+Enter |
Commit and move up (in editor) |
Esc |
Cancel edit |
F2 |
Start edit on selected cell |
Delete / Backspace |
Clear selected cells |
Ctrl/Cmd+C / Ctrl/Cmd+X / Ctrl/Cmd+V |
Copy / Cut / Paste (TSV) |
Ctrl/Cmd+Z |
Undo |
Ctrl/Cmd+Y / Ctrl/Cmd+Shift+Z |
Redo |
MIT