Share an entire mini-repository in a single link — everything lives in the URL hash.
Live Site · How It Works · FAQ · MIT
Fractal is a website for creating and sharing tiny self‑contained code workspaces. You build a file/folder structure, write code (multiple languages), inspect syntax trees, and then distribute the whole thing as a single URL. Visit that link and the exact project is reconstructed instantly — no archive downloads, no database lookup, no server fetch.
Why? To make teaching, debugging, discussing, and showcasing code frictionless.
- Open the site and enter the editor.
- Create folders / files in the file tree.
- Write code in Monaco-powered tabs (TS, JS, Python, Rust, Go, C, etc.).
- (Optional) Open the AST panel to explore the parsed syntax tree via Tree‑sitter.
- Click Share → a compressed hash (
#h:...) appears in the URL bar automatically. - Copy the URL, send to someone. They open it; the workspace rehydrates locally.
- (Optional) Shorten the hash (Supabase) or export as a GitHub Gist for permanence.
- [ Nearly Zero backend :) ] Everything necessary is inside the fragment after
#(browsers do not send it to servers, except for making the short link which has partial server needs). - Multi-language AST exploration: see how real parsers structure your code.
- Visual export: generate a PNG of pretty code panels for docs/social.
- Privacy by default: unless you press buttons for Gist / Shorten, nothing leaves your device.
https://fractal.very-expensive-domain.com/editor#h:<base64url-brotli-packed-project>
│
└─ starts with h: (hash pack). Alternative: #sb:<id> (short link)
Short link flow:
#h:<veryLongPayload> --(optional shorten)--> #sb:XYZ123
Browser loads #sb:XYZ123 → calls /api/shorten?id=XYZ123 → swaps back to #h:... (now self-contained)
- Virtual file tree (names, modes, contents) is linearized into a compact binary stream.
- Contents are UTF‑8, small heuristics decide placeholder vs inline for non-text.
- Stream compressed (Brotli preferred, fallback Gzip) to minimize size.
- Compressed bytes base64url encoded → put after
#h:. - On load: reverse steps → rebuild tree → open root tab(s)/UI state.
- Tree‑sitter WASM parsers load lazily per language when an AST view is opened.
| Area | Purpose |
|---|---|
| File Tree | Create, rename, delete files & folders (context menu). |
| Tabs Bar | Switch between open files; tracks unsaved state. |
| Editor Pane | Monaco editor (themes, Vim mode via monaco-vim). |
| AST Panel | Hierarchical syntax tree (Tree-sitter) for current file. |
| Share Dialog | Hash length, shorten link, Gist export, copy buttons. |
| Toasts / Dialogs | Feedback and modals via lightweight state stores. |
Tree‑sitter grammars bundled as WASM: C, C++, Go, Rust, Python, JavaScript, TypeScript, TSX, Bash, HTML, CSS, JSON, YAML, Markdown, PHP, Java, Lua, Ruby (plus easy extension—see below).
If your desired language isn't present, you can usually drop a tree-sitter-<lang>.wasm file into the public/parsers/ folder (when self-hosting) and map it in the language configuration. The live hosted version rolls new languages periodically.
- URL length: Some platforms truncate extremely long URLs (Slack previews, certain chat apps). Use short links or Gists for very large packs.
- Binary assets: Large binaries are not fully embedded (represented as placeholders) to keep packs lightweight.
- Not an execution sandbox: Code isn’t run (future experimental feature).
- Fragment (
#...) never sent in HTTP requests: server sees only the path. - No analytics events on file contents (unless you add them yourself while self‑hosting).
- Sharing is explicit; closing the tab leaves no remote trace.
Q: Can I collaborate in real time?
A: Not yet. Real-time presence (CRDT) is a roadmap idea.
Q: Can I execute code?
A: Execution is out of scope for now; Fractal focuses on structure, sharing, and AST insight.
Q: How big can a project be?
A: Practically a few hundred KB compressed before URLs become unwieldy(10MB is a safe limit); beyond that use Gist export(max 300MB).
Q: Why not just a Pastebin?
A: Fractal preserves full directory structure + multi-file relationships, not just a single blob. And I like moulding new and intresting way to do things.
Q: Are ASTs cached?
A: Parsers load per language; AST is regenerated when the file changes (lightweight for typical snippet sizes).
pack() → varint-coded metadata + file headers + content slices
→ Brotli (Q ~5-8 configurable) with fallback Gzip
→ base64url (no padding) → #h:<payload>
Shortening stores only the base64url payload keyed by a short id in a Supabase table (optional). Gist export uploads a reconstructed textual form (one file per gist entry) and returns a gist ID which is then referenced or imported.
MIT — do anything productive & kind. See LICENSE.
Next.js · Monaco Editor · Tree‑sitter · Supabase · Brotli & Gzip ecosystems · Open source community.
Open for local development & contribution details
Clone & run:
git clone https://github.com/AtharvRG/fractal.git
cd fractal
npm install
npm run devEnvironment (optional):
GITHUB_CLIENT_ID=... (Didn't implement yet!)
GITHUB_CLIENT_SECRET=... (In Progress)
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
Production (Vercel) setup for Short Links (Supabase):
- Create a table
short_linkswith columns:id text primary key,payload text not null,created_at timestamptz default now(),expires_at timestamptz,hit_count int default 0. - In Vercel, set these environment variables (Project Settings → Environment Variables):
NEXT_PUBLIC_SUPABASE_URL— your Supabase URL (used by client reads)NEXT_PUBLIC_SUPABASE_ANON_KEY— public anon keySUPABASE_SERVICE_ROLE_KEY— service role key (server-side secret; used for writes/reads by the API). Mark this as Environment: Production and asEncrypted.
Troubleshooting:
- If shortening succeeds (rows appear) but retrieval returns "Not found" or permission errors, likely Row Level Security (RLS) prevents anon access. Ensure either:
SUPABASE_SERVICE_ROLE_KEYis set in Vercel (the server API will use it), or- Disable RLS on the
short_linkstable or add a policy allowing anon selects for that table specifically.
- Check Supabase table contents in the dashboard and confirm
idandpayloadcolumns are populated.
Tests:
npm testBuild:
npm run build && npm startContribution ideas: new parser WASMs, AST UI enhancements, compression tweaks, collaborative layer prototype.
Made with curiosity, compression, and a sprinkle of fractal geometry. 🌀