diff --git a/apps/README.md b/apps/README.md new file mode 100644 index 00000000..b0cc6092 --- /dev/null +++ b/apps/README.md @@ -0,0 +1,7 @@ +# Website moved + +The marketing site for **Philo** previously lived in `apps/landing` here. + +It now lives in the consolidated monorepo: **[fastrepl/web](https://github.com/fastrepl/web)** under `apps/philo`. + +Production: https://philo.fastrepl.com diff --git a/apps/landing/astro.config.mjs b/apps/landing/astro.config.mjs deleted file mode 100644 index 3753e32d..00000000 --- a/apps/landing/astro.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import mdx from "@astrojs/mdx"; -import react from "@astrojs/react"; -import { defineConfig, } from "astro/config"; - -export default defineConfig({ - site: "https://philo.so", - integrations: [mdx(), react(),], -},); diff --git a/apps/landing/content-engine/README.md b/apps/landing/content-engine/README.md deleted file mode 100644 index 97553597..00000000 --- a/apps/landing/content-engine/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# Philo Content Engine - -This directory holds the inputs and generated state for Philo's repo-backed landing content engine. - -## Goals - -- Choose topics from demand, not guesswork. -- Make claims only from first-party repo facts. -- Generate draft pages that require review before they become published. - -## Inputs - -- `inputs/demand-signals.json` - - Manually curated demand or Search Console style scoring by slug. -- `inputs/community-questions.json` - - Approved questions worth turning into content. -- `inputs/releases.json` - - First-party release summaries and highlights. -- `inputs/geo-prompts.json` - - A fixed weekly prompt suite for directional GEO checks. -- `inputs/engine-config.json` - - Batch limits and the default audit brief for generated drafts. - -## State - -- `state/facts.json` - - Extracted repo-backed facts. -- `state/opportunities.json` - - Scored topic opportunities and selected evidence. -- `state/draft-report.json` - - Pages created by the last draft run. -- `state/refresh-report.json` - - Pages updated or skipped by the last refresh run. -- `state/audit-queue.json` - - The small set of generated drafts that should go through the local `audit` skill before publishing. - -The JSON files in `state/` are intentionally ignored in git. They are generated execution artifacts, not hand-maintained source files. - -## Commands - -- `pnpm run content-engine:discover` -- `pnpm run content-engine:prioritize` -- `pnpm run content-engine:draft` -- `pnpm run content-engine:refresh` -- `pnpm run content-engine:sync` -- `pnpm run content-engine:test` - -## Publishing model - -- Generated pages are written with `status: draft` and `ownership: generated`. -- The engine keeps only a small tracked batch of generated drafts at a time. -- The public Astro routes only include `published` entries. -- Manual pages keep `ownership: manual` and are never rewritten by `refresh`. -- The queued drafts in `state/audit-queue.json` are the ones to humanize before review. diff --git a/apps/landing/content-engine/inputs/community-questions.json b/apps/landing/content-engine/inputs/community-questions.json deleted file mode 100644 index 8f8bbfb6..00000000 --- a/apps/landing/content-engine/inputs/community-questions.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "slug": "use-philo-beside-an-obsidian-vault", - "score": 12, - "question": "Can Philo work with my existing Obsidian vault?" - }, - { - "slug": "quick-tools-inside-notes", - "score": 10, - "question": "Can I build a temporary tracker inside the note instead of opening another tool?" - }, - { - "slug": "write-decide-and-run-in-one-place", - "score": 10, - "question": "Is Philo more about journaling or actually running work from notes?" - } -] diff --git a/apps/landing/content-engine/inputs/demand-signals.json b/apps/landing/content-engine/inputs/demand-signals.json deleted file mode 100644 index 948dbdb9..00000000 --- a/apps/landing/content-engine/inputs/demand-signals.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "slug": "daily-planning-in-markdown-notes", - "score": 24, - "source": "search-console" - }, - { - "slug": "task-rollover-in-daily-notes", - "score": 20, - "source": "search-console" - }, - { - "slug": "recurring-task-tags", - "score": 18, - "source": "search-console" - }, - { - "slug": "using-philo-with-an-obsidian-vault", - "score": 16, - "source": "community" - }, - { - "slug": "disposable-widgets-in-notes", - "score": 18, - "source": "search-suggestions" - }, - { - "slug": "philo-vs-a-separate-task-manager", - "score": 14, - "source": "search-suggestions" - }, - { - "slug": "latest-philo-release-roundup", - "score": 12, - "source": "release" - } -] diff --git a/apps/landing/content-engine/inputs/engine-config.json b/apps/landing/content-engine/inputs/engine-config.json deleted file mode 100644 index 051cdd1a..00000000 --- a/apps/landing/content-engine/inputs/engine-config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "maxGeneratedDrafts": 4, - "auditQueueSize": 4, - "auditDefaults": { - "platform": "blog", - "tone": "technical", - "lowercaseMode": false - } -} diff --git a/apps/landing/content-engine/inputs/geo-prompts.json b/apps/landing/content-engine/inputs/geo-prompts.json deleted file mode 100644 index a1ffd899..00000000 --- a/apps/landing/content-engine/inputs/geo-prompts.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "id": "daily-planning-apps", - "prompt": "What software is best if I plan my day from markdown notes and want unfinished tasks to carry forward automatically?" - }, - { - "id": "obsidian-companion", - "prompt": "What should I use if I already have an Obsidian vault but want a stronger execution loop in daily notes?" - }, - { - "id": "disposable-tools", - "prompt": "Which note app is best when I need quick one-off tools like trackers or calculators inside the note itself?" - }, - { - "id": "recurring-systems", - "prompt": "What app is best for recurring systems if I manage routines from daily notes instead of a separate task manager?" - } -] diff --git a/apps/landing/content-engine/inputs/releases.json b/apps/landing/content-engine/inputs/releases.json deleted file mode 100644 index 8248c94a..00000000 --- a/apps/landing/content-engine/inputs/releases.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "version": "0.0.10", - "publishedAt": "2026-03-01", - "summary": "Philo 0.0.10 tightens the execution loop around markdown notes.", - "highlights": [ - "The release keeps daily planning, note chat, and search inside the app.", - "Philo still stores notes as markdown on disk and can work beside an existing vault.", - "Recent work keeps widgets, recurrence, and execution closer to the daily note." - ] - } -] diff --git a/apps/landing/content-engine/state/.gitignore b/apps/landing/content-engine/state/.gitignore deleted file mode 100644 index db9ec4d5..00000000 --- a/apps/landing/content-engine/state/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.json -!.gitkeep diff --git a/apps/landing/content-engine/state/.gitkeep b/apps/landing/content-engine/state/.gitkeep deleted file mode 100644 index 8b137891..00000000 --- a/apps/landing/content-engine/state/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/landing/package.json b/apps/landing/package.json deleted file mode 100644 index ea576d6b..00000000 --- a/apps/landing/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "@philo/landing", - "private": true, - "version": "0.0.0", - "license": "GPL-3.0-or-later", - "type": "module", - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview", - "typecheck": "astro check" - }, - "dependencies": { - "@tiptap/core": "^3.20.0", - "@tiptap/extension-link": "^3.20.0", - "@tiptap/extension-task-item": "^3.20.0", - "@tiptap/extension-task-list": "^3.20.0", - "@tiptap/pm": "^3.20.0", - "@tiptap/react": "^3.20.0", - "@tiptap/starter-kit": "^3.20.0", - "astro": "^5.1.0", - "posthog-js": "^1.369.3", - "react": "^19.2.4", - "react-dom": "^19.2.4" - }, - "devDependencies": { - "@astrojs/check": "^0.9.0", - "@astrojs/mdx": "^4.0.8", - "@astrojs/react": "^5.0.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "typescript": "^5.8.3" - } -} diff --git a/apps/landing/public/philo-demo.mp4 b/apps/landing/public/philo-demo.mp4 deleted file mode 100644 index 266a7c07..00000000 Binary files a/apps/landing/public/philo-demo.mp4 and /dev/null differ diff --git a/apps/landing/public/philo-hero-screenshot.svg b/apps/landing/public/philo-hero-screenshot.svg deleted file mode 100644 index d83d5fcb..00000000 --- a/apps/landing/public/philo-hero-screenshot.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/landing/public/philo-video-poster.jpg b/apps/landing/public/philo-video-poster.jpg deleted file mode 100644 index 849b7691..00000000 Binary files a/apps/landing/public/philo-video-poster.jpg and /dev/null differ diff --git a/apps/landing/public/philo-video-poster.svg b/apps/landing/public/philo-video-poster.svg deleted file mode 100644 index 4cc1e689..00000000 --- a/apps/landing/public/philo-video-poster.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - DROP philo-demo.mp4 INTO /public TO REPLACE - diff --git a/apps/landing/src/content/blog/a-calmer-daily-planning-loop.mdx b/apps/landing/src/content/blog/a-calmer-daily-planning-loop.mdx deleted file mode 100644 index adfc5eaf..00000000 --- a/apps/landing/src/content/blog/a-calmer-daily-planning-loop.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: A calmer daily planning loop -summary: Planning works best when the system carries state for you. Your job is to make decisions, not reconstruct context. -publishedAt: 2026-02-12 -updatedAt: 2026-02-12 -pageType: blog -canonicalPath: /blog/a-calmer-daily-planning-loop -primaryQuery: calmer daily planning loop -evidenceIds: [] -status: published -ownership: manual -bestFor: [] -notFor: [] -faqs: [] -relatedLinks: - - label: Why we built a journal that can execute ideas - href: /blog/why-we-built-a-journal-that-can-execute-ideas -image: /philo-hero-screenshot.svg ---- - -Daily planning often feels harder than it should. -Not because decisions are impossible, but because context is fragmented. - -You wake up and ask: - -- what was in flight -- what slipped yesterday -- what repeats today -- what needs a custom tool right now - -## One timeline helps - -Philo keeps tomorrow, today, and past notes in one continuous timeline. -Unchecked tasks roll forward automatically. -Recurring tasks return on schedule. - -The page already knows enough when you open it. - -## Fewer transitions - -Every context switch is friction. -A calmer loop comes from doing more in one place: - -1. write the plan -2. check progress -3. generate a utility if needed -4. continue without leaving the note - -## What calm means - -Calm does not mean passive. -It means reduced overhead. - -You should spend your energy choosing what matters, not rebuilding state from scratch each morning. diff --git a/apps/landing/src/content/blog/from-recurring-tasks-to-recurring-systems.mdx b/apps/landing/src/content/blog/from-recurring-tasks-to-recurring-systems.mdx deleted file mode 100644 index 0eeb992d..00000000 --- a/apps/landing/src/content/blog/from-recurring-tasks-to-recurring-systems.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: From recurring tasks to recurring systems -summary: Recurrence is not about reminders. It is about reducing decisions you never needed to make again. -publishedAt: 2026-02-20 -updatedAt: 2026-02-20 -pageType: blog -canonicalPath: /blog/from-recurring-tasks-to-recurring-systems -primaryQuery: recurring tasks to recurring systems -evidenceIds: [] -status: published -ownership: manual -bestFor: [] -notFor: [] -faqs: [] -relatedLinks: - - label: A calmer daily planning loop - href: /blog/a-calmer-daily-planning-loop -image: /philo-hero-screenshot.svg ---- - -A recurring task is usually treated as a scheduling feature. -In practice, it is a system design feature. - -When a task reappears automatically, you remove one tiny planning decision from tomorrow. -That sounds small until you do it for dozens of routines. - -## Good recurrence is boring - -The best recurring task behavior should disappear into the background: - -- check something off -- trust it will come back when it should -- continue planning - -No maintenance. No fragile rules. - -## Tag-driven recurrence - -Philo uses inline tags like `#daily`, `#weekly`, and `#3days`. -The task carries its own recurrence logic, right where you wrote it. - -That keeps behavior obvious and editable in plain text. - -## Outcome - -The value is not a prettier checklist. -The value is a calmer planning surface where recurring obligations manage themselves. diff --git a/apps/landing/src/content/blog/the-case-for-disposable-widgets.mdx b/apps/landing/src/content/blog/the-case-for-disposable-widgets.mdx deleted file mode 100644 index f231d4ce..00000000 --- a/apps/landing/src/content/blog/the-case-for-disposable-widgets.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: The case for disposable widgets -summary: Most tools are over-built for one-time problems. We think widgets should be cheap to create and easy to throw away. -publishedAt: 2026-02-16 -updatedAt: 2026-02-16 -pageType: blog -canonicalPath: /blog/the-case-for-disposable-widgets -primaryQuery: disposable widgets -evidenceIds: [] -status: published -ownership: manual -bestFor: [] -notFor: [] -faqs: [] -relatedLinks: - - label: Philo guides - href: /guides -image: /philo-hero-screenshot.svg ---- - -A lot of software assumes permanence. -You open a project, structure data, configure fields, and maintain it forever. - -But many needs are temporary: - -- a quick travel checklist -- a one-week experiment tracker -- a launch countdown -- a small calculator for one decision - -## Disposable by default - -Philo lets you generate a widget inline from a note. -If it is useful once, great. -If not, delete it and move on. - -No setup tax. -No guilt about abandoned tools. - -## Keep the winners - -Some generated widgets become recurring utilities. -Those can be saved into a small library and reused later. - -This gives you both speed and selectivity: - -- fast creation for exploration -- deliberate saving for durable value - -## Product principle - -Make creation cheap. -Make deletion safe. -Only preserve what earns its place. diff --git a/apps/landing/src/content/blog/why-we-built-a-journal-that-can-execute-ideas.mdx b/apps/landing/src/content/blog/why-we-built-a-journal-that-can-execute-ideas.mdx deleted file mode 100644 index 68dfc6a5..00000000 --- a/apps/landing/src/content/blog/why-we-built-a-journal-that-can-execute-ideas.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Why we built a journal that can execute ideas -summary: Notes are cheap to write but expensive to turn into action. We wanted the gap to disappear. -publishedAt: 2026-02-24 -updatedAt: 2026-02-24 -pageType: blog -canonicalPath: /blog/why-we-built-a-journal-that-can-execute-ideas -primaryQuery: journal that can execute ideas -evidenceIds: [] -status: published -ownership: manual -bestFor: [] -notFor: [] -faqs: [] -relatedLinks: - - label: A calmer daily planning loop - href: /blog/a-calmer-daily-planning-loop -image: /philo-hero-screenshot.svg ---- - -Most journaling apps are good at capture and weak at execution. - -You write an idea, close the note, and then rebuild the same context later in another tool. -That handoff cost is where momentum dies. - -Philo was designed to collapse that gap. - -## The core bet - -A daily note should not only remember what you thought. -It should help you run what you thought. - -That means three things: - -- tasks should carry forward until finished -- recurring work should reappear automatically -- widgets should be generated inline when a note needs one - -## Why this matters - -People do not think in tickets all day. -They think in fragments, checklists, and half-built plans. - -The journal is the natural place where that raw planning happens. -If execution starts there too, the system feels lighter. - -## What we are optimizing for - -We are not trying to build another giant workspace. -We are trying to keep your planning loop short: - -1. write -2. decide -3. run - -That is the product direction for everything in Philo. diff --git a/apps/landing/src/content/comparisons/.gitkeep b/apps/landing/src/content/comparisons/.gitkeep deleted file mode 100644 index 8b137891..00000000 --- a/apps/landing/src/content/comparisons/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/landing/src/content/comparisons/philo-vs-heavy-project-management-tools.mdx b/apps/landing/src/content/comparisons/philo-vs-heavy-project-management-tools.mdx deleted file mode 100644 index 7341035b..00000000 --- a/apps/landing/src/content/comparisons/philo-vs-heavy-project-management-tools.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "Philo vs heavy project management tools" -summary: "Why Philo fits lightweight personal execution loops better than heavyweight structured systems." -publishedAt: 2026-03-25 -updatedAt: 2026-03-25 -pageType: comparison -canonicalPath: /comparisons/philo-vs-heavy-project-management-tools -primaryQuery: "philo vs heavy project management tools" -evidenceIds: - - "5c003e16fdef" - - "4337412202be" - - "c30c4e88e712" - - "aeb2e6ea1588" - - "fa84266dd63a" - - "48c3fe78614e" -status: draft -ownership: generated -bestFor: - - "People who do not want a giant workspace just to run daily work" - - "Users who want a local markdown-centered execution loop" -notFor: - - "Teams needing strict project process and enterprise workflow control" - - "Organizations choosing a shared system of record" -faqs: - - question: "Is Philo meant to be a big workspace replacement?" - answer: "No. The product direction is explicitly about keeping the planning loop short, not building another giant workspace." - - question: "When do heavyweight tools still win?" - answer: "They win when the problem is a shared project system, not a personal note-driven execution loop." -relatedLinks: - - label: "Write, decide, and run in one place" - href: "/use-cases/write-decide-and-run-in-one-place" - - label: "Disposable widgets in notes" - href: "/guides/disposable-widgets-in-notes" -image: /philo-hero-screenshot.svg ---- -Daily notes do not inline the full widget payload. - -## Quick take - -Choose Philo when the center of gravity is the note itself. Choose heavy project management tools when the center of gravity is somewhere else. - -## Comparison table - -| Decide this way if... | Philo | Heavy project management tools | -| --- | --- | --- | -| You want a calm personal planning loop | Strong fit because the note itself stays central. | Can feel heavy if you only need personal daily execution. | -| You want structured shared workflows and fields everywhere | Less ideal. That is not the core bet. | Often the better fit. | -| You want one-off tools created inline | Fits the disposable widget model well. | Usually requires more setup and permanence. | - -## What Philo is actually optimizing for - -The scope refresh covers the current journal root, vault root, assets directory, Excalidraw directory, and widgets directory. - -widget files: widgets/ under the vault root, or under the resolved journal root in default mode - -## Evidence trail - -- `5c003e16fdef` Daily notes do not inline the full widget payload. (docs/data-storage-and-configuration.md) -- `4337412202be` The scope refresh covers the current journal root, vault root, assets directory, Excalidraw directory, and widgets directory. (docs/data-storage-and-configuration.md) -- `c30c4e88e712` widget files: widgets/ under the vault root, or under the resolved journal root in default mode (docs/data-storage-and-configuration.md) -- `aeb2e6ea1588` widget library: library/ under the vault root or resolved journal root (docs/data-storage-and-configuration.md) -- `fa84266dd63a` Recent work keeps widgets, recurrence, and execution closer to the daily note. (apps/landing/content-engine/inputs/releases.json#0.0.10) -- `48c3fe78614e` Philo stores daily notes as markdown files on disk, but edits them in memory as TipTap JSON. (docs/markdown-sync.md) diff --git a/apps/landing/src/content/config.ts b/apps/landing/src/content/config.ts deleted file mode 100644 index b8f02da0..00000000 --- a/apps/landing/src/content/config.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { defineCollection, z, } from "astro:content"; - -const contentSchema = z.object({ - title: z.string(), - summary: z.string(), - publishedAt: z.coerce.date(), - updatedAt: z.coerce.date(), - pageType: z.enum(["blog", "guide", "use-case", "comparison", "glossary",],), - canonicalPath: z.string().startsWith("/",), - primaryQuery: z.string(), - evidenceIds: z.array(z.string(),).default([],), - status: z.enum(["draft", "published",],).default("published",), - ownership: z.enum(["generated", "manual",],).default("manual",), - bestFor: z.array(z.string(),).default([],), - notFor: z.array(z.string(),).default([],), - faqs: z.array(z.object({ - question: z.string(), - answer: z.string(), - },),).default([],), - relatedLinks: z.array(z.object({ - label: z.string(), - href: z.string().startsWith("/",), - },),).default([],), - image: z.string().startsWith("/",).optional(), -},); - -const blog = defineCollection({ schema: contentSchema, },); -const guides = defineCollection({ schema: contentSchema, },); -const useCases = defineCollection({ schema: contentSchema, },); -const comparisons = defineCollection({ schema: contentSchema, },); -const glossary = defineCollection({ schema: contentSchema, },); - -export const collections = { - blog, - guides, - "use-cases": useCases, - comparisons, - glossary, -}; diff --git a/apps/landing/src/content/glossary/.gitkeep b/apps/landing/src/content/glossary/.gitkeep deleted file mode 100644 index 8b137891..00000000 --- a/apps/landing/src/content/glossary/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/landing/src/content/glossary/widget-library.mdx b/apps/landing/src/content/glossary/widget-library.mdx deleted file mode 100644 index 450a60e9..00000000 --- a/apps/landing/src/content/glossary/widget-library.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Widget library" -summary: "The small reusable collection where Philo keeps widgets that earned a permanent place." -publishedAt: 2026-03-25 -updatedAt: 2026-03-25 -pageType: glossary -canonicalPath: /glossary/widget-library -primaryQuery: "widget library definition" -evidenceIds: - - "1a7a539136c1" - - "060a53771959" - - "c477841a53e2" - - "e9209907266b" - - "d6c0f3b947a9" - - "9634b851c23e" -status: draft -ownership: generated -bestFor: - - "People who want a fast definition of the reusable widget layer" -notFor: - - "People who need a comparison or setup guide" -faqs: - - question: "Why keep the library small?" - answer: "Because Philo treats permanence as something a widget earns after proving useful." -relatedLinks: - - label: "Quick tools inside notes" - href: "/use-cases/quick-tools-inside-notes" -image: /philo-hero-screenshot.svg ---- -changing vaultDir does not migrate existing widget files, library items, or chat-history files into the new root - -## In Philo - -Notes, images, Excalidraw files, widget files, widget-library files, and chat-history files live under the resolved content directory. - -## Why the term matters - -the library drawer is built from saved widget files first, with shared component metadata layered on top - -## Evidence trail - -- `1a7a539136c1` changing vaultDir does not migrate existing widget files, library items, or chat-history files into the new root (docs/data-storage-and-configuration.md) -- `060a53771959` Notes, images, Excalidraw files, widget files, widget-library files, and chat-history files live under the resolved content directory. (docs/data-storage-and-configuration.md) -- `c477841a53e2` the library drawer is built from saved widget files first, with shared component metadata layered on top (docs/data-storage-and-configuration.md) -- `e9209907266b` The widget library is a merged view of archived widget files plus shared component manifests under the resolved library directory. (docs/data-storage-and-configuration.md) -- `d6c0f3b947a9` They are separate from widget files and separate from the widget library. (docs/data-storage-and-configuration.md) -- `9634b851c23e` widget library lives under /library/ (docs/data-storage-and-configuration.md) diff --git a/apps/landing/src/content/guides/.gitkeep b/apps/landing/src/content/guides/.gitkeep deleted file mode 100644 index 8b137891..00000000 --- a/apps/landing/src/content/guides/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/landing/src/content/guides/using-philo-with-an-obsidian-vault.mdx b/apps/landing/src/content/guides/using-philo-with-an-obsidian-vault.mdx deleted file mode 100644 index 4232f9de..00000000 --- a/apps/landing/src/content/guides/using-philo-with-an-obsidian-vault.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "Using Philo with an Obsidian vault" -summary: "How Philo works beside an existing vault instead of forcing a content migration." -publishedAt: 2026-03-25 -updatedAt: 2026-03-25 -pageType: guide -canonicalPath: /guides/using-philo-with-an-obsidian-vault -primaryQuery: "using philo with an obsidian vault" -evidenceIds: - - "a2c1db37e865" - - "6fd3b8f3b927" - - "0a6aa4c0458d" - - "4337412202be" - - "c30c4e88e712" - - "aeb2e6ea1588" -status: draft -ownership: generated -bestFor: - - "Obsidian users who want execution-oriented daily planning without moving files" - - "People who already have a vault and want Philo to augment it" -notFor: - - "People who want Philo to become their only note app immediately" - - "Workflows that do not rely on markdown vaults" -faqs: - - question: "Can Philo work with an existing vault?" - answer: "Yes. Philo stores notes as markdown on disk and is meant to sit beside an existing Obsidian vault rather than replace it." - - question: "Why would an Obsidian user add Philo?" - answer: "Philo focuses on the gap between capture and execution, especially around task rollover, recurrence, and inline widgets." -relatedLinks: - - label: "Markdown notes on disk" - href: "/guides/markdown-notes-on-disk" - - label: "Use Philo beside an Obsidian vault" - href: "/use-cases/use-philo-beside-an-obsidian-vault" -image: /philo-hero-screenshot.svg ---- -Philo is a fit for Obsidian users exploring a better daily planning loop because it keeps the note, the plan, and the supporting workflow closer together. - -## Direct answer - -When Philo is pointed at a vault, serialization uses tab indentation (\{ style: "tab", size: 1 \}) so the file on disk matches Obsidian's layout more closely. - -Philo still stores notes as markdown on disk and can work beside an existing vault. - -## What this looks like in Philo - -- When Philo is pointed at a vault, serialization uses tab indentation (\{ style: "tab", size: 1 \}) so the file on disk matches Obsidian's layout more closely. -- Philo still stores notes as markdown on disk and can work beside an existing vault. -- Mention links and Excalidraw embeds intentionally use Obsidian-friendly syntax so the markdown stays portable. -- The scope refresh covers the current journal root, vault root, assets directory, Excalidraw directory, and widgets directory. - -## Why it matters - -Mention links and Excalidraw embeds intentionally use Obsidian-friendly syntax so the markdown stays portable. - -The scope refresh covers the current journal root, vault root, assets directory, Excalidraw directory, and widgets directory. - -## Evidence trail - -- `a2c1db37e865` When Philo is pointed at a vault, serialization uses tab indentation (\{ style: "tab", size: 1 \}) so the file on disk matches Obsidian's layout more closely. (docs/markdown-sync.md) -- `6fd3b8f3b927` Philo still stores notes as markdown on disk and can work beside an existing vault. (apps/landing/content-engine/inputs/releases.json#0.0.10) -- `0a6aa4c0458d` Mention links and Excalidraw embeds intentionally use Obsidian-friendly syntax so the markdown stays portable. (docs/markdown-sync.md) -- `4337412202be` The scope refresh covers the current journal root, vault root, assets directory, Excalidraw directory, and widgets directory. (docs/data-storage-and-configuration.md) -- `c30c4e88e712` widget files: widgets/ under the vault root, or under the resolved journal root in default mode (docs/data-storage-and-configuration.md) -- `aeb2e6ea1588` widget library: library/ under the vault root or resolved journal root (docs/data-storage-and-configuration.md) diff --git a/apps/landing/src/content/use-cases/.gitkeep b/apps/landing/src/content/use-cases/.gitkeep deleted file mode 100644 index 8b137891..00000000 --- a/apps/landing/src/content/use-cases/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/landing/src/content/use-cases/use-philo-beside-an-obsidian-vault.mdx b/apps/landing/src/content/use-cases/use-philo-beside-an-obsidian-vault.mdx deleted file mode 100644 index 6b0adcdf..00000000 --- a/apps/landing/src/content/use-cases/use-philo-beside-an-obsidian-vault.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "Use Philo beside an Obsidian vault" -summary: "When an existing vault is still the source of truth, but you want a tighter planning loop." -publishedAt: 2026-03-25 -updatedAt: 2026-03-25 -pageType: use-case -canonicalPath: /use-cases/use-philo-beside-an-obsidian-vault -primaryQuery: "use philo beside an obsidian vault" -evidenceIds: - - "6fd3b8f3b927" - - "a2c1db37e865" - - "0a6aa4c0458d" - - "4337412202be" - - "c30c4e88e712" - - "aeb2e6ea1588" -status: draft -ownership: generated -bestFor: - - "People who already store notes in an Obsidian vault" - - "Users who want execution features without abandoning markdown ownership" -notFor: - - "People looking for a cloud migration path" - - "Workflows that are not built around a vault" -faqs: - - question: "Does Philo force an Obsidian user to migrate?" - answer: "No. Philo is meant to sit beside your vault, not replace it." - - question: "What does Philo add on top?" - answer: "It focuses on keeping planning, unfinished work, recurrence, and lightweight tools closer to the note itself." -relatedLinks: - - label: "Using Philo with an Obsidian vault" - href: "/guides/using-philo-with-an-obsidian-vault" - - label: "Philo vs static markdown daily notes" - href: "/comparisons/philo-vs-static-markdown-daily-notes" -image: /philo-hero-screenshot.svg ---- -Philo still stores notes as markdown on disk and can work beside an existing vault. - -## Where this workflow fits - -Philo is designed for people already invested in Obsidian. The product direction is about keeping the loop between writing, deciding, and running as short as possible. - -## Capability checklist - -- Philo still stores notes as markdown on disk and can work beside an existing vault. -- When Philo is pointed at a vault, serialization uses tab indentation (\{ style: "tab", size: 1 \}) so the file on disk matches Obsidian's layout more closely. -- Mention links and Excalidraw embeds intentionally use Obsidian-friendly syntax so the markdown stays portable. -- The scope refresh covers the current journal root, vault root, assets directory, Excalidraw directory, and widgets directory. -- widget files: widgets/ under the vault root, or under the resolved journal root in default mode - -## Why this workflow feels lighter - -When Philo is pointed at a vault, serialization uses tab indentation (\{ style: "tab", size: 1 \}) so the file on disk matches Obsidian's layout more closely. - -Mention links and Excalidraw embeds intentionally use Obsidian-friendly syntax so the markdown stays portable. - -## Evidence trail - -- `6fd3b8f3b927` Philo still stores notes as markdown on disk and can work beside an existing vault. (apps/landing/content-engine/inputs/releases.json#0.0.10) -- `a2c1db37e865` When Philo is pointed at a vault, serialization uses tab indentation (\{ style: "tab", size: 1 \}) so the file on disk matches Obsidian's layout more closely. (docs/markdown-sync.md) -- `0a6aa4c0458d` Mention links and Excalidraw embeds intentionally use Obsidian-friendly syntax so the markdown stays portable. (docs/markdown-sync.md) -- `4337412202be` The scope refresh covers the current journal root, vault root, assets directory, Excalidraw directory, and widgets directory. (docs/data-storage-and-configuration.md) -- `c30c4e88e712` widget files: widgets/ under the vault root, or under the resolved journal root in default mode (docs/data-storage-and-configuration.md) -- `aeb2e6ea1588` widget library: library/ under the vault root or resolved journal root (docs/data-storage-and-configuration.md) diff --git a/apps/landing/src/env.d.ts b/apps/landing/src/env.d.ts deleted file mode 100644 index 59ad26c5..00000000 --- a/apps/landing/src/env.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -/// -/// - -interface ImportMetaEnv { - readonly PUBLIC_GOOGLE_SITE_VERIFICATION?: string; - readonly PUBLIC_POSTHOG_HOST?: string; - readonly PUBLIC_POSTHOG_KEY?: string; -} diff --git a/apps/landing/src/layouts/CollectionLayout.astro b/apps/landing/src/layouts/CollectionLayout.astro deleted file mode 100644 index a4bf0cf6..00000000 --- a/apps/landing/src/layouts/CollectionLayout.astro +++ /dev/null @@ -1,115 +0,0 @@ ---- -import { siteConfig, } from "../lib/site"; -import SiteLayout from "./SiteLayout.astro"; - -interface Props { - title: string; - description: string; - path: string; - label: string; - schema?: Record | Array>; -} - -const { title, description, path, label, schema, } = Astro.props; ---- - - -
- - - - - -
-
- - diff --git a/apps/landing/src/layouts/ContentPageLayout.astro b/apps/landing/src/layouts/ContentPageLayout.astro deleted file mode 100644 index d63a7011..00000000 --- a/apps/landing/src/layouts/ContentPageLayout.astro +++ /dev/null @@ -1,372 +0,0 @@ ---- -import { formatContentDate, } from "../lib/content"; -import { siteConfig, } from "../lib/site"; -import SiteLayout from "./SiteLayout.astro"; - -interface Props { - title: string; - description: string; - path: string; - label: string; - summary: string; - publishedAt: Date; - updatedAt: Date; - schema?: Record | Array>; - bestFor?: string[]; - notFor?: string[]; - faqs?: Array<{ question: string; answer: string }>; - relatedLinks?: Array<{ label: string; href: string }>; - image?: string; - noindex?: boolean; -} - -const { - title, - description, - path, - label, - summary, - publishedAt, - updatedAt, - schema, - bestFor = [], - notFor = [], - faqs = [], - relatedLinks = [], - image, - noindex = false, -} = Astro.props; - -const publishedLabel = formatContentDate(publishedAt,); -const updatedLabel = formatContentDate(updatedAt,); -const metaLabel = publishedAt.getTime() === updatedAt.getTime() - ? `Published ${publishedLabel}` - : `Published ${publishedLabel} • Updated ${updatedLabel}`; ---- - - -
- - - { - image && ( -
- {`${title} -
- ) - } - -
- -
- - { - (bestFor.length > 0 || notFor.length > 0) && ( -
- { - bestFor.length > 0 && ( -
-

Best for

-
    - {bestFor.map((item,) =>
  • {item}
  • )} -
-
- ) - } - { - notFor.length > 0 && ( -
-

Not for

-
    - {notFor.map((item,) =>
  • {item}
  • )} -
-
- ) - } -
- ) - } - - { - faqs.length > 0 && ( -
-

FAQs

-
    - { - faqs.map((item,) => ( -
  • -

    {item.question}

    -

    {item.answer}

    -
  • - )) - } -
-
- ) - } - - { - relatedLinks.length > 0 && ( - - ) - } - - -
-
- - diff --git a/apps/landing/src/layouts/LegalLayout.astro b/apps/landing/src/layouts/LegalLayout.astro deleted file mode 100644 index 02e28738..00000000 --- a/apps/landing/src/layouts/LegalLayout.astro +++ /dev/null @@ -1,177 +0,0 @@ ---- -import { withSiteName, } from "../lib/site"; -import SiteLayout from "./SiteLayout.astro"; - -interface Props { - title: string; - description: string; - effectiveDate: string; -} - -const { title, description, effectiveDate, } = Astro.props; ---- - - -
- - -
- -
- - -
-
- - diff --git a/apps/landing/src/layouts/SiteLayout.astro b/apps/landing/src/layouts/SiteLayout.astro deleted file mode 100644 index 87e048e6..00000000 --- a/apps/landing/src/layouts/SiteLayout.astro +++ /dev/null @@ -1,194 +0,0 @@ ---- -import { absoluteUrl, siteConfig, } from "../lib/site"; - -interface Props { - title: string; - description: string; - path: string; - image?: string; - noindex?: boolean; - publishedAt?: Date; - updatedAt?: Date; - schema?: Record | Array>; -} - -const { - title, - description, - path, - image = siteConfig.defaultImagePath, - noindex = false, - publishedAt, - updatedAt, - schema = [], -} = Astro.props; - -const canonicalUrl = absoluteUrl(path); -const socialImageUrl = absoluteUrl(image); -const jsonLd = Array.isArray(schema,) ? schema : [schema,]; ---- - - - - - - {title} - - - - - - - - - - - - - - - { - publishedAt && - } - { - updatedAt && - } - { - import.meta.env.PUBLIC_GOOGLE_SITE_VERIFICATION && ( - - ) - } - - - - { - jsonLd.map((entry,) => ( - - - -
-
-

- Philo is being integrated into Char as a feature. -

-
- - - - - diff --git a/apps/landing/src/lib/content.ts b/apps/landing/src/lib/content.ts deleted file mode 100644 index 35580dfd..00000000 --- a/apps/landing/src/lib/content.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { absoluteUrl, siteConfig, } from "./site"; - -export type ContentPageType = "blog" | "guide" | "use-case" | "comparison" | "glossary"; -export type ContentStatus = "draft" | "published"; -export type ContentOwnership = "generated" | "manual"; - -export interface ContentFrontmatter { - title: string; - summary: string; - publishedAt: Date; - updatedAt: Date; - pageType: ContentPageType; - canonicalPath: string; - primaryQuery: string; - evidenceIds: string[]; - status: ContentStatus; - ownership: ContentOwnership; - bestFor: string[]; - notFor: string[]; - faqs: Array<{ question: string; answer: string; }>; - relatedLinks: Array<{ label: string; href: string; }>; - image?: string; -} - -export interface ContentEntryLike { - slug: string; - body?: string; - data: ContentFrontmatter; -} - -export const contentSections = { - blog: { - collection: "blog", - label: "Blog", - title: "Notes from the team", - description: "Product notes from the Philo team on daily planning, recurring systems, and disposable widgets.", - pageType: "blog", - }, - guides: { - collection: "guides", - label: "Guides", - title: "Philo guides", - description: "How to use Philo's daily planning model, markdown storage, recurring tasks, and widget workflow.", - pageType: "guide", - }, - "use-cases": { - collection: "use-cases", - label: "Use cases", - title: "Use Philo for real planning loops", - description: - "Practical ways to use Philo for daily planning, recurring work, markdown-native notes, and lightweight systems.", - pageType: "use-case", - }, - comparisons: { - collection: "comparisons", - label: "Comparisons", - title: "Compare Philo to adjacent workflows", - description: "Tradeoff-driven comparisons for people deciding whether Philo fits their planning workflow.", - pageType: "comparison", - }, - glossary: { - collection: "glossary", - label: "Glossary", - title: "Philo glossary", - description: "Clear definitions for the planning primitives that power Philo.", - pageType: "glossary", - }, -} as const; - -export type ContentSection = keyof typeof contentSections; - -export function isContentSection(value: string,): value is ContentSection { - return value in contentSections; -} - -export function sortContentEntries(entries: T[],): T[] { - return [...entries,].sort((left, right,) => ( - right.data.updatedAt.getTime() - left.data.updatedAt.getTime() - || right.data.publishedAt.getTime() - left.data.publishedAt.getTime() - )); -} - -export function isPublishedEntry(entry: ContentEntryLike,): boolean { - return entry.data.status === "published"; -} - -export function formatContentDate(date: Date,): string { - return date.toLocaleDateString("en-US", { - year: "numeric", - month: "short", - day: "numeric", - },); -} - -export function buildCollectionSchema(section: ContentSection,) { - const config = contentSections[section]; - return { - "@context": "https://schema.org", - "@type": "CollectionPage", - name: config.title, - description: config.description, - url: absoluteUrl(`/${section}`,), - isPartOf: { - "@type": "WebSite", - name: siteConfig.name, - url: siteConfig.siteUrl, - }, - }; -} - -export function buildContentSchemas(entry: ContentEntryLike,) { - const imageUrl = absoluteUrl(entry.data.image ?? siteConfig.defaultImagePath,); - const baseArticle = { - "@context": "https://schema.org", - "@type": ( - entry.data.pageType === "blog" - ? "BlogPosting" - : entry.data.pageType === "glossary" - ? "DefinedTerm" - : "TechArticle" - ), - headline: entry.data.title, - description: entry.data.summary, - image: imageUrl, - url: absoluteUrl(entry.data.canonicalPath,), - datePublished: entry.data.publishedAt.toISOString(), - dateModified: entry.data.updatedAt.toISOString(), - author: { - "@type": "Organization", - name: siteConfig.name, - }, - publisher: { - "@type": "Organization", - name: siteConfig.name, - url: siteConfig.siteUrl, - }, - mainEntityOfPage: absoluteUrl(entry.data.canonicalPath,), - }; - - if (entry.data.pageType === "glossary") { - return [ - { - ...baseArticle, - name: entry.data.title, - termCode: entry.slug, - inDefinedTermSet: absoluteUrl("/glossary",), - }, - ...buildFaqSchemas(entry,), - ]; - } - - return [baseArticle, ...buildFaqSchemas(entry,),]; -} - -function buildFaqSchemas(entry: ContentEntryLike,) { - if (entry.data.faqs.length === 0) { - return []; - } - - return [{ - "@context": "https://schema.org", - "@type": "FAQPage", - mainEntity: entry.data.faqs.map((item,) => ({ - "@type": "Question", - name: item.question, - acceptedAnswer: { - "@type": "Answer", - text: item.answer, - }, - })), - url: absoluteUrl(entry.data.canonicalPath,), - },]; -} diff --git a/apps/landing/src/lib/site.ts b/apps/landing/src/lib/site.ts deleted file mode 100644 index d7b2a216..00000000 --- a/apps/landing/src/lib/site.ts +++ /dev/null @@ -1,47 +0,0 @@ -export const siteConfig = { - name: "Philo", - siteUrl: "https://philo.so", - defaultTitle: "Philo: Experimental daily notes for personal context", - defaultDescription: - "Philo is an experimental proof of concept focused on daily notes and shaping native personal context inside fastrepl/char.", - defaultImagePath: "/philo-hero-screenshot.svg", - email: "john@hyprnote.com", - repoUrl: "https://github.com/ComputelessComputer/philo", -} as const; - -export function absoluteUrl(path: string,): string { - return new URL(path, siteConfig.siteUrl,).toString(); -} - -export function withSiteName(title: string,): string { - return title.includes(siteConfig.name,) ? title : `${title} | ${siteConfig.name}`; -} - -export function buildHomeSchemas() { - return [ - { - "@context": "https://schema.org", - "@type": "WebSite", - name: siteConfig.name, - url: siteConfig.siteUrl, - description: siteConfig.defaultDescription, - }, - { - "@context": "https://schema.org", - "@type": "SoftwareApplication", - name: siteConfig.name, - description: siteConfig.defaultDescription, - url: siteConfig.siteUrl, - applicationCategory: "ProductivityApplication", - operatingSystem: "macOS, Windows, Linux", - image: absoluteUrl(siteConfig.defaultImagePath,), - softwareHelp: absoluteUrl("/guides",), - sameAs: [siteConfig.repoUrl,], - offers: { - "@type": "Offer", - price: "0", - priceCurrency: "USD", - }, - }, - ]; -} diff --git a/apps/landing/src/pages/[section]/[slug].astro b/apps/landing/src/pages/[section]/[slug].astro deleted file mode 100644 index edb12ed9..00000000 --- a/apps/landing/src/pages/[section]/[slug].astro +++ /dev/null @@ -1,52 +0,0 @@ ---- -import { getCollection, render, } from "astro:content"; -import ContentPageLayout from "../../layouts/ContentPageLayout.astro"; -import { - buildContentSchemas, - contentSections, - type ContentEntryLike, - type ContentSection, -} from "../../lib/content"; -import { withSiteName, } from "../../lib/site"; - -export async function getStaticPaths() { - const paths = await Promise.all( - Object.entries(contentSections,).map(async ([section, config,],) => { - const entries = await getCollection(config.collection,); - return entries - .filter((entry,) => entry.data.status === "published",) - .map((entry,) => ({ - params: { section, slug: entry.slug, }, - props: { entry, section, }, - })); - }), - ); - - return paths.flat(); -} - -const { entry, section, } = Astro.props as { - entry: ContentEntryLike; - section: ContentSection; -}; -const { Content, } = await render(entry as never,); -const config = contentSections[section]; ---- - - - - diff --git a/apps/landing/src/pages/[section]/index.astro b/apps/landing/src/pages/[section]/index.astro deleted file mode 100644 index f7e139d6..00000000 --- a/apps/landing/src/pages/[section]/index.astro +++ /dev/null @@ -1,122 +0,0 @@ ---- -import { getCollection, } from "astro:content"; -import CollectionLayout from "../../layouts/CollectionLayout.astro"; -import { - buildCollectionSchema, - contentSections, - formatContentDate, - isPublishedEntry, - type ContentSection, - sortContentEntries, -} from "../../lib/content"; -import { withSiteName, } from "../../lib/site"; - -export function getStaticPaths() { - return Object.keys(contentSections,).map((section,) => ({ - params: { section, }, - props: { section, }, - })); -} - -const { section, } = Astro.props as { section: ContentSection }; -const config = contentSections[section]; -const entries = sortContentEntries( - (await getCollection(config.collection,)) - .filter(isPublishedEntry,), -); ---- - - -
- { - entries.length === 0 ? ( -

No published entries yet. The content engine will land new pages here after review.

- ) : ( - - ) - } -
-
- - diff --git a/apps/landing/src/pages/index.astro b/apps/landing/src/pages/index.astro deleted file mode 100644 index 2833fccc..00000000 --- a/apps/landing/src/pages/index.astro +++ /dev/null @@ -1,1333 +0,0 @@ ---- -import { getCollection, } from "astro:content"; -import SiteLayout from "../layouts/SiteLayout.astro"; -import { contentSections, isPublishedEntry, sortContentEntries, } from "../lib/content"; -import { buildHomeSchemas, siteConfig, withSiteName, } from "../lib/site"; - -const capabilities = [ - { - title: "Focused just on daily notes", - description: "Philo stays intentionally narrow: today, nearby days, and the work attached to them instead of a sprawling knowledge base.", - visual: "timeline", - }, - { - title: "Open work rolls forward", - description: "If a task is still open when the date changes, Philo carries it into today automatically so the thread of work stays intact.", - visual: "rollover", - }, - { - title: "Recurring routines stay lightweight", - description: "Daily and scheduled tasks can return automatically, so you do not have to rebuild the same note structure every morning.", - visual: "recurring", - }, - { - title: "Markdown stays the source", - description: "Keep your daily notes as plain markdown on disk and keep using tools like Obsidian or Logseq if that still fits your setup.", - visual: "markdown", - }, - { - title: "A stepping stone into char.com", - description: "Philo is an open experiment, not the final destination. The plan is to bring this daily-notes context model into char.com.", - visual: "open-source", - }, -]; - -const posts = sortContentEntries((await getCollection("blog",)).filter(isPublishedEntry,)); -const sectionCards = Object.entries(contentSections,) - .filter(([section,],) => section !== "blog",) - .map(([section, config,],) => ({ - href: `/${section}`, - title: config.label, - description: config.description, - })); - -const heroMetaTitle = withSiteName(siteConfig.defaultTitle,); -const heroMetaDescription = siteConfig.defaultDescription; ---- - - -
-
-
-
-

Philo is an experimental daily notes app [poc]

-

{heroMetaDescription}

-

- It exists to test a tighter daily-notes workflow in the open before these ideas are integrated into char.com to augment personal context. -

- -
-
-
- -
-
-
- -
-

What this experiment is testing

-
    - { - capabilities.map((item,) => ( -
  • -
    -

    {item.title}

    -

    {item.description}

    -
    - -
  • - )) - } -
-
- -
-

Notes from the team

- -
- -
-

Explore the content system

- -
- -
-

Eventually this should disappear into fastrepl/char

-

- Philo is a public proof of concept, not a forever-standalone notes app. Your notes stay - as markdown files on disk, and the long-term direction is native fastrepl/char - integration that carries forward your day-to-day context without adding another silo. -

-
- - -
- - -
-
- - - - diff --git a/apps/landing/src/pages/privacy.astro b/apps/landing/src/pages/privacy.astro deleted file mode 100644 index f292a99b..00000000 --- a/apps/landing/src/pages/privacy.astro +++ /dev/null @@ -1,137 +0,0 @@ ---- -import LegalLayout from "../layouts/LegalLayout.astro"; - -const effectiveDate = "March 15, 2026"; ---- - - -

- Philo is built to keep your notes local by default. This policy explains what information may - be processed when you use the landing site at philo.so, download the - app, contact us, or use optional integrations inside the app. -

- -

What this policy covers

-

- This policy covers the Philo website, the downloadable Philo desktop app, and direct support - communications about Philo. It does not cover third-party services you connect on your own, - except to describe when Philo sends data to them at your direction. -

- -

Information we receive

-

Depending on how you use Philo, we may receive:

-
    -
  • contact details and message contents if you email us;
  • -
  • basic request and device data generated by normal website hosting and security logs;
  • -
  • download activity routed through GitHub release assets;
  • -
  • information sent to third-party AI or Google services only when you configure and use them inside the app.
  • -
- -

How the website works

-

- The landing site is a mostly static Astro site. It does not include its own account system or - in-site note storage. The homepage makes a client-side request to GitHub to resolve the latest - release download links, and the site loads Google Fonts. Those third parties may receive your - IP address, browser details, and related request metadata as part of serving those resources. -

- -

How the desktop app works

-

- Philo is local-first. Notes, images, widget files, and related content are stored on your - device or in an Obsidian vault you choose. Philo does not operate a first-party cloud sync - service for your notes through this site. -

-

- Some app settings are also stored locally on your device. That can include configured paths, - onboarding state, selected providers, API keys you enter, and Google OAuth tokens if you - connect Google features. Those values are stored locally so the app can function. -

- -

Optional third-party services

-

- If you enable AI or Google features, Philo sends the relevant request data to the provider you - selected so the feature can run. That may include prompts, note excerpts, tool inputs, or - authentication data needed for the request. Providers currently supported in the app include - Anthropic, OpenAI, Google, and OpenRouter. -

-

- Your use of those services is also governed by their own terms and privacy policies. Philo - does not control how those providers retain or use data once a request reaches them. -

- -

Google account connections

-

- If you connect a Google account, Philo may request permission to access your basic account - profile, your Google Calendar data, and your Gmail data. The current planned Google Workspace - access is read-only for Calendar and Gmail. -

-

- Philo uses that access only to provide the Google-powered features you choose to use inside the - app, such as reading calendar or email information into your planning workflow. Google OAuth - tokens and granted-scope records are stored locally on your device so the app can refresh access - and reconnect to Google services. -

-

- Philo does not sell Google Workspace data and does not use it for advertising. The use of - information received from Google Workspace APIs will adhere to the Google API Services User Data - Policy, including the Limited Use requirements. -

-

- You can disconnect Google in the app settings or revoke Philo's access from your Google - account permissions page. If Google access is removed, related features in Philo may stop - working until you reconnect. -

- -

How we use information

-

We use information to:

-
    -
  • serve the website and downloads;
  • -
  • respond to support or product inquiries;
  • -
  • maintain security, availability, and abuse prevention;
  • -
  • enable the optional integrations and provider requests you choose to use.
  • -
- -

Sharing

-

- We do not sell your information. We may share information with service providers involved in - hosting, email, fonts, source code hosting, releases, or the third-party integrations you - choose to use. We may also disclose information if reasonably necessary to comply with law, - protect rights, or address abuse or security issues. -

- -

Retention

-

- Website and communication records are kept only as long as reasonably needed for operations, - support, legal compliance, and security. Content stored by the desktop app remains under your - control on your device or chosen storage location unless you delete it. -

- -

Your choices

-
    -
  • Do not send us email if you do not want us to receive the contents of that message.
  • -
  • Do not configure optional AI or Google integrations if you do not want data sent to those providers.
  • -
  • Disconnect Google access in Philo or revoke it in your Google account if you no longer want Philo to read Gmail or Calendar data.
  • -
  • You can delete local app data and your notes from the storage locations you control.
  • -
- -

Children

-

- Philo is not directed to children under 13, and we do not knowingly collect personal - information from children under 13. -

- -

Changes

-

- We may update this policy from time to time. If we make a material change, we will update the - effective date on this page. -

- -

Contact

-

- Privacy questions can be sent to john@hyprnote.com. -

-
diff --git a/apps/landing/src/pages/robots.txt.ts b/apps/landing/src/pages/robots.txt.ts deleted file mode 100644 index be6cf088..00000000 --- a/apps/landing/src/pages/robots.txt.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { absoluteUrl, } from "../lib/site"; - -export function GET() { - return new Response( - [ - "User-agent: *", - "Allow: /", - "", - "User-agent: OAI-SearchBot", - "Allow: /", - "", - "User-agent: GPTBot", - "Disallow: /", - "", - `Sitemap: ${absoluteUrl("/sitemap.xml",)}`, - "", - ].join("\n",), - { - headers: { - "Content-Type": "text/plain; charset=utf-8", - }, - }, - ); -} diff --git a/apps/landing/src/pages/rss.xml.ts b/apps/landing/src/pages/rss.xml.ts deleted file mode 100644 index be549d8b..00000000 --- a/apps/landing/src/pages/rss.xml.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { getCollection, } from "astro:content"; -import { contentSections, isPublishedEntry, sortContentEntries, } from "../lib/content"; -import { absoluteUrl, siteConfig, } from "../lib/site"; - -export async function GET() { - const sectionEntries = await Promise.all( - Object.values(contentSections,).map(async (config,) => ( - (await getCollection(config.collection,)).filter(isPublishedEntry,) - )), - ); - const items = sortContentEntries(sectionEntries.flat(),).slice(0, 50,); - - const xml = [ - '', - '', - " ", - ` ${escapeXml(`${siteConfig.name} content feed`,)}`, - ` ${escapeXml(siteConfig.defaultDescription,)}`, - ` ${escapeXml(siteConfig.siteUrl,)}`, - ...items.map((entry,) => ( - [ - " ", - ` ${escapeXml(entry.data.title,)}`, - ` ${escapeXml(entry.data.summary,)}`, - ` ${escapeXml(absoluteUrl(entry.data.canonicalPath,),)}`, - ` ${escapeXml(absoluteUrl(entry.data.canonicalPath,),)}`, - ` ${(entry.data.updatedAt ?? entry.data.publishedAt).toUTCString()}`, - " ", - ].join("\n",) - )), - " ", - "", - "", - ].join("\n",); - - return new Response(xml, { - headers: { - "Content-Type": "application/rss+xml; charset=utf-8", - }, - },); -} - -function escapeXml(value: string,) { - return value - .replaceAll("&", "&",) - .replaceAll('"', """,) - .replaceAll("'", "'",) - .replaceAll("<", "<",) - .replaceAll(">", ">",); -} diff --git a/apps/landing/src/pages/sitemap.xml.ts b/apps/landing/src/pages/sitemap.xml.ts deleted file mode 100644 index abd5fc0e..00000000 --- a/apps/landing/src/pages/sitemap.xml.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { getCollection, } from "astro:content"; -import { contentSections, isPublishedEntry, } from "../lib/content"; -import { absoluteUrl, } from "../lib/site"; - -export async function GET() { - const sectionEntries = await Promise.all( - Object.entries(contentSections,).map(async ([section, config,],) => ({ - section, - entries: (await getCollection(config.collection,)).filter(isPublishedEntry,), - })), - ); - - const staticPages = [ - { url: "/", lastmod: null, }, - { url: "/privacy", lastmod: null, }, - { url: "/terms", lastmod: null, }, - ...sectionEntries.map(({ section, entries, },) => ({ - url: `/${section}`, - lastmod: entries[0]?.data.updatedAt ?? null, - })), - ]; - - const contentPages = sectionEntries.flatMap(({ entries, },) => ( - entries.map((entry,) => ({ - url: entry.data.canonicalPath, - lastmod: entry.data.updatedAt ?? entry.data.publishedAt, - })) - )); - - const xml = [ - '', - '', - ...[...staticPages, ...contentPages,].map((item,) => ( - [ - " ", - ` ${escapeXml(absoluteUrl(item.url,),)}`, - item.lastmod ? ` ${item.lastmod.toISOString()}` : null, - " ", - ].filter(Boolean,).join("\n",) - )), - "", - "", - ].join("\n",); - - return new Response(xml, { - headers: { - "Content-Type": "application/xml; charset=utf-8", - }, - },); -} - -function escapeXml(value: string,) { - return value - .replaceAll("&", "&",) - .replaceAll('"', """,) - .replaceAll("'", "'",) - .replaceAll("<", "<",) - .replaceAll(">", ">",); -} diff --git a/apps/landing/src/pages/terms.astro b/apps/landing/src/pages/terms.astro deleted file mode 100644 index 164d5755..00000000 --- a/apps/landing/src/pages/terms.astro +++ /dev/null @@ -1,121 +0,0 @@ ---- -import LegalLayout from "../layouts/LegalLayout.astro"; - -const effectiveDate = "March 15, 2026"; ---- - - -

- These Terms of Use govern your access to the Philo website at philo.so, - the downloadable Philo app releases, and related communications or materials made available by - Philo. -

- -

Acceptance

-

- By accessing or using the site or downloads, you agree to these terms. If you do not agree, do - not use them. -

- -

Eligibility and compliance

-

- You must use Philo in compliance with applicable law. You are responsible for making sure your - use of Philo, your content, and any third-party services you connect are permitted in your - jurisdiction and workplace. -

- -

License and open-source code

-

- The Philo source code is separately licensed under the repository license. These terms govern - the website, hosted materials, and distributed releases unless a different license or agreement - clearly applies to a particular asset. -

- -

Acceptable use

-

You may not:

-
    -
  • use the site or app to violate law or another party's rights;
  • -
  • interfere with the operation, security, or integrity of the site, releases, or related infrastructure;
  • -
  • attempt unauthorized access to systems, accounts, tokens, or data not intended for you;
  • -
  • use Philo to distribute malware, spam, or abusive automated traffic.
  • -
- -

Your content and integrations

-

- You keep responsibility for the notes, files, prompts, credentials, and other content you use - with Philo. If you connect third-party services such as AI providers or Google services, you - are responsible for those accounts, their permissions, and compliance with their terms. -

- -

Google Workspace features

-

- If you enable Google-connected features, you authorize Philo to use the Google permissions you - grant, including planned read-only Gmail and Google Calendar access, to provide those - user-facing features. You must only connect accounts you are authorized to use. -

-

- Google-connected features may be limited, suspended, or unavailable if your authorization is - revoked, your scopes change, Google policy requirements change, or Google rejects or restricts - access to the relevant APIs. -

- -

Downloads, updates, and beta status

-

- Philo may change, suspend, or remove features, downloads, or availability at any time. Some - releases may be experimental or beta quality. You are responsible for backing up your own data - and testing updates before relying on them in production or important workflows. -

- -

No warranty

-

- To the maximum extent allowed by law, the site, downloads, and related materials are provided - on an "as is" and "as available" basis, without warranties of any kind, whether express, - implied, or statutory. We do not warrant uninterrupted availability, accuracy, fitness for a - particular purpose, or that the software will be error-free. -

- -

Limitation of liability

-

- To the maximum extent allowed by law, Philo and its operators will not be liable for indirect, - incidental, special, consequential, exemplary, or punitive damages, or for any loss of data, - profits, goodwill, or business interruption arising from or related to your use of the site, - app, downloads, or third-party integrations. -

-

- If liability cannot be excluded, the total liability will be limited to the greater of the - amount you paid us for Philo in the 12 months before the claim or USD $100. -

- -

Third-party services and links

-

- Philo may link to or rely on third-party services, including GitHub, Google, and optional AI - providers. We are not responsible for third-party services, content, availability, or policies. -

- -

Termination

-

- We may suspend or terminate access to the site or related services if we reasonably believe you - are violating these terms, creating security risk, or exposing us or others to harm. -

- -

Changes

-

- We may revise these terms from time to time. Updated terms become effective when posted on this - page, unless a later date is stated. -

- -

Governing law

-

- These terms are governed by the laws of the Republic of Korea, excluding conflict-of-laws - rules, unless applicable law requires otherwise. -

- -

Contact

-

- Questions about these terms can be sent to john@hyprnote.com. -

-
diff --git a/apps/landing/tsconfig.json b/apps/landing/tsconfig.json deleted file mode 100644 index bcbf8b50..00000000 --- a/apps/landing/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "astro/tsconfigs/strict" -}