Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/assets/apps/documents/icon.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/apps/documents/screenshot-1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/apps/documents/screenshot-2.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/apps/documents/screenshot-3.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion scripts/audit-built-site.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,12 @@ if (JSON.stringify(appDirectories) !== JSON.stringify(releaseSlugs)) {
);
}
for (const [slug, release] of Object.entries(releaseMetadata.apps)) {
if (!release.sourceVersion || !release.sourceReleaseUrl) {
if (!release.sourceReleaseUrl) {
errors.push(`release metadata is incomplete for ${slug}`);
}
if (release.sourceKind !== "repository" && !release.sourceVersion) {
errors.push(`release metadata has no version for ${slug}`);
}
if (release.sourceKind === "release" && !release.publishedAt) {
errors.push(`release metadata has no publication date for ${slug}`);
}
Expand Down
14 changes: 6 additions & 8 deletions src/components/PolicyPage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ type Props = {
const { policy, canonicalPath } = Astro.props;
const relatedApp = apps.find((app) => app.links.policy === canonicalPath);
const isUnlisted = "unlisted" in policy && policy.unlisted;
const policyDetails: PolicyDetails = relatedApp
? {
privacy: relatedApp.privacy,
dataAccess: relatedApp.dataAccess,
permissionSummary: relatedApp.permissionSummary,
dataLeavingDevice: relatedApp.dataLeavingDevice,
}
: policy.details!;
const policyDetails: PolicyDetails = policy.details ?? {
privacy: relatedApp!.privacy,
dataAccess: relatedApp!.dataAccess,
permissionSummary: relatedApp!.permissionSummary,
dataLeavingDevice: relatedApp!.dataLeavingDevice,
};
---

<BaseLayout
Expand Down
54 changes: 54 additions & 0 deletions src/data/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,60 @@ export const apps: FossifyApp[] = [
policy: "/policy/filemanager.html",
},
},
{
slug: "documents",
repo: "Documents",
title: "Fossify Documents",
shortTitle: "Documents",
status: "Beta",
category: "Utilities",
packageName: "org.fossify.documents",
isFree: false,
tagline: "Offline document reading and organization.",
summary:
"Read and organize PDF, DOCX, text, Markdown, CSV, TSV, and HTML files.",
description:
"Read and organize documents, edit text and Markdown, and browse recent files, favorites, and selected folders.",
featureHeading: "Documents, folders, and offline reading",
features: [
"PDF, DOCX, text, Markdown, CSV, TSV, and HTML viewing",
"Text and Markdown editing, with plain-text editing for CSV and TSV",
"Recent documents, favorites, selected folders, search, filtering, and sorting",
"Password-protected PDFs, page navigation, zoom, and printing",
"Offline use without an account or Internet permission",
],
privacy:
"Documents works with files chosen through Android's file picker and keeps its library records locally.",
dataAccess: [
"Documents and folders selected through Android's file picker",
"Document names, locations, recent activity, favorites, and selected folder references",
"Appearance, sorting, and viewing preferences",
],
permissionSummary: [
"Read access to documents and folders selected through Android's file picker",
"Write access when a supported document is edited or a new document is created",
"Persisted access to selected folders so they remain available after the app restarts",
],
dataLeavingDevice:
"A document is passed to another app or system service only when you choose Share, Open with, or Print. The selected app, storage provider, or print service then handles it.",
icon: appAsset("documents", "icon.webp"),
screenshotSize: { width: 540, height: 1212 },
screenshots: [
appAsset("documents", "screenshot-1.webp"),
appAsset("documents", "screenshot-2.webp"),
appAsset("documents", "screenshot-3.webp"),
],
screenshotCaptions: [
"Document library",
"Selected folder",
"Markdown preview",
],
links: {
github: github("Documents"),
play: play("org.fossify.documents"),
policy: "/policy/documents.html",
},
},
{
slug: "messages",
repo: "Messages",
Expand Down
9 changes: 9 additions & 0 deletions src/data/release-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@
"sourceReleaseUrl": "https://github.com/FossifyOrg/Contacts/releases/tag/1.6.0",
"publishedAt": "2026-01-30T20:46:35Z"
},
"documents": {
"title": "Fossify Documents",
"repo": "Documents",
"sourceVersion": "1.0.0",
"sourceTag": "1.0.0",
"sourceKind": "release",
"sourceReleaseUrl": "https://github.com/FossifyOrg/Documents/releases/tag/1.0.0",
"publishedAt": "2026-07-31T21:36:37Z"
},
"file-manager": {
"title": "Fossify File Manager",
"repo": "File-Manager",
Expand Down
11 changes: 5 additions & 6 deletions src/data/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export const site = {
name: "Fossify",
title: "Fossify - open-source Android apps",
description:
"Open-source Android apps for gallery, calendar, files, messages, phone, notes, camera, music, and more.",
"Open-source Android apps for gallery, calendar, files, documents, messages, phone, notes, camera, music, and more.",
url: "https://www.fossify.org",
brandColor: "#216e39",
email: "hello@fossify.org",
Expand Down Expand Up @@ -91,18 +91,17 @@ export const policyRoutes: PolicyRoute[] = [
{
slug: "documents",
appName: "Fossify Documents",
updated: "July 12, 2026",
unlisted: true,
updated: "July 31, 2026",
details: {
privacy:
"The app works with documents chosen through Android's file picker and keeps its own history, favorites, folder list, and settings locally.",
dataAccess: [
"PDF, text, Markdown, and other supported documents opened through Android or chosen with the system file picker.",
"PDF, DOCX, text, Markdown, CSV, TSV, and HTML documents opened through Android or chosen with the system file picker.",
"Document names, locations, recent activity, favorites, and selected folders used to organize those documents.",
"App preferences such as appearance, sorting, and viewing options.",
],
permissionsIntro:
"The app does not request broad access to device storage. Android gives it access only to documents and folders selected through the system file picker:",
"The app does not request broad access to device storage. File access is limited to documents and folders selected through the system file picker:",
permissionSummary: [
"Read access to documents and folders selected through Android's file picker.",
"Write access when a supported document is edited or a new document is created.",
Expand All @@ -116,7 +115,7 @@ export const policyRoutes: PolicyRoute[] = [
"Android's file picker, storage providers, backup and device-transfer services, print services, and apps selected through Share or Open with operate under their own terms and privacy policies.",
storageAndDeletion: [
"Recent activity, favorites, selected folder references, and app settings remain in app storage until they are changed, cleared through the app or Android settings, or removed by uninstalling the app.",
"Clearing the app's records does not delete the original documents. Documents remain with their storage provider unless the user edits or deletes them.",
"Clearing the app's records does not delete the original documents. The files remain with their storage provider and can still be edited or deleted through that provider or another app.",
"Android backup or device transfer may include app settings and local app records according to the device's backup settings.",
],
},
Expand Down
2 changes: 1 addition & 1 deletion src/pages/404.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import BaseLayout from "../layouts/BaseLayout.astro";
const recoveryRoutes = [
{
title: "Apps",
body: "Browse Fossify tools for gallery, calendar, files, messages, phone, music, notes, and more.",
body: "Browse Fossify tools for gallery, calendar, files, documents, messages, phone, music, notes, and more.",
href: "/apps/",
action: "Browse apps",
},
Expand Down
4 changes: 2 additions & 2 deletions src/pages/about.astro
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { site } from "../data/site";
<h1 class="page-title">The Fossify project</h1>
<p class="lead">
Fossify develops open-source Android apps for common phone tasks,
including photos, calendars, files, messages, calls, music, notes,
camera, keyboard, and utilities.
including photos, calendars, files, documents, messages, calls, music,
notes, camera, keyboard, and utilities.
</p>
<div class="actions">
<a class="button primary" href="/apps/">Browse apps</a>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/apps/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { appCategories, apps } from "../../data/apps";
const categoryCopy: Record<string, string> = {
Media: "Photos, video, recording, and local music playback.",
Everyday: "Calendar, notes, typing, time, and home-screen tools.",
Utilities: "File management, calculations, and drawing.",
Utilities: "File and document management, calculations, and drawing.",
Communication:
"Phone, messages, and contacts for basic communication on the device.",
Funding: "Project funding, customization, and shared app settings.",
Expand Down Expand Up @@ -36,8 +36,8 @@ const grouped = appCategories.map((category) => ({
<p class="eyebrow">Apps</p>
<h1 class="page-title">Fossify apps</h1>
<p class="lead">
Android tools for photos, calendars, files, messages, calls, music,
notes, camera, keyboard, and other everyday tasks.
Android tools for photos, calendars, files, documents, messages,
calls, music, notes, camera, keyboard, and other everyday tasks.
</p>
<div class="actions">
{
Expand Down
2 changes: 1 addition & 1 deletion src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const structuredData = [
<h1 class="hero-title">Fossify</h1>
<p class="lead lede-narrow">
Open-source tools for everyday tasks: photos, calendars, files,
messages, calls, music, notes, camera, and more.
documents, messages, calls, music, notes, camera, and more.
</p>
<div class="actions">
<a class="button primary" href="/apps/">Explore apps</a>
Expand Down
8 changes: 6 additions & 2 deletions src/pages/press.astro
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
import { apps } from "../data/apps";
import { releaseEntries } from "../data/release-info";
import { site } from "../data/site";

const shortDescription =
"Fossify develops open-source Android apps for common phone tasks. The apps contain no advertising, do not track users, work without a Fossify account, and have public source code and release history on GitHub.";

const mediumDescription =
"Fossify is an open-source Android app project covering photos, calendars, files, messages, calls, contacts, music, notes, camera, keyboard, and utilities. The apps request only the permissions needed for their features, contain no advertising, and do not track users. Source code, issues, releases, translations, install links, and app-specific privacy policies are publicly available.";
"Fossify is an open-source Android app project covering photos, calendars, files, documents, messages, calls, contacts, music, notes, camera, keyboard, and utilities. The apps request only the permissions needed for their features, contain no advertising, and do not track users. Source code, issues, releases, translations, install links, and app-specific privacy policies are publicly available.";
const releasedAppCount = apps.filter(
(app) => releaseEntries[app.slug]?.sourceVersion,
).length;
---

<BaseLayout
Expand Down Expand Up @@ -48,7 +52,7 @@ const mediumDescription =
height="92"
/>
<dl class="definition-list">
<div><dt>Released apps</dt><dd>{apps.length}</dd></div>
<div><dt>Released apps</dt><dd>{releasedAppCount}</dd></div>
<div><dt>Platform</dt><dd>Android</dd></div>
<div><dt>Source</dt><dd>GitHub</dd></div>
</dl>
Expand Down
1 change: 1 addition & 0 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,7 @@ textarea {
}

.app-title-heading {
max-width: none;
margin: 0;
}

Expand Down
Loading