TreeMap
A free, open-source disk-space visualizer. Squarified treemap, duplicate hunting, disk-full forecasting, and cleanup that only ever moves files to the Trash.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Your notes from Google Drive — PDFs, notebook photos and AI summaries — as books on the shelves of a 3D study room.
▶ Try the live demo — opens a sample library, no sign-in needed.
OAuth is in production; general rollout is still being prepared. The local Phase 6 code no longer requires a setup URL parameter; the deployed preview stays on its previous version until an approved push. The preview may require Vercel sign-in. The live demo above is a separate, sign-in-free sample.
Open the Phase 6 preview to try this flow with an authorised account. The interface is currently in Turkish; button labels below match the app.
# Basics starts a unit; following lines such as Variables and Conditions are its topics. Review the preview and press Oluştur.Normal accounts use the narrow drive.file permission. Files added manually in Drive are not automatically visible to Defter, even if placed inside its library folder: add them through Dosya ekle. The configured owner account can use broader Drive access for its existing library.
Read the privacy policy and terms of use. These are the policy files in this repository branch; publishing them on the production site is still pending.
As a student my notes live in three places at once: handwritten notebooks, lecture PDFs on my laptop, and summaries I create with AI tools. Each course ends up scattered across folders, photos and chat exports, and there is no single place that shows what I have for a course and how far I am with it.
Defter turns one Google Drive folder into a personal library. Every course or topic is a book; its units and topics point to the PDFs, notebook photos, AI outputs and links that belong together. The files stay in your own Drive; Defter organises them and saves the changes you make through the app.
| A 3D study room — a lit diorama with desk, plants, window and a bookcase, rendered with three.js. | |
| Day and evening — switch manually or automatically after 18:00; the sun sets, the moon rises and the desk lamp turns on. | |
| Your shelves — books are generated from Drive folders (cloth or leather covers, ribbons, dust on books you haven't opened in weeks). Drag books between shelves; new folders appear in the new arrivals pile. | |
| Open a book — it flies to the desk and opens on a title page and a table of contents with its units and topics, each with a status (unread → reading → read → studied → review). | |
| Add your notebook — photograph handwritten pages; Defter finds the page, straightens it and appends it to the topic's summary PDF. PDFs and images can be added to a topic as well. | |
| Search — find books, topics and files by name, and words inside your PDFs (Drive's full-text search), and in handwriting that has been read. In the reader, search the open file: matches are highlighted and you jump between them. |
<name>.ocr.json. Nothing is read automatically, so no money is spent unasked; the buttons appear only for the owner's account when the server has its Anthropic key.The interface is in Turkish for now; an English option is planned.
In Phase 2 the room got realistic lighting without changing its design:
?oda=eski forces it).Phase 3 turned the books into something you can actually read. A topic opens its lecture PDF, summary, exercise sheets and assignments as tabs, straight from Drive.
modifiedTime, so a changed file is fetched again automatically. Above 500 MB the least recently opened files are removed.kitap.json, applies only the fields that changed in this session, and checks modifiedTime again; if another device wrote in between, it retries. It always updates the same file (never creates a copy), keeps unknown fields, and holds the patch in memory while offline.The live demo uses two PDFs generated by scripts/demo-pdf-uret.mjs (a 64-page portrait document and 24 landscape slides). Their text was written for the demo, so no lecture material is published.
Phase 4 added handwriting. With an Apple Pencil (or a mouse on the laptop) you can write straight onto any page, and the notes are saved inside the PDF itself, not in a separate format.
/AP), so the notes also show up in the Drive preview, Preview, Acrobat and other readers. Defter marks its own notes with a /DefterId key and only ever adds, changes or removes those. The page content, other annotations, form fields, metadata and page order stay untouched; signed PDFs are never written./AP stream all come from the same shape function, so what you see is what is saved.PATCH, resumable above 5 MB). If the file changed in between, it starts again (up to three times). Before the very first write, the original version is kept forever in Drive's revision history (keepForever). Offline, the diff waits and is retried.flowchart LR
Pen["Apple Pencil / mouse"] --> Layer["SVG layer<br/>PDF user space"]
Layer --> IDB[("IndexedDB<br/>net diff per file")]
IDB --> Read["read latest PDF<br/>from Drive"]
Read --> Merge["merge by stroke id<br/>(pdf-lib)"]
Merge --> Write["write touched pages<br/>Ink + /AP"]
Write --> Patch["PATCH same file id"]
Patch -->|changed meanwhile| Read
Patch -->|offline / 5xx| IDB
Try it: open the demo, choose Programlamaya Giriş → Değişkenler ve veri tipleri → the Özet tab. The summary already has a few handwritten notes; tap the pen button to add your own. The demo never writes to Drive — your strokes stay in your browser.
Phase 5 brought the paper notebook in. A photo of a handwritten page becomes a real page at the end of the topic's summary PDF, and lecture files, exercise sheets or solutions can be added to a topic straight from the reader.
ozet.pdf is created in the topic folder.keepForever), and if the file changed in between, Defter starts again.X_cozum.pdf next to X.pdf), or Orijinal / Özet when the topic doesn't have one yet. In the Phase 6 code, missing Uebungen/ or Oedevler/ folders are created only when the first file is added, after checking the library and parent folders. A file with the same name is never overwritten or renamed — you pick another name. A pre-allocated Drive file id and an operation id make sure a retry never creates a second copy. Files are limited to 50 MB; Keynote and Pages files get the hint save as PDF, then add.| Corner editor: drag the four corners onto the page. | Dosya ekle: three images become one PDF in Übungen. |
The screenshots come from the demo library, where adding is shown as a preview only (Ekle is disabled); the photos in them are generated by scripts/screenshots.mjs.
flowchart LR
Photo["photo / image / PDF"] --> Crop["find page + straighten<br/>(or corner editor)"]
Crop --> IDB[("IndexedDB<br/>until uploaded")]
IDB --> Queue["write queue<br/>(after pending strokes)"]
Queue --> Has{"summary<br/>exists?"}
Has -->|yes| Append["append pages<br/>PATCH same file id"]
Has -->|no| Create["create ozet.pdf<br/>pre-allocated id"]
Append -->|changed meanwhile| Queue
Append --> Reader["open reader<br/>refreshes"]
Create --> Reader
Search arrived in Phase 6. Ara (or /, Ctrl+F) opens one panel for the whole library; inside the reader, the search bar looks through the open file.
| The library panel: books, topics and files. | In the reader: matches highlighted, 6/25 and arrows to move between them. |
blatt-01_cozum.pdf), from a tree of the library that is built once and kept for ten minutes.fullText search. Drive matches whole words only (no prefixes), and needs some time to index a newly added file. The query is limited to the folders of the library, results are kept only if they belong to a known book, and Defter's temporary conversion files are left out. Search only ever reads from Drive (GET requests).fetchEverything runs in the browser. There is no backend: the app talks to Google directly with a short-lived access token.
flowchart LR
subgraph Browser["Browser (iPad / laptop)"]
UI["UI<br/>top bar, panel, reader"]
Scene["3D scene<br/>three.js"]
Model["Data model<br/>parse · validate · serialize"]
Auth["auth.ts<br/>token in memory"]
Drive["drive.ts<br/>fetch wrapper"]
end
GIS["Google Identity Services<br/>(sign-in popup)"]
API["Google Drive API v3"]
Folder[("My Drive / Kitaplık<br/>kitaplik.json<br/>kitaplar/<id>/kitap.json")]
UI --> Scene
UI --> Model
Scene --> Model
Auth <-->|access token| GIS
Drive -->|Bearer token| API
Auth --> Drive
Model <--> Drive
API <--> Folder
The room geometry has one source: the three.js scene. Blender only adds light.
flowchart LR
App["three.js room<br/>(dev export)"] -->|oda-kaynak.glb| Build["Blender<br/>build_room.py<br/>day + evening lights"]
Build --> Bake["bake.py<br/>Cycles (OptiX)<br/>diffuse light, no colour"]
Bake -->|"2 lightmaps<br/>2048 px PNG + scale"| Models[("public/models<br/>oda.glb<br/>lightmap_gunduz.png<br/>lightmap_aksam.png")]
Bake -->|"glTF, 2nd UV set"| GT["gltf-transform<br/>meshopt + WebP"]
GT --> Models
Models --> Mobile["mobil.py<br/>1024 px copies"]
Mobile --> Models
Models --> Room["three.js<br/>colour × mix(day, evening)"]
Live["bookcase + books<br/>live lights & shadows"] --> Room
A folder named Kitaplık in the root of My Drive:
Kitaplık/
kitaplik.json ← shelves (in order) and room settings
kitaplar/<book-id>/ ← one folder per book; folder name = book id
kitap.json ← title, spine, code, course, cover, units and topics
Unite-01-.../Konu-01-.../ ← one folder per topic
orijinal.pdf ← lecture material
ozet.pdf ← summary (or brifing.pdf + sorular.pdf)
Uebungen/*.pdf ← exercise sheets
Oedevler/*.pdf ← assignments
kitaplik.json — the library:
{
"surum": 1,
"raflar": [{ "id": "dersler", "ad": "Dersler", "kitaplar": ["programlamaya-giris", "lineer-cebir"] }],
"oda": { "duvar": "#efe6d8", "zemin": "mese", "mod": "otomatik" }
}
kitap.json — one book:
{
"surum": 2,
"baslik": "Programlamaya Giriş",
"sirt": "Programlama",
"kod": "PRG",
"ders": "Bilgisayar Bilimi",
"kapak": { "renk": "#24476b", "stil": "kumas" },
"sonAcilis": null,
"kurdele": { "konu": "Unite-01-Temeller/Konu-02-Kosullar", "materyal": "ozet", "dosya": "ozet.pdf", "sayfa": 7 },
"uniteler": [
{
"baslik": "Temeller",
"konular": [
{ "baslik": "Değişkenler ve veri tipleri", "klasor": "Unite-01-Temeller/Konu-01-Degiskenler", "durum": "calisildi" },
{
"baslik": "Koşullar ve döngüler",
"klasor": "Unite-01-Temeller/Konu-02-Kosullar",
"durum": "tekrar",
"kurdeleler": { "ozet": { "dosya": "ozet.pdf", "sayfa": 7 } }
}
]
}
]
}
uniteler), a unit has topics (konular). klasor is the topic's folder, relative to the book folder.kitap.json. Names are case-insensitive: orijinal.pdf (original), ozet.pdf or else brifing.pdf + sorular.pdf (summary), Uebungen/*.pdf and Oedevler/*.pdf (alphabetical). X_cozum.pdf is the solution of X.pdf in the same folder. Missing materials are hidden; a topic without any shows no material yet.durum (topic status), in this order: okunmadi (unread) → okunuyor (reading) → okundu (read) → calisildi (studied) → tekrar (review). Tapping cycles through them; the reader only moves a topic forward on its own (unread → reading → read).kurdeleler keeps the last page per material of a topic (orijinal · ozet · uebungen · oedevler); the book-level kurdele points to the last place read in the whole book.surum: 1 books (a flat bolumler list with kaynaklar) still open: their chapters appear as topics of a single unit called Genel.kitap.json still appears (folder name, grey cover). Books that are on no shelf appear in the new arrivals pile.This section is for developers running their own copy. For the hosted preview, use Getting started above. You need Node.js 20+ and a Google account.
git clone https://github.com/denizyarpinar/defter.git
cd defter
npm install
npm run dev, then open http://localhost:5173/?demo. The sample library comes from public/ornek/.http://localhost:5173 under Authorized JavaScript origins..env.local in the project root (it is git-ignored):
VITE_GOOGLE_CLIENT_ID=1234567890-abc.apps.googleusercontent.com
[email protected]
VITE_SAHIP_EPOSTA (optional): this account asks for full Drive access; everyone else gets drive.file. Without it, everyone gets drive.file.Kitaplık/kitaplar/ library; that legacy layout is described above.npm run dev. For normal setup testing, open the local app without parameters, then sign in with Google. Setup starts only when you press its button. For diagnostics, add ?olcum=1; do not force the scope or owner when testing a real second account.Other scripts: npm run build (production build into dist/), npm run typecheck (tsc --noEmit), npm run preview, npm run screenshots (regenerates the images in docs/; needs Chrome and ffmpeg; with SHOTS=faz5 only the three Phase 5 images, with SHOTS=arama only the two search images; neither needs ffmpeg).
To deploy on Vercel, import the repository, set VITE_GOOGLE_CLIENT_ID as an environment variable, and add the Vercel URL to the Client ID's authorized JavaScript origins.
Defter is my first larger project, and I built it together with Claude Code, Anthropic's AI coding agent.
The product and architecture decisions are mine: the idea, the study-room concept and a clickable prototype I approved before writing the app, the Drive folder structure and JSON data model, the "no server, token only in memory" approach, and the rules for what the app may write to Drive. I split the work into small tasks, reviewed the plan for each one, and tested every step myself.
Most of the code was written by Claude Code from those plans. Working this way taught me a lot about three.js, OAuth and the Drive API, and about describing software precisely enough that it can be built.
Deniz Yarpinar — Informatik @ Universität Bremen
Defter ist eine Web-App, die Lernunterlagen aus Google Drive – PDFs, Fotos aus handschriftlichen Heften und KI-Zusammenfassungen – als Bücher in einem 3D-Arbeitszimmer darstellt. Jedes Fach ist ein Buch mit Einheiten und Themen; Bücher lassen sich per Drag-and-drop zwischen Regalen verschieben, und die Anordnung wird zurück nach Google Drive gespeichert. PDFs werden direkt aus Drive gelesen und mit dem Apple Pencil beschriftet; Fotos aus dem Heft werden automatisch zugeschnitten und an die Zusammenfassung angehängt, und PDFs oder Bilder lassen sich einem Thema hinzufügen. Word- und PowerPoint-Dateien werden über Google Drive automatisch in PDF umgewandelt. Die App läuft komplett im Browser (TypeScript, three.js, Google Identity Services, Drive API) und ist für das iPad optimiert. Konzept, Datenmodell und Architektur stammen von mir; der Großteil des Codes wurde mit Claude Code geschrieben.
© 2026 Deniz Yarpinar. All rights reserved.
kitaplar/<book>/); conversion uses a temporary Google file. The Phase 6 code can also create library folders and JSON settings, and trash selected items after confirmation, with undo. Created items are marked with appProperties.defter = "1"; the app does not permanently delete Drive files.