A metadata application profile editor implementing the DC TAP (Dublin Core Tabular Application Profile) standard.
- Workspace Management: Create, duplicate, and delete workspaces
- Spreadsheet-like Interface: Edit metadata profiles in a familiar spreadsheet format
- Shape Management: Organize properties into shapes (entity types)
- Namespace Prefixes: Manage and auto-complete namespace prefixes
- Import/Export: Import from and export to CSV/TSV files
- Validation: Real-time validation with inline error display
- Clipboard Support: Copy, cut, and paste cells and ranges
- Undo/Redo: In-session undo/redo support
- Concurrent Editing: Polling-based updates for multi-tab usage
- Backend: Node.js, Express, TypeScript, SQLite (better-sqlite3)
- Frontend: Vue 3 (Options API), Vite, TypeScript
dctap-dancer/
├── backend/ # Express API server
│ ├── src/
│ │ ├── index.ts # Server entry point
│ │ ├── routes/ # API route handlers
│ │ ├── services/ # Business logic
│ │ │ ├── database.ts # SQLite operations
│ │ │ ├── validation.ts # DCTap validation
│ │ │ └── csv-parser.ts # Import/export logic
│ │ ├── middleware/ # Error handling
│ │ └── types/ # TypeScript types
│ └── data/ # SQLite database files
│
├── frontend/ # Vue 3 SPA
│ ├── src/
│ │ ├── views/ # Page components
│ │ ├── components/ # Reusable components
│ │ │ └── spreadsheet/ # Spreadsheet editor
│ │ ├── services/ # API client
│ │ └── types/ # TypeScript types
│ └── index.html
│
└── package.json # Monorepo workspace config
- Node.js 18+
- npm 9+
# Install dependencies
npm install
# Start development servers (backend + frontend)
npm run devThe frontend will be available at http://localhost:5173 The backend API will be at http://localhost:3000
# Run backend only
npm run dev:backend
# Run frontend only
npm run dev:frontend
# Build frontend for production
npm run build
# Start production backend
npm run start| Column | Description |
|---|---|
| shapeLabel | Human-readable name for the shape |
| propertyID | IRI/CURIE of the vocabulary term (e.g., dcterms:title) - Required |
| propertyLabel | Human-friendly display name |
| mandatory | Boolean: is this property required? |
| repeatable | Boolean: can this property appear multiple times? |
| valueNodeType | RDF node type: IRI, literal, or bnode |
| valueDataType | XSD datatype (e.g., xsd:string) - only for literals |
| valueShape | Reference to another shape - only for IRI/bnode |
| valueConstraint | Constraint value(s) |
| valueConstraintType | Type: picklist, IRIstem, pattern, etc. |
| note | Explanatory text |
GET /api/workspaces- List all workspacesPOST /api/workspaces- Create workspaceGET /api/workspaces/:id- Get workspacePUT /api/workspaces/:id- Update workspaceDELETE /api/workspaces/:id- Delete workspacePOST /api/workspaces/:id/duplicate- Duplicate workspace
GET /api/workspaces/:id/shapes- List shapesPOST /api/workspaces/:id/shapes- Create shapeGET /api/workspaces/:id/shapes/:shapeId- Get shapePUT /api/workspaces/:id/shapes/:shapeId- Update shapeDELETE /api/workspaces/:id/shapes/:shapeId- Delete shape
GET /api/workspaces/:id/shapes/:shapeId/rows- List rowsPOST /api/workspaces/:id/shapes/:shapeId/rows- Create rowPUT /api/workspaces/:id/shapes/:shapeId/rows/:rowId- Update rowPUT /api/workspaces/:id/shapes/:shapeId/rows- Bulk updateDELETE /api/workspaces/:id/shapes/:shapeId/rows/:rowId- Delete row
GET /api/workspaces/:id/namespaces- List namespacesPOST /api/workspaces/:id/namespaces- Create namespacePUT /api/workspaces/:id/namespaces/:prefix- Update namespaceDELETE /api/workspaces/:id/namespaces/:prefix- Delete namespace
GET /api/workspaces/:id/folders- List foldersPOST /api/workspaces/:id/folders- Create folderPUT /api/workspaces/:id/folders/:folderId- Update folderDELETE /api/workspaces/:id/folders/:folderId- Delete folder
POST /api/import- Import CSV/TSV fileGET /api/workspaces/:id/export?format=csv|tsv- Export workspace
GET /api/marva-profile/export/:id- Download Marva/Sinopia profile JSON
POST /api/starting-point/import/:id- Import LC Starting Point JSONGET /api/starting-point/export/:id- Download Starting Points JSONGET /api/starting-point/has/:id- Check if workspace has starting points
GET /api/serve/workspaces- List workspaces with URLs to all export formatsGET /api/serve/:id/profile- Serve Marva profile JSON (cached)GET /api/serve/:id/starting-points- Serve Starting Points JSON (cached)GET /api/serve/:id/csv- Serve CSV export (cached)GET /api/serve/:id/tsv- Serve TSV export (cached)GET /api/serve/cache/stats- Cache statistics (debug)
GET /api/health- Health check endpoint
| Shortcut | Action |
|---|---|
| Arrow keys | Navigate cells |
| Enter | Edit cell |
| Escape | Cancel editing |
| Tab | Move to next cell |
| Shift+Tab | Move to previous cell |
| Delete/Backspace | Clear selection |
| Ctrl/Cmd+C | Copy |
| Ctrl/Cmd+X | Cut |
| Ctrl/Cmd+V | Paste |
| Ctrl/Cmd+Z | Undo |
| Ctrl/Cmd+Shift+Z | Redo |
Build and run the full application (frontend + backend) in a single container:
# Build image
docker build -t dctap-dancer .
# Run container
docker run -d --name dctap -p 3000:3000 -v dctap-data:/app/data dctap-dancer
# Access at http://localhost:3000The -v dctap-data:/app/data flag persists the SQLite databases between container restarts.
# Run backend tests
cd backend && npm test
# Run tests in watch mode
cd backend && npm run test:watchCreative Commons Zero v1.0 Universal