Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - Sumit189/GitGalleryApp · GitHub
Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Sumit189/GitGalleryApp · GitHub
Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Sumit189/GitGalleryApp · GitHub
Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - Sumit189/GitGalleryApp · GitHub
Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Sumit189/GitGalleryApp · GitHub
Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Sumit189/GitGalleryApp · GitHub
Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - Sumit189/GitGalleryApp · GitHub
Skip to content

Repository files navigation

GitGallery preview

Latest releaseGitHub starsExpo + React NativeLicense

GitGallery

GitGallery is a privacy-first photo vault that stores your memories securely in your own GitHub repository. No third-party servers, no data mining, no ads. Just you, your device, and GitHub.

Your photos are version-controlled, encrypted, and fully owned by you. Whether you're backing up personal photos or building a digital journal, GitGallery keeps your data safe and accessible.

Built with Expo and React Native, the app currently targets Android with a cross-platform foundation ready for future iOS and web releases.

Core principles: Ownership, Transparency, and Privacy by Design.

Behind the Build

F*** DB: How I built a photo gallery using GitHub as storage

Downloads

You can get GitGallery in two ways:

Option 1: Build it yourself - Follow the Building a Release instructions below to create your own APK. This is free but requires some setup.

Option 2: Get it from Play Store - Skip the hassle and support the project by purchasing it at a minimal price from Google Play.

Get it on Google Play

Your Play Store purchase keeps the project sustainable and funds ongoing development.

Why GitGallery?

  • Own your storage: photos live in your private GitHub repo instead of someone else’s cloud.
  • Familiar tooling: Git history, pull requests, and Actions can automate your media backups.
  • Thoughtful UX: modern UI with dark/light themes, album filters, and clear sync states.
  • Offline friendly: a local queue and SQLite cache keep track of work even when the network drops.

Features at a Glance

  • GitHub Device Flow sign-in - no personal access tokens to copy/paste.
  • Guided repo setup that can create a fresh private repository for you.
  • Local ↔ cloud gallery views so you can browse device photos or the repo-backed library.
  • Selective album syncing with optional auto-delete after successful uploads.
  • Job queue with resumable uploads, retry handling, and conflict detection (requires app to be open).
  • Repo maintenance actions, including an optional clean‑slate reset that rewrites history (explicit opt‑in with double confirmation; use with caution).

Getting Started

Requirements

  • Node.js 18 or newer and npm 9+.
  • Expo CLI (npm install -g expo-cli) if you prefer the classic developer menu.
  • A GitHub account capable of creating private repositories.

Local Setup

  1. Clone the repo and install dependencies:
    git clone https://github.com/Sumit189/GitGallery.git
    cd GitGallery
    npm install
  2. Create a GitHub OAuth app (Device Flow enabled) and note the Client ID. Scope should allow repo access.
  3. Provide the Client ID to the app at runtime using the Expo public env var:
    • Easiest (one-off):
       EXPO_PUBLIC_GITHUB_CLIENT_ID=<your_client_id> npx expo start
    • Or set it in eas.json under the build profile you use (see below) so local runs via EAS CLI inherit it.
  4. Ensure your app.json contains your EAS project ID at expo.extra.eas.projectId. You can find this in the EAS Dashboard or after running eas project:init.
  5. Start the project with npx expo start, then launch on Android or the web preview.
  6. On first launch, sign in with GitHub, pick (or create) a private repo, and choose which albums should auto-sync.

Building a Release

  • Make sure EXPO_PUBLIC_GITHUB_CLIENT_ID is set in eas.json for the profile you will use (e.g., production). Example:
     {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_GITHUB_CLIENT_ID": "<your_client_id>"
    }
    }
    }
    }
  • Ensure app.json includes your EAS project ID at expo.extra.eas.projectId.
  • Run a build:
     eas build --platform android --profile production
  • Artifacts will be available in the EAS dashboard once the build completes.

How Sync Works

  • On-device index: a lightweight SQLite store remembers every asset fingerprint, upload status, and last-known SHA.
  • Job queue: uploads, deletions, and downloads run through a serialized queue so the UI stays responsive.
  • GitHub bridge: Octokit handles file pushes, branch resets, and content downloads against your chosen repo.
  • Metadata mirror: a meta index inside the repo lets the app fetch cloud thumbnails quickly without downloading originals.
  • Recovery tools: auto-sync blocklists, repo resets, and cache clears help recover from API hiccups without nuking the app.

Roadmap & Ideas

  • Background sync triggers (App Clips / Headless JS) once platforms allow it.
  • End-to-end encryption for assets before they leave the device.
  • Video support and higher throughput batching for large libraries.
  • Share-sheet shortcut to push a single freshly-snapped photo to GitHub.

Suggestions live in the issue tracker-feel free to propose others.

Contributing

  • Check open issues or start a discussion before tackling big changes.
  • Keep pull requests focused; it makes review easier for everyone.
  • Use npx expo start for local testing and verify both local and cloud gallery modes before submitting.
  • If you touch sync logic, include notes on failure scenarios you exercised.

Community & Support

  • File bugs and feature requests via GitHub Issues.
  • If you ship something cool (actions workflows, automations, etc.), link it in a discussion so others can learn from it.

License

Released under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages