TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 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.