A local-first graphics editor for developers shipping web assets.
Create OG images, social cards, banners, thumbnails, icons, and screenshots without leaving the browser.
Developer-facing assets are usually small, frequent, and annoyingly disruptive: an OG image for a release, a thumbnail for a demo, a social card, or an icon. Glyft keeps that work in a focused browser editor with familiar canvas controls and no account requirement.
- Local-first: projects live in IndexedDB on the current browser and device.
- Fast to use: create an asset, edit it, and export it without a backend workflow.
- Portable: share reusable designs as
.glyfttemplate files. - Built for contributors: React, TypeScript, Fabric.js, Vitest, and a small local-first architecture.
Project data stays in this browser. Export a template or recovery artifact before clearing browser storage, changing browsers, or moving to another machine.
Open glyft.vercel.app/editor, create a project, edit, and export.
Requirements: Node.js 22 and npm. npm is the repository's supported package manager; package-lock.json is authoritative.
git clone https://github.com/cadornajansen/glyft.git
cd glyft
npm ci
npm run devThen open:
http://localhost:3000- landing pagehttp://localhost:3000/editor- editor
- Create a project or choose a starter preset.
- Add rectangles, circles, lines, arrows, text, images, or SVGs.
- Use the properties panel for size, fill, stroke, opacity, typography, shadows, and transforms.
- Organize layers with names, visibility, locking, grouping, and ordering.
- Export PNG, JPEG, WebP, or SVG.
Use Export -> Save as template to create a portable .glyft package. Use Import .glyft to load it into a new project. Template packages can include referenced image assets; installed fonts are referenced by family name and are not bundled.
Glyft validates stored canvas documents before reconstructing Fabric objects. Invalid individual objects are skipped with a warning; a fatal document error opens a recovery dialog where you can download the original project record before replacing or deleting it.
| Action | Shortcut |
|---|---|
| Select | V |
| Pan | H or hold Space and drag |
| Add rectangle | R |
| Add circle | C |
| Add text | T |
| Import image | I |
| Delete selection | Delete / Backspace |
| Copy / paste | Cmd/Ctrl + C / Cmd/Ctrl + V |
| Undo / redo | Cmd/Ctrl + Z / Cmd/Ctrl + Shift + Z or Cmd/Ctrl + Y |
| Duplicate | Cmd/Ctrl + D |
| Group | Cmd/Ctrl + G |
| Fit document | Cmd/Ctrl + 0 |
| Zoom to 100% | Cmd/Ctrl + 1 |
Glyft has no editor backend. A project record contains its metadata, thumbnail, and serialized canvas document; Dexie persists that record in IndexedDB.
edit canvas
-> CanvasController serializes a versioned document
-> autosave writes the project record transactionally
-> IndexedDB stores it in the current browser
Exports are generated from document coordinates, not the current pan or zoom. The visible workspace state does not change exported composition or dimensions.
npm run dev # Vite development server on port 3000
npm run lint # TypeScript type-check
npm run test # Vitest unit tests
npm run build # production build
npm run preview # preview the production buildBefore opening a pull request, run:
npm run lint
npm run test
npm run buildGitHub Actions runs the same install, type-check, test, and build sequence for pull requests targeting main.
src/
├── app/ application composition, routing, global styles
├── features/
│ ├── editor/
│ │ ├── canvas/ Fabric controller, documents, history, viewport, selection
│ │ ├── components/ toolbar, properties, layers, status, export UI
│ │ ├── export/ document-coordinate export service
│ │ └── state/ Zustand editor state and UI contracts
│ ├── projects/
│ │ ├── persistence/ Dexie records and safe transactional updates
│ │ ├── recovery/ corrupt-project recovery download and dialog
│ │ └── session/ project activation, switching, autosave sequencing
│ └── templates/ portable .glyft packages and template catalog
├── components/ application-level sidebar shell
└── pages/ landing and editor route wrappers
The boundaries that matter most:
- Canvas owns document behavior. Fabric object restoration, validation, history, selection, viewport, and export coordinates live under
features/editor/canvasorfeatures/editor/export. - Projects own persistence. Database writes and active-project lifecycle code stay under
features/projects. - Templates consume contracts. Portable templates use project and canvas document contracts but do not own project persistence.
- React owns UI. Prefer React state and components over injected DOM behavior.
For repository-specific rules and current architectural context, read AGENTS.md.
Contributions are welcome, especially focused fixes, tests, documentation, and well-scoped feature proposals.
- Search issues before starting.
- For larger features or architectural work, open or discuss an issue first.
- Branch from
main; keep one concern per pull request. - Preserve existing project, template, and canvas document compatibility.
- Run lint, tests, and build; manually test the affected editor workflow.
- Include screenshots or a short recording for visible UI changes.
Read CONTRIBUTING.md for the complete contribution guide and AGENTS.md for architecture and implementation constraints.
- Regression tests for persistence, canvas documents, history, and export
- Accessibility and keyboard-flow improvements
- Focused editor fixes with a manual reproduction case
- Documentation improvements and examples
- Template catalog additions with portable assets
Canvas work can affect several systems at once. When relevant, verify:
- fresh project creation and project reload;
- undo and redo;
- autosave without unrelated metadata loss;
.glyfttemplate import/export;- PNG, JPEG, WebP, and SVG export;
- malformed-document recovery behavior.
- Projects are browser-local; there is not yet a full cross-browser project backup/import workflow.
- Fonts are not bundled with templates.
- Browser interaction and pixel-level rendering still need manual validation beyond the unit suite.
Glyft is released under the MIT License.
