├── apps ├── web │ ├── turso │ │ └── .gitkeep │ ├── .npmrc │ ├── src │ │ ├── lib │ │ │ ├── types.d.ts │ │ │ ├── components │ │ │ │ ├── app │ │ │ │ │ ├── groups │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── connect │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── command │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── command-list-groups.svelte │ │ │ │ │ ├── saves │ │ │ │ │ │ ├── item │ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ │ ├── item-description.svelte │ │ │ │ │ │ │ ├── item-media.svelte │ │ │ │ │ │ │ ├── types │ │ │ │ │ │ │ │ ├── item-color.svelte │ │ │ │ │ │ │ │ ├── item-text.svelte │ │ │ │ │ │ │ │ ├── item-image.svelte │ │ │ │ │ │ │ │ └── item-website.svelte │ │ │ │ │ │ │ └── item-image.svelte │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── nav │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── link.svelte │ │ │ │ │ ├── gradient.svelte │ │ │ │ │ ├── empty-state.svelte │ │ │ │ │ └── copy-button.svelte │ │ │ │ └── site │ │ │ │ │ ├── hero │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── vault-clip-path.svelte │ │ │ │ │ └── context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── logos │ │ │ │ │ ├── twitter-bookmark.svelte │ │ │ │ │ ├── github-star.svelte │ │ │ │ │ ├── codepen.svelte │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── text.svelte │ │ │ │ │ └── colors.svelte │ │ │ ├── index.ts │ │ │ ├── actions │ │ │ │ └── index.ts │ │ │ ├── server │ │ │ │ └── db │ │ │ │ │ ├── index.ts │ │ │ │ │ └── migrate.ts │ │ │ └── stores │ │ │ │ ├── index.ts │ │ │ │ └── new-stash.ts │ │ ├── routes │ │ │ ├── homepage │ │ │ │ └── +server.ts │ │ │ ├── main │ │ │ │ ├── groups │ │ │ │ │ ├── +page.svelte │ │ │ │ │ └── +page.ts │ │ │ │ ├── +page.ts │ │ │ │ ├── unsorted │ │ │ │ │ ├── +page.svelte │ │ │ │ │ └── +page.ts │ │ │ │ ├── group │ │ │ │ │ ├── [slug] │ │ │ │ │ │ └── +page.svelte │ │ │ │ │ ├── delete │ │ │ │ │ │ ├── schema.ts │ │ │ │ │ │ └── +page.server.ts │ │ │ │ │ └── new │ │ │ │ │ │ ├── schema.ts │ │ │ │ │ │ └── +page.server.ts │ │ │ │ ├── save │ │ │ │ │ ├── new │ │ │ │ │ │ ├── schema.ts │ │ │ │ │ │ └── +page.server.ts │ │ │ │ │ └── edit │ │ │ │ │ │ └── [id] │ │ │ │ │ │ └── schema.ts │ │ │ │ └── +page.svelte │ │ │ ├── help │ │ │ │ └── +page.ts │ │ │ ├── (auth) │ │ │ │ ├── login │ │ │ │ │ ├── +page.ts │ │ │ │ │ ├── github │ │ │ │ │ │ └── +server.ts │ │ │ │ │ ├── +page.svelte │ │ │ │ │ ├── google │ │ │ │ │ │ └── +server.ts │ │ │ │ │ └── user-login-form.svelte │ │ │ │ └── logout │ │ │ │ │ └── +page.server.ts │ │ │ ├── extension │ │ │ │ └── +page.ts │ │ │ ├── (legal) │ │ │ │ └── terms │ │ │ │ │ └── +page.svelte │ │ │ ├── api │ │ │ │ ├── explore │ │ │ │ │ ├── +server.ts │ │ │ │ │ └── explore.json │ │ │ │ ├── groups │ │ │ │ │ ├── +server.ts │ │ │ │ │ ├── new │ │ │ │ │ │ └── +server.ts │ │ │ │ │ └── sort │ │ │ │ │ │ └── +server.ts │ │ │ │ ├── saves │ │ │ │ │ ├── [id] │ │ │ │ │ │ └── +server.ts │ │ │ │ │ ├── delete │ │ │ │ │ │ └── [id] │ │ │ │ │ │ │ └── +server.ts │ │ │ │ │ ├── +server.ts │ │ │ │ │ └── metadata │ │ │ │ │ │ └── update │ │ │ │ │ │ └── +server.ts │ │ │ │ └── connect │ │ │ │ │ └── generate-key │ │ │ │ │ └── +server.ts │ │ │ ├── +layout.server.ts │ │ │ ├── +error.svelte │ │ │ └── +layout.svelte │ │ ├── app.html │ │ └── app.d.ts │ ├── postcss.config.cjs │ ├── static │ │ ├── og.png │ │ ├── poof.riv │ │ ├── vault.png │ │ ├── favicon.png │ │ └── screenshot.png │ ├── .eslintrc.cjs │ ├── .prettierignore │ ├── .env.example │ ├── .eslintignore │ ├── .gitignore │ ├── drizzle │ │ └── meta │ │ │ └── _journal.json │ ├── .prettierrc │ ├── tailwind.config.ts │ ├── svelte.config.js │ ├── drizzle.config.ts │ ├── tsconfig.json │ └── vite.config.ts ├── extension │ ├── .env │ ├── src │ │ ├── entries │ │ │ ├── background │ │ │ │ ├── script.ts │ │ │ │ └── serviceWorker.ts │ │ │ └── contentScript │ │ │ │ ├── primary │ │ │ │ └── main.ts │ │ │ │ ├── utils │ │ │ │ └── index.ts │ │ │ │ └── renderContent.ts │ │ ├── vite-env.d.ts │ │ └── app.pcss │ ├── postcss.config.cjs │ ├── .npmrc │ ├── .gitignore │ ├── public │ │ └── icons │ │ │ ├── icon16.png │ │ │ ├── icon32.png │ │ │ ├── icon48.png │ │ │ └── icon128.png │ ├── svelte.config.js │ ├── tailwind.config.ts │ ├── vite.config.ts │ └── tsconfig.json └── launcher │ ├── src-tauri │ ├── build.rs │ ├── icons │ │ ├── icon.ico │ │ ├── icon.png │ │ ├── 32x32.png │ │ ├── icon.icns │ │ ├── 128x128.png │ │ ├── StoreLogo.png │ │ ├── 128x128@2x.png │ │ ├── Square30x30Logo.png │ │ ├── Square44x44Logo.png │ │ ├── Square71x71Logo.png │ │ ├── Square89x89Logo.png │ │ ├── Square107x107Logo.png │ │ ├── Square142x142Logo.png │ │ ├── Square150x150Logo.png │ │ ├── Square284x284Logo.png │ │ ├── Square310x310Logo.png │ │ ├── ios │ │ │ ├── AppIcon-512@2x.png │ │ │ ├── AppIcon-20x20@1x.png │ │ │ ├── AppIcon-20x20@2x.png │ │ │ ├── AppIcon-20x20@3x.png │ │ │ ├── AppIcon-29x29@1x.png │ │ │ ├── AppIcon-29x29@2x.png │ │ │ ├── AppIcon-29x29@3x.png │ │ │ ├── AppIcon-40x40@1x.png │ │ │ ├── AppIcon-40x40@2x.png │ │ │ ├── AppIcon-40x40@3x.png │ │ │ ├── AppIcon-60x60@2x.png │ │ │ ├── AppIcon-60x60@3x.png │ │ │ ├── AppIcon-76x76@1x.png │ │ │ ├── AppIcon-76x76@2x.png │ │ │ ├── AppIcon-20x20@2x-1.png │ │ │ ├── AppIcon-29x29@2x-1.png │ │ │ ├── AppIcon-40x40@2x-1.png │ │ │ └── AppIcon-83.5x83.5@2x.png │ │ └── android │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ └── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ ├── .gitignore │ ├── Cargo.toml │ └── tauri.conf.json │ ├── .vscode │ ├── settings.json │ └── extensions.json │ ├── postcss.config.cjs │ ├── src │ ├── lib │ │ ├── command │ │ │ ├── index.ts │ │ │ ├── footers │ │ │ │ ├── index.ts │ │ │ │ └── new-stash-groups.svelte │ │ │ ├── pages │ │ │ │ └── index.ts │ │ │ ├── command-list-groups.svelte │ │ │ └── command-item-image.svelte │ │ ├── env.ts │ │ ├── utils.ts │ │ ├── stores.ts │ │ └── types.d.ts │ ├── routes │ │ ├── +page.svelte │ │ └── +layout.ts │ ├── app.html │ └── app.css │ ├── .env.example │ ├── app-icon.png │ ├── static │ ├── favicon.png │ └── vite.svg │ ├── .gitignore │ ├── tailwind.config.ts │ ├── svelte.config.js │ ├── tsconfig.json │ └── vite.config.js ├── .npmrc ├── pnpm-workspace.yaml ├── packages ├── ui │ ├── .eslintrc.cjs │ ├── components │ │ └── ui │ │ │ ├── tags │ │ │ └── index.ts │ │ │ ├── gradient │ │ │ ├── index.ts │ │ │ └── gradient.svelte │ │ │ ├── heading │ │ │ ├── index.ts │ │ │ └── heading.svelte │ │ │ ├── masonry │ │ │ └── index.ts │ │ │ ├── section │ │ │ ├── index.ts │ │ │ └── section.svelte │ │ │ ├── typography │ │ │ ├── index.ts │ │ │ └── typography.svelte │ │ │ ├── label │ │ │ ├── index.ts │ │ │ └── label.svelte │ │ │ ├── sonner │ │ │ ├── index.ts │ │ │ └── sonner.svelte │ │ │ ├── checkbox │ │ │ ├── index.ts │ │ │ └── checkbox.svelte │ │ │ ├── shortcut │ │ │ └── index.ts │ │ │ ├── slider │ │ │ ├── index.ts │ │ │ └── slider.svelte │ │ │ ├── switch │ │ │ ├── index.ts │ │ │ └── switch.svelte │ │ │ ├── skeleton │ │ │ ├── index.ts │ │ │ └── skeleton.svelte │ │ │ ├── separator │ │ │ ├── index.ts │ │ │ └── separator.svelte │ │ │ ├── dialog │ │ │ ├── dialog-portal.svelte │ │ │ ├── dialog-header.svelte │ │ │ ├── dialog-footer.svelte │ │ │ ├── dialog-title.svelte │ │ │ ├── dialog-description.svelte │ │ │ ├── dialog.svelte │ │ │ ├── dialog-overlay.svelte │ │ │ ├── index.ts │ │ │ └── dialog-content.svelte │ │ │ ├── scroll-area │ │ │ ├── index.ts │ │ │ ├── scroll-area-scrollbar.svelte │ │ │ └── scroll-area.svelte │ │ │ ├── alert-dialog │ │ │ ├── alert-dialog-portal.svelte │ │ │ ├── alert-dialog-header.svelte │ │ │ ├── alert-dialog-footer.svelte │ │ │ ├── alert-dialog-description.svelte │ │ │ ├── alert-dialog-title.svelte │ │ │ ├── alert-dialog.svelte │ │ │ ├── alert-dialog-action.svelte │ │ │ ├── alert-dialog-cancel.svelte │ │ │ ├── alert-dialog-overlay.svelte │ │ │ ├── alert-dialog-content.svelte │ │ │ └── index.ts │ │ │ ├── avatar │ │ │ ├── index.ts │ │ │ ├── avatar-fallback.svelte │ │ │ ├── avatar-image.svelte │ │ │ └── avatar.svelte │ │ │ ├── form │ │ │ ├── form-button.svelte │ │ │ ├── form-legend.svelte │ │ │ ├── form-description.svelte │ │ │ ├── form-label.svelte │ │ │ ├── form-field-errors.svelte │ │ │ ├── form-fieldset.svelte │ │ │ ├── form-field.svelte │ │ │ ├── index.ts │ │ │ └── form-element-field.svelte │ │ │ ├── command │ │ │ ├── command-footer.svelte │ │ │ ├── command-separator.svelte │ │ │ ├── command-empty.svelte │ │ │ ├── command-shortcut.svelte │ │ │ ├── command-loading.svelte │ │ │ ├── command-list.svelte │ │ │ ├── command-group.svelte │ │ │ ├── command-breadcrumbs.svelte │ │ │ ├── command-item.svelte │ │ │ ├── command.svelte │ │ │ ├── command-input.svelte │ │ │ ├── index.ts │ │ │ └── command-dialog.svelte │ │ │ ├── tooltip │ │ │ ├── index.ts │ │ │ └── tooltip-content.svelte │ │ │ ├── radio-group │ │ │ ├── index.ts │ │ │ ├── radio-group.svelte │ │ │ └── radio-group-item.svelte │ │ │ ├── context-menu │ │ │ ├── context-menu-radio-group.svelte │ │ │ ├── context-menu-separator.svelte │ │ │ ├── context-menu-shortcut.svelte │ │ │ ├── context-menu-label.svelte │ │ │ ├── context-menu-content.svelte │ │ │ ├── context-menu-sub-content.svelte │ │ │ ├── context-menu-item.svelte │ │ │ ├── context-menu-sub-trigger.svelte │ │ │ ├── context-menu-checkbox-item.svelte │ │ │ └── context-menu-radio-item.svelte │ │ │ ├── card │ │ │ ├── card-content.svelte │ │ │ ├── card-footer.svelte │ │ │ ├── card-header.svelte │ │ │ ├── card-description.svelte │ │ │ ├── card.svelte │ │ │ ├── card-title.svelte │ │ │ └── index.ts │ │ │ ├── dropdown-menu │ │ │ ├── dropdown-menu-radio-group.svelte │ │ │ ├── dropdown-menu-shortcut.svelte │ │ │ ├── dropdown-menu-separator.svelte │ │ │ ├── dropdown-menu-label.svelte │ │ │ ├── dropdown-menu-content.svelte │ │ │ ├── dropdown-menu-sub-content.svelte │ │ │ ├── dropdown-menu-item.svelte │ │ │ ├── dropdown-menu-sub-trigger.svelte │ │ │ ├── dropdown-menu-radio-item.svelte │ │ │ ├── dropdown-menu-checkbox-item.svelte │ │ │ └── dropdown-menu-link.svelte │ │ │ ├── select │ │ │ ├── select-separator.svelte │ │ │ ├── select-label.svelte │ │ │ ├── index.ts │ │ │ ├── select-trigger.svelte │ │ │ ├── select-content.svelte │ │ │ └── select-item.svelte │ │ │ ├── drawer │ │ │ ├── drawer-footer.svelte │ │ │ ├── drawer-nested.svelte │ │ │ ├── drawer-overlay.svelte │ │ │ ├── drawer-description.svelte │ │ │ ├── drawer-header.svelte │ │ │ ├── drawer-title.svelte │ │ │ ├── drawer.svelte │ │ │ └── index.ts │ │ │ ├── badge │ │ │ ├── badge.svelte │ │ │ └── index.ts │ │ │ ├── button │ │ │ └── button.svelte │ │ │ ├── input │ │ │ ├── index.ts │ │ │ └── input.svelte │ │ │ └── textarea │ │ │ ├── index.ts │ │ │ └── textarea.svelte │ ├── index.d.ts │ ├── components.json │ ├── icons │ │ ├── google.svelte │ │ └── stash.svelte │ ├── postcss.config.cjs │ └── tsconfig.json ├── constants │ ├── index.js │ ├── package.json │ └── siteconfig.js ├── tsconfig │ ├── package.json │ └── tsconfig-base.json └── config-eslint │ ├── package.json │ └── index.js ├── .prettierrc ├── .vscode └── settings.json ├── .eslintrc.cjs ├── nixpacks.toml ├── .prettierignore ├── turbo.json ├── .gitignore ├── README.md └── package.json /apps/web/turso/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/web/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers = true 2 | -------------------------------------------------------------------------------- /apps/extension/.env: -------------------------------------------------------------------------------- 1 | MANIFEST_VERSION=3 -------------------------------------------------------------------------------- /apps/web/src/lib/types.d.ts: -------------------------------------------------------------------------------- 1 | export type TODO = any; -------------------------------------------------------------------------------- /apps/extension/src/entries/background/script.ts: -------------------------------------------------------------------------------- 1 | import "./main"; 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "apps/*" 3 | - "packages/*" 4 | -------------------------------------------------------------------------------- /apps/extension/src/entries/background/serviceWorker.ts: -------------------------------------------------------------------------------- 1 | import "./main"; 2 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require('@repo/ui/postcss.config'); -------------------------------------------------------------------------------- /apps/extension/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require('@repo/ui/postcss.config'); -------------------------------------------------------------------------------- /apps/launcher/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "svelte.enable-ts-plugin": true 3 | } 4 | -------------------------------------------------------------------------------- /apps/launcher/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require('@repo/ui/postcss.config'); -------------------------------------------------------------------------------- /apps/launcher/src/lib/command/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Command } from "./main.svelte"; -------------------------------------------------------------------------------- /apps/web/static/og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/web/static/og.png -------------------------------------------------------------------------------- /apps/launcher/.env.example: -------------------------------------------------------------------------------- 1 | STRONGHOLD_SALT='my-random-string' 2 | STRONGHOLD_PASSWORD='vault-password' -------------------------------------------------------------------------------- /apps/web/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@repo/eslint-config/index.js'] 3 | }; 4 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/groups/index.ts: -------------------------------------------------------------------------------- 1 | export { default as GroupsList } from './list.svelte'; -------------------------------------------------------------------------------- /apps/web/static/poof.riv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/web/static/poof.riv -------------------------------------------------------------------------------- /apps/web/static/vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/web/static/vault.png -------------------------------------------------------------------------------- /packages/ui/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@repo/eslint-config/index.js'] 3 | }; 4 | -------------------------------------------------------------------------------- /packages/ui/components/ui/tags/index.ts: -------------------------------------------------------------------------------- 1 | import Tags from './tags.svelte'; 2 | 3 | export default Tags; -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "none", 4 | "printWidth": 100 5 | } 6 | -------------------------------------------------------------------------------- /apps/extension/.npmrc: -------------------------------------------------------------------------------- 1 | # auto-install-peers=false 2 | # strict-peer-dependencies=false 3 | engine-strict=true -------------------------------------------------------------------------------- /apps/launcher/app-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/app-icon.png -------------------------------------------------------------------------------- /apps/web/src/lib/components/site/hero/index.ts: -------------------------------------------------------------------------------- 1 | import Hero from "./hero.svelte"; 2 | 3 | export { Hero }; -------------------------------------------------------------------------------- /apps/web/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | // place files you want to import through the `$lib` alias in this folder. 2 | -------------------------------------------------------------------------------- /apps/web/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/web/static/favicon.png -------------------------------------------------------------------------------- /packages/ui/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "@repo/ui/tailwind.config"; -------------------------------------------------------------------------------- /apps/extension/.gitignore: -------------------------------------------------------------------------------- 1 | **/dist 2 | **/node_modules 3 | .DS_Store 4 | dist.zip 5 | vite.config.ts.timestamp-* -------------------------------------------------------------------------------- /apps/web/static/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/web/static/screenshot.png -------------------------------------------------------------------------------- /apps/launcher/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/static/favicon.png -------------------------------------------------------------------------------- /packages/ui/components/ui/gradient/index.ts: -------------------------------------------------------------------------------- 1 | import Gradient from './gradient.svelte'; 2 | 3 | export { Gradient }; -------------------------------------------------------------------------------- /packages/ui/components/ui/heading/index.ts: -------------------------------------------------------------------------------- 1 | import Heading from './heading.svelte'; 2 | 3 | export default Heading; -------------------------------------------------------------------------------- /packages/ui/components/ui/masonry/index.ts: -------------------------------------------------------------------------------- 1 | import Masonry from './masonry.svelte'; 2 | 3 | export default Masonry; -------------------------------------------------------------------------------- /packages/ui/components/ui/section/index.ts: -------------------------------------------------------------------------------- 1 | import Section from './section.svelte'; 2 | 3 | export default Section; -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.workingDirectories": [ 3 | { 4 | "mode": "auto" 5 | } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore files for PNPM, NPM and YARN 2 | pnpm-lock.yaml 3 | package-lock.json 4 | yarn.lock 5 | -------------------------------------------------------------------------------- /apps/extension/public/icons/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/extension/public/icons/icon16.png -------------------------------------------------------------------------------- /apps/extension/public/icons/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/extension/public/icons/icon32.png -------------------------------------------------------------------------------- /apps/extension/public/icons/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/extension/public/icons/icon48.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/connect/index.ts: -------------------------------------------------------------------------------- 1 | export { default as GenerateKeyDialog } from './generate-key-dialog.svelte'; -------------------------------------------------------------------------------- /packages/ui/components/ui/typography/index.ts: -------------------------------------------------------------------------------- 1 | import Typography from './typography.svelte'; 2 | 3 | export default Typography; -------------------------------------------------------------------------------- /apps/extension/public/icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/extension/public/icons/icon128.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /apps/web/src/lib/actions/index.ts: -------------------------------------------------------------------------------- 1 | import { gridArrowKeys } from './grid-arrow-keys'; 2 | 3 | export { 4 | gridArrowKeys 5 | } -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/command/index.ts: -------------------------------------------------------------------------------- 1 | import CommandMenu from "./command-menu.svelte"; 2 | 3 | export { 4 | CommandMenu, 5 | } -------------------------------------------------------------------------------- /packages/ui/components/ui/label/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./label.svelte"; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Label, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/ui/components/ui/sonner/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Toaster } from './sonner.svelte'; 2 | export { toast } from 'svelte-sonner'; 3 | -------------------------------------------------------------------------------- /apps/launcher/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/components/ui/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './checkbox.svelte'; 2 | export { 3 | Root, 4 | // 5 | Root as Checkbox 6 | }; 7 | -------------------------------------------------------------------------------- /packages/ui/components/ui/shortcut/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./shortcut.svelte"; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Shortcut, 7 | }; -------------------------------------------------------------------------------- /packages/ui/components/ui/slider/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./slider.svelte"; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Slider, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/ui/components/ui/switch/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './switch.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Switch 7 | }; 8 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /packages/ui/components/ui/skeleton/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './skeleton.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Skeleton 7 | }; 8 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-512@2x.png -------------------------------------------------------------------------------- /apps/web/src/routes/homepage/+server.ts: -------------------------------------------------------------------------------- 1 | import { redirect } from '@sveltejs/kit'; 2 | 3 | export function GET() { 4 | redirect(302, '/?homepage'); 5 | } -------------------------------------------------------------------------------- /packages/ui/components/ui/separator/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './separator.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Separator 7 | }; 8 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-20x20@1x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-20x20@2x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-20x20@3x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-29x29@1x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-29x29@2x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-29x29@3x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-40x40@1x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-40x40@2x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-40x40@3x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-60x60@2x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-60x60@3x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-76x76@1x.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-76x76@2x.png -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/saves/item/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Item } from './item.svelte'; 2 | export { default as ItemImage } from './item-image.svelte'; -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-20x20@2x-1.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-29x29@2x-1.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-40x40@2x-1.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | // This tells ESLint to load the config from the package `eslint-config-custom` 4 | extends: ['custom'] 5 | }; 6 | -------------------------------------------------------------------------------- /apps/web/src/routes/main/groups/+page.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /apps/web/src/routes/main/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from './$types'; 2 | 3 | export const load = (async () => { 4 | return { title: 'All' }; 5 | }) satisfies PageLoad; -------------------------------------------------------------------------------- /apps/extension/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/web/src/routes/help/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from './$types'; 2 | 3 | export const load = (async () => { 4 | return { title: 'Help' }; 5 | }) satisfies PageLoad; -------------------------------------------------------------------------------- /packages/constants/index.js: -------------------------------------------------------------------------------- 1 | import { siteConfig } from './siteconfig.js'; 2 | import { gradients } from './gradients.js'; 3 | 4 | export { 5 | gradients, 6 | siteConfig 7 | } -------------------------------------------------------------------------------- /apps/extension/src/app.pcss: -------------------------------------------------------------------------------- 1 | * { 2 | @apply border-border; 3 | } 4 | #stashlist-root { 5 | @apply bg-background text-foreground font-sans; 6 | font-size: 1rem !important; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /apps/launcher/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "svelte.svelte-vscode", 4 | "tauri-apps.tauri-vscode", 5 | "rust-lang.rust-analyzer" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/web/src/routes/(auth)/login/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from './$types'; 2 | 3 | export const load = (async () => { 4 | return { title: 'Login' }; 5 | }) satisfies PageLoad; -------------------------------------------------------------------------------- /apps/web/src/routes/main/groups/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from './$types'; 2 | 3 | export const load = (async () => { 4 | return { title: 'Groups' }; 5 | }) satisfies PageLoad; -------------------------------------------------------------------------------- /apps/web/src/routes/main/unsorted/+page.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /nixpacks.toml: -------------------------------------------------------------------------------- 1 | providers = ["node"] 2 | 3 | [phases.install] 4 | cmds = ["npm install -g corepack", "corepack enable", "corepack prepare pnpm@9.2.0 --activate", "pnpm install --filter web"] -------------------------------------------------------------------------------- /apps/launcher/src/lib/env.ts: -------------------------------------------------------------------------------- 1 | import { invoke } from "@tauri-apps/api/core"; 2 | 3 | export async function getEnv(name: string) { 4 | return await invoke("get_env", { name }); 5 | } -------------------------------------------------------------------------------- /apps/web/src/routes/extension/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from './$types'; 2 | 3 | export const load = (async () => { 4 | return { title: 'Extension' }; 5 | }) satisfies PageLoad; -------------------------------------------------------------------------------- /apps/web/src/routes/main/unsorted/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from './$types'; 2 | 3 | export const load = (async () => { 4 | return { title: 'Unsorted' }; 5 | }) satisfies PageLoad; -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/web/src/routes/main/group/[slug]/+page.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jramke/stashlist/HEAD/apps/launcher/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /apps/launcher/src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Generated by Tauri 6 | # will have schema files for capabilities auto-completion 7 | /gen/schemas 8 | -------------------------------------------------------------------------------- /apps/web/src/routes/main/group/delete/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | export const formSchema = z.object({ 3 | id: z.string().min(1), 4 | isOnCurrentSlug: z.boolean() 5 | }); 6 | export type FormSchema = typeof formSchema; 7 | -------------------------------------------------------------------------------- /apps/web/src/routes/main/save/new/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | export const formSchema = z.object({ 3 | input: z.string().min(1), 4 | groups: z.string().optional() 5 | }); 6 | export type FormSchema = typeof formSchema; 7 | -------------------------------------------------------------------------------- /packages/constants/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/constants", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "main": "index.js", 6 | "type": "module", 7 | "exports": { 8 | ".": "./index.js" 9 | } 10 | } -------------------------------------------------------------------------------- /apps/web/.env.example: -------------------------------------------------------------------------------- 1 | DEV='1' 2 | 3 | DATABASE_AUTH_TOKEN='' 4 | # DATABASE_URL='' 5 | DATABASE_URL='http://127.0.0.1:8080' 6 | 7 | GITHUB_CLIENT_ID='' 8 | GITHUB_CLIENT_SECRET='' 9 | 10 | GOOGLE_CLIENT_ID='' 11 | GOOGLE_CLIENT_SECRET='' -------------------------------------------------------------------------------- /apps/web/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /apps/web/src/routes/main/group/new/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | export const formSchema = z.object({ 3 | title: z.string().min(2), 4 | gradientIndex: z.number().optional(), 5 | }); 6 | export type FormSchema = typeof formSchema; 7 | -------------------------------------------------------------------------------- /apps/launcher/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js.timestamp-* 10 | vite.config.ts.timestamp-* 11 | static/groups.json 12 | static/saves.json 13 | -------------------------------------------------------------------------------- /apps/web/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js.timestamp-* 10 | vite.config.ts.timestamp-* 11 | turso/* 12 | !turso/.gitkeep 13 | .vercel 14 | stashlist-replica* -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/index.ts: -------------------------------------------------------------------------------- 1 | import EmptyState from './empty-state.svelte'; 2 | import Gradient from './gradient.svelte'; 3 | import CopyButton from './copy-button.svelte'; 4 | 5 | export { 6 | EmptyState, 7 | Gradient, 8 | CopyButton 9 | } -------------------------------------------------------------------------------- /apps/extension/src/entries/contentScript/primary/main.ts: -------------------------------------------------------------------------------- 1 | import renderContent from "../renderContent"; 2 | import App from "./App.svelte"; 3 | 4 | renderContent(import.meta.PLUGIN_WEB_EXT_CHUNK_CSS_PATHS, (appRoot) => { 5 | new App({ 6 | target: appRoot, 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .svelte-kit 3 | node_modules 4 | /build 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js* 10 | 11 | # Ignore files for PNPM, NPM and YARN 12 | pnpm-lock.yaml 13 | pnpm-workspace.yaml 14 | package-lock.json 15 | yarn.lock 16 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dialog/dialog-portal.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/saves/index.ts: -------------------------------------------------------------------------------- 1 | // import List from './list.svelte'; 2 | // import { Item } from './item'; 3 | 4 | // export { 5 | // List as SavesList, 6 | // Item 7 | // } 8 | 9 | export { default as SavesList } from './list.svelte'; 10 | export * from './item'; -------------------------------------------------------------------------------- /apps/launcher/src/routes/+layout.ts: -------------------------------------------------------------------------------- 1 | // Tauri doesn't have a Node.js server to do proper SSR 2 | // so we will use adapter-static to prerender the app (SSG) 3 | // See: https://beta.tauri.app/start/frontend/sveltekit/ for more info 4 | export const prerender = true; 5 | export const ssr = false; 6 | -------------------------------------------------------------------------------- /apps/web/drizzle/meta/_journal.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "6", 3 | "dialect": "sqlite", 4 | "entries": [ 5 | { 6 | "idx": 0, 7 | "version": "6", 8 | "when": 1720889812656, 9 | "tag": "0000_spooky_marvel_zombies", 10 | "breakpoints": true 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /apps/web/src/lib/components/site/index.ts: -------------------------------------------------------------------------------- 1 | import Footer from './footer.svelte'; 2 | import Navigation from './navigation.svelte'; 3 | import Metadata from './metadata.svelte'; 4 | import { Hero } from './hero'; 5 | 6 | export { 7 | Footer, 8 | Navigation, 9 | Metadata, 10 | Hero, 11 | } -------------------------------------------------------------------------------- /apps/web/src/routes/(legal)/terms/+page.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 |
8 | Terms 9 |
10 |
11 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/tsconfig", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "files": [ 6 | "tsconfig-base.json", 7 | "tsconfig-svelte-library.json" 8 | ], 9 | "devDependencies": { 10 | "@tsconfig/svelte": "^5.0.4" 11 | } 12 | } -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/nav/index.ts: -------------------------------------------------------------------------------- 1 | export {default as Link } from "./link.svelte"; 2 | export {default as Topbar } from "./topbar.svelte"; 3 | export {default as Userinfo } from "./userinfo.svelte"; 4 | export {default as Groups } from "./groups.svelte"; 5 | export {default as NewStashInput } from "./new-stash-input.svelte"; -------------------------------------------------------------------------------- /packages/ui/components/ui/scroll-area/index.ts: -------------------------------------------------------------------------------- 1 | import Scrollbar from "./scroll-area-scrollbar.svelte"; 2 | // import Root from "./scroll-area.svelte"; 3 | import Root from "./scroll-area-legacy.svelte"; 4 | 5 | export { 6 | Root, 7 | Scrollbar, 8 | //, 9 | Root as ScrollArea, 10 | Scrollbar as ScrollAreaScrollbar, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ui/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://shadcn-svelte.com/schema.json", 3 | "style": "default", 4 | "tailwind": { 5 | "config": "tailwind.config.ts", 6 | "css": "globals.pcss", 7 | "baseColor": "stone" 8 | }, 9 | "aliases": { 10 | "components": "$ui/components", 11 | "utils": "$ui/utils" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-portal.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/ui/components/ui/avatar/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./avatar.svelte"; 2 | import Image from "./avatar-image.svelte"; 3 | import Fallback from "./avatar-fallback.svelte"; 4 | 5 | export { 6 | Root, 7 | Image, 8 | Fallback, 9 | // 10 | Root as Avatar, 11 | Image as AvatarImage, 12 | Fallback as AvatarFallback, 13 | }; 14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/form/form-button.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/ui/components/ui/typography/typography.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 | 11 |
-------------------------------------------------------------------------------- /apps/web/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], 7 | "overrides": [ 8 | { 9 | "files": "*.svelte", 10 | "options": { 11 | "parser": "svelte" 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /apps/extension/svelte.config.js: -------------------------------------------------------------------------------- 1 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 2 | import sveltePreprocess from "svelte-preprocess"; 3 | 4 | export default { 5 | // Consult https://github.com/sveltejs/svelte-preprocess 6 | // for more information about preprocessors 7 | preprocess: [sveltePreprocess(), vitePreprocess({})], 8 | }; 9 | -------------------------------------------------------------------------------- /apps/launcher/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | export function memoize(func: (...args: any[]) => any) { 2 | const cache = new Map(); 3 | return function (...args: any[]) { 4 | const key = JSON.stringify(args); 5 | if (!cache.has(key)) { 6 | cache.set(key, func(...args)); 7 | } 8 | return cache.get(key); 9 | }; 10 | } -------------------------------------------------------------------------------- /apps/launcher/src/lib/command/footers/index.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentType } from "svelte"; 2 | 3 | import NewStashGroups from "./new-stash-groups.svelte"; 4 | 5 | type FooterComponents = { 6 | [key: string]: ComponentType; 7 | } 8 | 9 | export const footerComponents = { 10 | newStashGroups: NewStashGroups 11 | } as const satisfies FooterComponents; -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/saves/item/item-description.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /apps/web/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | import sharedConfig from "@repo/ui/tailwind.config"; 3 | 4 | const config: Pick = { 5 | content: [ 6 | './src/**/*.{html,js,svelte,ts}', 7 | '../../packages/ui/**/*.{html,js,svelte,ts}', 8 | ], 9 | presets: [sharedConfig], 10 | }; 11 | 12 | export default config; -------------------------------------------------------------------------------- /apps/extension/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | import sharedConfig from "@repo/ui/tailwind.config"; 3 | 4 | const config: Pick = { 5 | content: [ 6 | './src/**/*.{html,js,svelte,ts}', 7 | '../../packages/ui/**/*.{html,js,svelte,ts}', 8 | ], 9 | presets: [sharedConfig], 10 | }; 11 | 12 | export default config; -------------------------------------------------------------------------------- /apps/launcher/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | import sharedConfig from "@repo/ui/tailwind.config"; 3 | 4 | const config: Pick = { 5 | content: [ 6 | './src/**/*.{html,js,svelte,ts}', 7 | '../../packages/ui/**/*.{html,js,svelte,ts}', 8 | ], 9 | presets: [sharedConfig], 10 | }; 11 | 12 | export default config; -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-footer.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 | 11 |
-------------------------------------------------------------------------------- /packages/ui/components/ui/section/section.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /packages/ui/components/ui/tooltip/index.ts: -------------------------------------------------------------------------------- 1 | import { Tooltip as TooltipPrimitive } from "bits-ui"; 2 | import Content from "./tooltip-content.svelte"; 3 | 4 | const Root = TooltipPrimitive.Root; 5 | const Trigger = TooltipPrimitive.Trigger; 6 | 7 | export { 8 | Root, 9 | Trigger, 10 | Content, 11 | // 12 | Root as Tooltip, 13 | Content as TooltipContent, 14 | Trigger as TooltipTrigger, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/ui/components/ui/radio-group/index.ts: -------------------------------------------------------------------------------- 1 | import { RadioGroup as RadioGroupPrimitive } from 'bits-ui'; 2 | 3 | import Root from './radio-group.svelte'; 4 | import Item from './radio-group-item.svelte'; 5 | const Input = RadioGroupPrimitive.Input; 6 | 7 | export { 8 | Root, 9 | Input, 10 | Item, 11 | // 12 | Root as RadioGroup, 13 | Input as RadioGroupInput, 14 | Item as RadioGroupItem 15 | }; 16 | -------------------------------------------------------------------------------- /packages/ui/components/ui/context-menu/context-menu-radio-group.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/ui/components/ui/card/card-content.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/skeleton/skeleton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /apps/web/src/routes/main/save/edit/[id]/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | export const formSchema = z.object({ 3 | id: z.string(), 4 | title: z.string(), 5 | description: z.string(), 6 | text: z.string(), 7 | groups: z.string(), 8 | // .transform( value => value.split( ',' ).map( String ) ) 9 | // .pipe( z.string().array() ), 10 | // imageUrl: z.string(), 11 | }); 12 | export type FormSchema = typeof formSchema; 13 | -------------------------------------------------------------------------------- /packages/config-eslint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/eslint-config", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "@typescript-eslint/eslint-plugin": "^7.6.0", 6 | "@typescript-eslint/parser": "^7.6.0", 7 | "eslint-config-prettier": "^9.1.0", 8 | "eslint-config-turbo": "^1.13.2", 9 | "eslint-plugin-svelte": "^2.37.0" 10 | }, 11 | "publishConfig": { 12 | "access": "public" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/ui/components/ui/card/card-footer.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/card/card-header.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/select/select-separator.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /apps/web/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/site/logos/twitter-bookmark.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 16 | -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-separator.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": [".svelte-kit/**", ".build/**"] 7 | }, 8 | "preview": { 9 | "dependsOn": ["^build"], 10 | "outputs": [".svelte-kit/**", ".build/**"] 11 | }, 12 | "lint": {}, 13 | "dev": { 14 | "cache": false, 15 | "persistent": true 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui/components/ui/card/card-description.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |

12 | 13 |

14 | -------------------------------------------------------------------------------- /apps/web/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-node'; 2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | preprocess: [vitePreprocess({})], 7 | 8 | kit: { 9 | adapter: adapter(), 10 | csrf: { 11 | checkOrigin: false, 12 | }, 13 | alias: { 14 | '$routes': './src/routes', 15 | } 16 | } 17 | }; 18 | 19 | export default config; 20 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dialog/dialog-header.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-header.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/card/card.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-empty.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/ui/components/ui/context-menu/context-menu-separator.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dropdown-menu/dropdown-menu-separator.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /packages/ui/components/ui/gradient/gradient.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
17 | -------------------------------------------------------------------------------- /apps/launcher/src/lib/stores.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | import type { CommandPage } from "./types"; 3 | 4 | export const apiKey = writable(''); 5 | export const currentPage = writable(undefined); 6 | 7 | export const saves = writable([]); 8 | export const groups = writable([]); 9 | export const loading = writable(false); 10 | 11 | export const newStashInputValue = writable(''); 12 | export const newStashSelectedGroups = writable([]); -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/gradient.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dialog/dialog-footer.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/saves/item/item-media.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | {#if $listLayout !== 'list'} 11 |
12 | 13 |
14 | {/if} -------------------------------------------------------------------------------- /packages/ui/components/ui/select/select-label.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-footer.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-shortcut.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /apps/launcher/src/lib/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentType } from "svelte"; 2 | import type { Icon } from "lucide-svelte"; 3 | import { footerComponents } from "./command/footers"; 4 | 5 | 6 | export type CommandPage = { 7 | name: string; 8 | id: string; 9 | groupId?: string; 10 | placeholder?: string; 11 | preventFilter?: boolean; 12 | height?: number; 13 | icon?: ComponentType; 14 | hideFooter?: boolean; 15 | footer?: keyof typeof footerComponents; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /packages/ui/components/ui/context-menu/context-menu-shortcut.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dialog/dialog-title.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dialog/dialog-description.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /apps/launcher/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tauri + SvelteKit + Typescript App 8 | %sveltekit.head% 9 | 10 | 11 |
%sveltekit.body%
12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dialog/dialog.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /apps/web/src/routes/api/explore/+server.ts: -------------------------------------------------------------------------------- 1 | import type { RequestHandler } from './$types'; 2 | import explore from './explore.json'; 3 | import { error, json, redirect } from '@sveltejs/kit'; 4 | 5 | export const GET: RequestHandler = async ({ locals }) => { 6 | if (!locals.user) redirect(302, '/login'); 7 | 8 | try { 9 | return json(explore); 10 | 11 | } catch (err) { 12 | 13 | console.log('error fetch groups', err); 14 | return error(400, { 15 | message: 'Failed to fetch groups' 16 | }); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/nav/link.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | -------------------------------------------------------------------------------- /apps/web/src/lib/server/db/index.ts: -------------------------------------------------------------------------------- 1 | import { drizzle } from 'drizzle-orm/libsql'; 2 | import { createClient } from '@libsql/client'; 3 | import { env } from '$env/dynamic/private'; 4 | import * as schema from './schema'; 5 | 6 | const client = createClient({ 7 | url: "file:stashlist-replica.db", 8 | syncUrl: env.DATABASE_URL, 9 | authToken: env.DATABASE_AUTH_TOKEN, 10 | encryptionKey: env.DATABASE_REPLICA_ENCRYPTION_KEY, 11 | syncInterval: 60, 12 | }); 13 | 14 | export const db = drizzle(client, { schema }); 15 | -------------------------------------------------------------------------------- /packages/ui/components/ui/heading/heading.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/ui/components/ui/radio-group/radio-group.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/launcher/src/lib/command/pages/index.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentType } from "svelte"; 2 | import type { CommandPage } from "$lib/types"; 3 | 4 | import Connect from "./connect.svelte"; 5 | import NewStash from "./new-stash.svelte"; 6 | import NewStashGroups from "./new-stash-groups.svelte"; 7 | 8 | type PageComponents = { 9 | [key: CommandPage['id']]: ComponentType; 10 | } 11 | export const pageComponents: PageComponents = { 12 | 'connect': Connect, 13 | 'new-stash': NewStash, 14 | 'new-stash-groups': NewStashGroups 15 | }; -------------------------------------------------------------------------------- /packages/ui/components/ui/avatar/avatar-fallback.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /apps/launcher/svelte.config.js: -------------------------------------------------------------------------------- 1 | // Tauri doesn't have a Node.js server to do proper SSR 2 | // so we will use adapter-static to prerender the app (SSG) 3 | // See: https://beta.tauri.app/start/frontend/sveltekit/ for more info 4 | import adapter from "@sveltejs/adapter-static"; 5 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 6 | 7 | /** @type {import('@sveltejs/kit').Config} */ 8 | const config = { 9 | preprocess: vitePreprocess(), 10 | kit: { 11 | adapter: adapter(), 12 | }, 13 | }; 14 | 15 | export default config; 16 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/empty-state.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 | {title} 11 |

{message}

12 | 13 |
-------------------------------------------------------------------------------- /packages/ui/components/ui/drawer/drawer-footer.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/form/form-legend.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-description.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/ui/components/ui/drawer/drawer-nested.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-title.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/ui/components/ui/badge/badge.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/ui/components/ui/drawer/drawer-overlay.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/ui/components/ui/avatar/avatar-image.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /apps/launcher/src/app.css: -------------------------------------------------------------------------------- 1 | * { 2 | @apply border-border; 3 | } 4 | #stashlist { 5 | @apply text-foreground; 6 | min-height: 100%; 7 | } 8 | body, main { 9 | height: 100vh; 10 | background-color: transparent; 11 | } 12 | main { 13 | @apply bg-background rounded-[10px] overflow-hidden; 14 | } 15 | [data-cmdk-list-sizer], .scroll-area { 16 | height: 100%; 17 | } 18 | 19 | /* [data-sonner-toaster] { 20 | --mobile-offset: 0px !important; 21 | --offset: 12px; 22 | } 23 | [data-sonner-toast] { 24 | width: fit-content !important; 25 | transform: translateX(50%); 26 | } */ -------------------------------------------------------------------------------- /packages/ui/components/ui/drawer/drawer-description.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/ui/components/ui/drawer/drawer-header.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /packages/ui/components/ui/drawer/drawer-title.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /apps/web/src/routes/api/groups/+server.ts: -------------------------------------------------------------------------------- 1 | import { getAllGroups } from '$lib/server/db/queries'; 2 | import type { RequestHandler } from './$types'; 3 | import { error, json, redirect } from '@sveltejs/kit'; 4 | 5 | export const GET: RequestHandler = async ({ locals }) => { 6 | if (!locals.user) redirect(302, '/login'); 7 | 8 | try { 9 | const groups = await getAllGroups(locals.user.id); 10 | return json(groups); 11 | } catch (err) { 12 | console.log('error fetch groups', err); 13 | return error(400, { 14 | message: 'Failed to fetch groups' 15 | }); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # svelte 12 | .svelte-kit 13 | 14 | # misc 15 | .DS_Store 16 | *.pem 17 | 18 | # debug 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | # local env files 24 | .env.local 25 | .env.development.local 26 | .env.test.local 27 | .env.production.local 28 | 29 | # turbo 30 | .turbo 31 | 32 | # excalidraw 33 | *.excalidraw 34 | 35 | # notes 36 | NOTES.md 37 | bookmarks.html -------------------------------------------------------------------------------- /apps/web/src/routes/main/+page.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/ui/components/ui/drawer/drawer.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/ui/components/ui/avatar/avatar.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/ui/components/ui/form/form-description.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/site/logos/github-star.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stashlist — Your Creative Vault 2 | 3 | Save inspirational websites, images, code snippets, and more at one place. 4 | 5 | Stashlist comes with a web extension to easily save new stashes. 6 | 7 | Check out the website: [stashlist.app](https://www.stashlist.app/) 8 | 9 | ## Techstack 10 | - Svelte(kit) as framework 11 | - Drizzle ORM as orm 12 | - Turso as database 13 | - Lucia for authentication 14 | - Shadcn-svelte as base for ui 15 | - Turborepo for monorepo 16 | 17 | 18 | # TODOS 19 | 20 | - [ ] Caching 21 | - [ ] Types 22 | -------------------------------------------------------------------------------- /packages/ui/components/ui/label/label.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /packages/ui/icons/google.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/site/logos/codepen.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 20 | -------------------------------------------------------------------------------- /packages/ui/components/ui/form/form-label.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /apps/web/src/routes/(auth)/logout/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { lucia } from '$lib/server/auth'; 2 | import { fail, redirect } from '@sveltejs/kit'; 3 | 4 | import type { Actions } from './$types'; 5 | 6 | export const actions: Actions = { 7 | default: async ({ locals, cookies }) => { 8 | if (!locals.session) { 9 | return fail(401); 10 | } 11 | await lucia.invalidateSession(locals.session.id); 12 | const sessionCookie = lucia.createBlankSessionCookie(); 13 | cookies.set(sessionCookie.name, sessionCookie.value, { 14 | path: '.', 15 | ...sessionCookie.attributes 16 | }); 17 | redirect(302, '/login'); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /apps/web/drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'drizzle-kit'; 2 | import * as dotenv from 'dotenv'; 3 | dotenv.config(); 4 | 5 | const { DATABASE_URL, DATABASE_AUTH_TOKEN } = process.env; 6 | if (!DATABASE_URL) { 7 | throw new Error('No url'); 8 | } 9 | if (!DATABASE_AUTH_TOKEN) { 10 | throw new Error('No auth token'); 11 | } 12 | 13 | export default { 14 | schema: './src/lib/server/db/schema.ts', 15 | out: './drizzle', 16 | driver: 'turso', 17 | dialect: 'sqlite', 18 | dbCredentials: { 19 | url: DATABASE_URL, 20 | authToken: DATABASE_AUTH_TOKEN 21 | }, 22 | // strict: true 23 | verbose: true, 24 | } satisfies Config; 25 | -------------------------------------------------------------------------------- /apps/web/src/routes/api/saves/[id]/+server.ts: -------------------------------------------------------------------------------- 1 | import type { RequestHandler } from './$types'; 2 | 3 | import { error, json, redirect } from '@sveltejs/kit'; 4 | import { getSaveWithGroups } from '$lib/server/db/queries'; 5 | 6 | export const GET: RequestHandler = async ({ locals, params }) => { 7 | if (!locals.user) redirect(302, '/login'); 8 | 9 | try { 10 | const saveId = params.id; 11 | const saveWithGroups = await getSaveWithGroups(saveId); 12 | return json(saveWithGroups); 13 | } catch (err) { 14 | console.log('error fetch save', err); 15 | return error(400, { 16 | message: 'Failed to fetch save' 17 | }); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /packages/ui/components/ui/card/card-title.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-loading.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | *]:flex [&_>*]:items-center [&_>*]:justify-center [&_>*]:gap-2", className)} {...$$restProps}> 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dropdown-menu/dropdown-menu-label.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/ui/components/ui/context-menu/context-menu-label.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-list.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /apps/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | // "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "moduleResolution": "bundler" 13 | } 14 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 15 | // 16 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 17 | // from the referenced tsconfig.json - TypeScript does not merge them in 18 | } 19 | -------------------------------------------------------------------------------- /apps/launcher/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | // "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "moduleResolution": "bundler" 13 | } 14 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 15 | // 16 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 17 | // from the referenced tsconfig.json - TypeScript does not merge them in 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/src/routes/(auth)/login/github/+server.ts: -------------------------------------------------------------------------------- 1 | import type { RequestEvent } from "@sveltejs/kit"; 2 | 3 | import { github } from "$lib/server/auth"; 4 | import { generateState } from "arctic"; 5 | import { redirect } from "@sveltejs/kit"; 6 | 7 | export async function GET(event: RequestEvent): Promise { 8 | const state = generateState(); 9 | const url = await github.createAuthorizationURL(state); 10 | 11 | event.cookies.set("github_oauth_state", state, { 12 | path: "/", 13 | secure: import.meta.env.PROD, 14 | httpOnly: true, 15 | maxAge: 60 * 10, // 10 min 16 | sameSite: "lax" 17 | }); 18 | 19 | return redirect(302, url.toString()); 20 | } -------------------------------------------------------------------------------- /apps/web/src/routes/api/saves/delete/[id]/+server.ts: -------------------------------------------------------------------------------- 1 | import type { RequestHandler } from './$types'; 2 | 3 | import { error, json, redirect } from '@sveltejs/kit'; 4 | import { deleteSave } from '$lib/server/db/queries'; 5 | 6 | export const POST: RequestHandler = async ({ locals, params }) => { 7 | if (!locals.user) redirect(302, '/login'); 8 | 9 | try { 10 | const saveId = params.id; 11 | console.log('delete save', saveId); 12 | await deleteSave(saveId); 13 | return json({ success: true }); 14 | } catch (err) { 15 | console.log('error delete save', err); 16 | return error(400, { 17 | message: 'Failed to delete save' 18 | }); 19 | } 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /apps/web/src/routes/+layout.server.ts: -------------------------------------------------------------------------------- 1 | import { siteConfig } from '@repo/constants'; 2 | import { getLatestReleaseByOS, getLatestReleases, getOS } from '$lib/helper/releases'; 3 | import type { LayoutServerLoad } from './$types'; 4 | import { redirect } from '@sveltejs/kit'; 5 | 6 | export const load: LayoutServerLoad = async ({ locals, route, request }) => { 7 | if (!locals.user && route.id?.includes(siteConfig.appUrl)) redirect(302, '/login'); 8 | 9 | return { 10 | user: locals.user, 11 | os: getOS(request.headers.get('user-agent') ?? null), 12 | // releaseInfo: getLatestReleaseByOS('jramke/stashlist', request.headers.get('user-agent') ?? null), 13 | }; 14 | }; 15 | -------------------------------------------------------------------------------- /apps/web/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | import tsconfigPaths from 'vite-tsconfig-paths'; 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | sveltekit(), 8 | tsconfigPaths({ 9 | loose: true, 10 | root: '../../' 11 | }) 12 | ], 13 | // build: { 14 | // commonjsOptions: { 15 | // // include: [/@repo-ui/, /node_modules/], 16 | // include: [/@ui/, /@repo-ui/, /node_modules/], 17 | // }, 18 | // }, 19 | // server: { 20 | // fs: { 21 | // // Allow serving files from two level up to the project root 22 | // allow: ['../..'], 23 | // }, 24 | // } 25 | }); 26 | -------------------------------------------------------------------------------- /packages/ui/components/ui/card/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './card.svelte'; 2 | import Content from './card-content.svelte'; 3 | import Description from './card-description.svelte'; 4 | import Footer from './card-footer.svelte'; 5 | import Header from './card-header.svelte'; 6 | import Title from './card-title.svelte'; 7 | 8 | export { 9 | Root, 10 | Content, 11 | Description, 12 | Footer, 13 | Header, 14 | Title, 15 | // 16 | Root as Card, 17 | Content as CardContent, 18 | Description as CardDescription, 19 | Footer as CardFooter, 20 | Header as CardHeader, 21 | Title as CardTitle 22 | }; 23 | 24 | export type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; 25 | -------------------------------------------------------------------------------- /apps/launcher/src/lib/command/footers/new-stash-groups.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 |
9 | Toggle groups 10 | 11 |
12 | 13 |
14 | Create stash 15 | 16 |
17 |
-------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-group.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-action.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dialog/dialog-overlay.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | -------------------------------------------------------------------------------- /packages/ui/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | // const tailwindcss = require('tailwindcss'); 2 | // const autoprefixer = require('autoprefixer'); 3 | // const nested = require('tailwindcss/nesting'); 4 | 5 | // const config = { 6 | // plugins: [ 7 | // nested, 8 | // //Some plugins, like tailwindcss/nesting, need to run before Tailwind, 9 | // tailwindcss(), 10 | // //But others, like autoprefixer, need to run after, 11 | // autoprefixer 12 | // ] 13 | // }; 14 | 15 | // module.exports = config; 16 | 17 | /** @type {import('postcss-load-config').Config} */ 18 | module.exports = { 19 | plugins: [ 20 | require('tailwindcss/nesting'), 21 | require('tailwindcss'), 22 | require('autoprefixer'), 23 | ] 24 | }; -------------------------------------------------------------------------------- /packages/tsconfig/tsconfig-base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "inlineSources": false, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "preserveWatchOutput": true, 16 | "skipLibCheck": true, 17 | "strict": true 18 | }, 19 | "exclude": [ 20 | "node_modules" 21 | ] 22 | } -------------------------------------------------------------------------------- /apps/extension/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, loadEnv } from "vite"; 2 | import { svelte } from "@sveltejs/vite-plugin-svelte"; 3 | import webExtension from "@samrum/vite-plugin-web-extension"; 4 | import { getManifest } from "./src/manifest"; 5 | import tsconfigPaths from 'vite-tsconfig-paths'; 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig(({ mode }) => { 9 | const env = loadEnv(mode, process.cwd(), ""); 10 | 11 | return { 12 | plugins: [ 13 | svelte(), 14 | webExtension({ 15 | manifest: getManifest(Number(env.MANIFEST_VERSION)) 16 | }), 17 | tsconfigPaths({ 18 | loose: true, 19 | root: '../../' 20 | }) 21 | ], 22 | }; 23 | }); -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-cancel.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /packages/ui/components/ui/alert-dialog/alert-dialog-overlay.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/site/logos/index.ts: -------------------------------------------------------------------------------- 1 | import Arc from './arc.svelte'; 2 | import Behance from './behance.svelte'; 3 | import Chrome from './chrome.svelte'; 4 | import Codepen from './codepen.svelte'; 5 | import Dribbble from './dribbble.svelte'; 6 | import GithubStar from './github-star.svelte'; 7 | import TwitterBookmark from './twitter-bookmark.svelte'; 8 | import Colors from './colors.svelte'; 9 | import Image from './image.svelte'; 10 | import Text from './text.svelte'; 11 | 12 | import LogoPoof from './logo-poof.svelte'; 13 | 14 | export { 15 | Arc, 16 | Behance, 17 | Chrome, 18 | Codepen, 19 | Dribbble, 20 | GithubStar, 21 | TwitterBookmark, 22 | LogoPoof, 23 | Colors, 24 | Image, 25 | Text, 26 | } -------------------------------------------------------------------------------- /apps/web/src/routes/+error.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 |
12 |

404 Error

13 | Page not found! 14 | {#if $page.data.user} 15 | 16 | {:else} 17 | 18 | {/if} 19 |
20 |
21 | -------------------------------------------------------------------------------- /packages/constants/siteconfig.js: -------------------------------------------------------------------------------- 1 | export const siteConfig = /** @type {const} */ ({ 2 | "name": "Stashlist", 3 | "slogan": "Your Creative Vault", 4 | "appUrl": "/main", 5 | "url": "https://stashlist.app", 6 | "wwwUrl": "https://www.stashlist.app", 7 | "fullAppUrl": "https://stashlist.app/main", 8 | "ogImage": "https://stashlist.app/og.png", 9 | "description": "The creative vault for developers and designers.", 10 | "keywords": "bookmarks, bookmark tool, code snippets, inspiration, stashlist, raindrop alternative, bookmark developers, raindrop developers", 11 | "extensionUrl": { 12 | "chrome": "https://chromewebstore.google.com/detail/flpkpkopodpmfiobdcdhffgphjibolka" 13 | }, 14 | "releaseUrl": "https://github.com/jramke/stashlist/releases/latest" 15 | }); -------------------------------------------------------------------------------- /apps/web/src/lib/stores/index.ts: -------------------------------------------------------------------------------- 1 | import { persisted } from 'svelte-persisted-store'; 2 | import { writable } from 'svelte/store'; 3 | 4 | import { newStashStore } from './new-stash'; 5 | import { itemsStore } from './items'; 6 | 7 | export const listColumns = persisted('stashlist-columns', 3); 8 | 9 | type ListLayout = 'grid' | 'list' | 'masonry'; 10 | export const listLayout = persisted('stashlist-layout', 'grid'); 11 | 12 | export const commandMenuOpen = writable(false); 13 | 14 | export const liveView = writable(false); 15 | 16 | export const editGroupsDialogOpen = writable(false); 17 | 18 | export const newGroupDialogOpen = writable(false); 19 | 20 | export const generateKeyDialogOpen = writable(false); 21 | 22 | export { newStashStore, itemsStore }; -------------------------------------------------------------------------------- /packages/config-eslint/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: [ 4 | 'eslint:recommended', 5 | 'plugin:@typescript-eslint/recommended', 6 | 'plugin:svelte/recommended', 7 | 'prettier', 8 | 'turbo' 9 | ], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['@typescript-eslint'], 12 | parserOptions: { 13 | sourceType: 'module', 14 | ecmaVersion: 2020, 15 | extraFileExtensions: ['.svelte'] 16 | }, 17 | env: { 18 | browser: true, 19 | es2017: true, 20 | node: true 21 | }, 22 | overrides: [ 23 | { 24 | files: ['*.svelte'], 25 | parser: 'svelte-eslint-parser', 26 | parserOptions: { 27 | parser: '@typescript-eslint/parser' 28 | } 29 | } 30 | ] 31 | }; 32 | -------------------------------------------------------------------------------- /packages/ui/components/ui/button/button.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /apps/extension/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true, 5 | "target": "esnext", 6 | "useDefineForClassFields": true, 7 | "module": "esnext", 8 | "resolveJsonModule": true, 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"], 12 | }, 13 | /** 14 | * Typecheck JS in `.svelte` and `.js` files by default. 15 | * Disable checkJs if you'd like to use dynamic types in JS. 16 | * Note that setting allowJs false does not prevent the use 17 | * of JS in `.svelte` files. 18 | */ 19 | "allowJs": true, 20 | "checkJs": true 21 | }, 22 | // "include": ["*"] 23 | "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] 24 | } 25 | -------------------------------------------------------------------------------- /packages/ui/components/ui/separator/separator.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/app/saves/item/types/item-color.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 |
14 |
15 |
16 | 17 | {#if description} 18 | 19 | {description} 20 | 21 | {/if} 22 |
-------------------------------------------------------------------------------- /packages/ui/components/ui/context-menu/context-menu-content.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /apps/launcher/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { sveltekit } from "@sveltejs/kit/vite"; 3 | import tsconfigPaths from 'vite-tsconfig-paths'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [ 8 | sveltekit(), 9 | tsconfigPaths({ 10 | loose: true, 11 | root: '../../' 12 | }) 13 | ], 14 | 15 | // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` 16 | // 17 | // 1. prevent vite from obscuring rust errors 18 | clearScreen: false, 19 | // 2. tauri expects a fixed port, fail if that port is not available 20 | server: { 21 | port: 1420, 22 | strictPort: true, 23 | watch: { 24 | // 3. tell vite to ignore watching `src-tauri` 25 | ignored: ["**/src-tauri/**"], 26 | }, 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /packages/ui/components/ui/form/form-field-errors.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | 22 | {#each errors as error} 23 |
{error}
24 | {/each} 25 |
26 |
27 | -------------------------------------------------------------------------------- /packages/ui/components/ui/dropdown-menu/dropdown-menu-content.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-breadcrumbs.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | {#each pages as page, i} 13 | 25 | {/each} 26 |
-------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "turbo run build", 5 | "dev": "turbo run dev", 6 | "preview": "turbo run preview", 7 | "lint": "turbo run lint", 8 | "format": "prettier --write .", 9 | "ui:add": "pnpm --filter @repo/ui ui:add", 10 | "turso": "pnpm --filter web turso", 11 | "studio": "pnpm --filter web studio", 12 | "generate": "pnpm --filter web generate", 13 | "migrate": "pnpm --filter web migrate", 14 | "push": "pnpm --filter web push", 15 | "introspect": "pnpm --filter web introspect" 16 | }, 17 | "devDependencies": { 18 | "@repo/eslint-config": "workspace:*", 19 | "eslint": "^8.57.1", 20 | "prettier": "^3.4.2", 21 | "prettier-plugin-svelte": "^3.3.2", 22 | "turbo": "^1.13.4" 23 | }, 24 | "engines": { 25 | "node": ">=18" 26 | }, 27 | "packageManager": "pnpm@9.2.0" 28 | } 29 | -------------------------------------------------------------------------------- /packages/ui/components/ui/input/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './input.svelte'; 2 | 3 | type FormInputEvent = T & { 4 | currentTarget: EventTarget & HTMLInputElement; 5 | }; 6 | export type InputEvents = { 7 | blur: FormInputEvent; 8 | change: FormInputEvent; 9 | click: FormInputEvent; 10 | focus: FormInputEvent; 11 | focusin: FormInputEvent; 12 | focusout: FormInputEvent; 13 | keydown: FormInputEvent; 14 | keypress: FormInputEvent; 15 | keyup: FormInputEvent; 16 | mouseover: FormInputEvent; 17 | mouseenter: FormInputEvent; 18 | mouseleave: FormInputEvent; 19 | paste: FormInputEvent; 20 | input: FormInputEvent; 21 | }; 22 | 23 | export { 24 | Root, 25 | // 26 | Root as Input 27 | }; 28 | -------------------------------------------------------------------------------- /apps/web/src/routes/main/group/new/+page.server.ts: -------------------------------------------------------------------------------- 1 | import type { Actions } from './$types'; 2 | 3 | import { superValidate, message } from 'sveltekit-superforms/server'; 4 | import { zod } from 'sveltekit-superforms/adapters'; 5 | import { formSchema } from './schema'; 6 | 7 | export const actions: Actions = { 8 | default: async (event) => { 9 | const form = await superValidate(event, zod(formSchema)); 10 | 11 | if (!form.valid) { 12 | return message(form, { type: 'error', text: 'Something went wrong. Please try again.' }); 13 | } 14 | 15 | try { 16 | const response = await event.fetch('/api/groups/new', { 17 | method: 'POST', 18 | body: JSON.stringify(form.data) 19 | }); 20 | } catch (error) { 21 | console.log('Error creating new group', error); 22 | return message(form, { type: 'error', text: 'Something went wrong. Please try again.' }); 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /packages/ui/components/ui/tooltip/tooltip-content.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /apps/web/src/lib/components/site/hero/vault-clip-path.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/ui/components/ui/form/form-fieldset.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /apps/extension/src/entries/contentScript/utils/index.ts: -------------------------------------------------------------------------------- 1 | export function waitForElement( 2 | selector: string, 3 | root: HTMLElement | null | undefined | Document = document, 4 | timeout: number = 5000 5 | ): Promise { 6 | return new Promise((resolve, reject) => { 7 | const interval = setInterval(() => { 8 | if (!root) { 9 | clearInterval(interval); 10 | clearTimeout(timer); 11 | reject(new Error('Root element not found')); 12 | } 13 | const element = root!.querySelector(selector); 14 | if (element) { 15 | clearInterval(interval); 16 | clearTimeout(timer); 17 | resolve(element); 18 | } 19 | }, 100); 20 | 21 | const timer = setTimeout(() => { 22 | clearInterval(interval); 23 | reject(new Error(`Element ${selector} not found within ${timeout}ms`)); 24 | }, timeout); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /packages/ui/components/ui/textarea/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './textarea.svelte'; 2 | 3 | type FormTextareaEvent = T & { 4 | currentTarget: EventTarget & HTMLTextAreaElement; 5 | }; 6 | 7 | type TextareaEvents = { 8 | blur: FormTextareaEvent; 9 | change: FormTextareaEvent; 10 | click: FormTextareaEvent; 11 | focus: FormTextareaEvent; 12 | keydown: FormTextareaEvent; 13 | keypress: FormTextareaEvent; 14 | keyup: FormTextareaEvent; 15 | mouseover: FormTextareaEvent; 16 | mouseenter: FormTextareaEvent; 17 | mouseleave: FormTextareaEvent; 18 | paste: FormTextareaEvent; 19 | input: FormTextareaEvent; 20 | }; 21 | 22 | export { 23 | Root, 24 | // 25 | Root as Textarea, 26 | type TextareaEvents, 27 | type FormTextareaEvent 28 | }; 29 | -------------------------------------------------------------------------------- /packages/ui/components/ui/select/index.ts: -------------------------------------------------------------------------------- 1 | import { Select as SelectPrimitive } from 'bits-ui'; 2 | 3 | import Label from './select-label.svelte'; 4 | import Item from './select-item.svelte'; 5 | import Content from './select-content.svelte'; 6 | import Trigger from './select-trigger.svelte'; 7 | import Separator from './select-separator.svelte'; 8 | 9 | const Root = SelectPrimitive.Root; 10 | const Group = SelectPrimitive.Group; 11 | const Input = SelectPrimitive.Input; 12 | const Value = SelectPrimitive.Value; 13 | 14 | export { 15 | Root, 16 | Group, 17 | Input, 18 | Label, 19 | Item, 20 | Value, 21 | Content, 22 | Trigger, 23 | Separator, 24 | // 25 | Root as Select, 26 | Group as SelectGroup, 27 | Input as SelectInput, 28 | Label as SelectLabel, 29 | Item as SelectItem, 30 | Value as SelectValue, 31 | Content as SelectContent, 32 | Trigger as SelectTrigger, 33 | Separator as SelectSeparator 34 | }; 35 | -------------------------------------------------------------------------------- /packages/ui/components/ui/badge/index.ts: -------------------------------------------------------------------------------- 1 | import { tv, type VariantProps } from "tailwind-variants"; 2 | export { default as Badge } from "./badge.svelte"; 3 | 4 | export const badgeVariants = tv({ 5 | base: "inline-flex items-center border rounded-full px-2.5 py-0.5 text-xs transition-colors focus:outline-none select-none focus:ring-2 focus:ring-ring focus:ring-offset-2", 6 | variants: { 7 | variant: { 8 | default: "bg-accent shadow-inner shadow-popover border border-accent text-muted-foreground", 9 | secondary: 10 | "bg-secondary hover:bg-secondary/80 border-transparent text-secondary-foreground", 11 | destructive: 12 | "bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground", 13 | outline: "text-foreground", 14 | }, 15 | }, 16 | defaultVariants: { 17 | variant: "default", 18 | }, 19 | }); 20 | 21 | export type Variant = VariantProps["variant"]; 22 | -------------------------------------------------------------------------------- /packages/ui/components/ui/context-menu/context-menu-sub-content.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /apps/web/src/routes/api/connect/generate-key/+server.ts: -------------------------------------------------------------------------------- 1 | import { generateId } from 'lucia'; 2 | import type { RequestHandler } from './$types'; 3 | import { error, json, redirect } from '@sveltejs/kit'; 4 | import { updateUser } from '$lib/server/db/queries'; 5 | import { Argon2id } from "oslo/password"; 6 | 7 | export const POST: RequestHandler = async ({ locals }) => { 8 | if (!locals.user) redirect(302, '/login'); 9 | 10 | const encodedUserName = encodeURIComponent(locals.user.username); 11 | const apiKey = encodedUserName + '-' + generateId(30); 12 | 13 | const argon2id = new Argon2id(); 14 | const hash = await argon2id.hash(apiKey); 15 | 16 | await updateUser(locals.user.id, { apiKeyHash: hash }); 17 | 18 | try { 19 | return json({ apiKey }); 20 | } catch (err) { 21 | console.log('error generating api key', err); 22 | return error(400, { 23 | message: 'Failed to generate API Key' 24 | }); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /apps/launcher/src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "Stashlist_Launcher" 3 | version = "0.1.0" 4 | description = "Stashlist Launcher" 5 | authors = ["you"] 6 | edition = "2021" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [build-dependencies] 11 | tauri-build = { version = "2.0.0-beta", features = [] } 12 | 13 | [dependencies] 14 | tauri = { version = "2.0.0-beta", features = [] } 15 | tauri-plugin-shell = "2.0.0-beta" 16 | serde = { version = "1", features = ["derive"] } 17 | serde_json = "1" 18 | tauri-plugin-http = "2.0.0-beta.9" 19 | tauri-plugin-stronghold = "2.0.0-beta.6" 20 | rust-argon2 = "2.1.0" 21 | tauri-plugin-clipboard-manager = "2.1.0-beta.4" 22 | dotenvs = "0.1.0" 23 | 24 | [target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] 25 | tauri-plugin-autostart = "2.0.0-beta" 26 | tauri-plugin-global-shortcut = "2.0.0-beta" 27 | 28 | -------------------------------------------------------------------------------- /packages/ui/components/ui/command/command-item.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /apps/web/src/lib/server/db/migrate.ts: -------------------------------------------------------------------------------- 1 | import { migrate } from 'drizzle-orm/libsql/migrator'; 2 | import { drizzle } from 'drizzle-orm/libsql'; 3 | import { createClient } from '@libsql/client'; 4 | import * as dotenv from 'dotenv'; 5 | dotenv.config(); 6 | 7 | const { DATABASE_URL, DATABASE_AUTH_TOKEN } = process.env; 8 | if (!DATABASE_URL) { 9 | throw new Error('No url'); 10 | } 11 | if (!DATABASE_AUTH_TOKEN) { 12 | throw new Error('No auth token'); 13 | } 14 | 15 | const client = createClient({ url: DATABASE_URL as string, authToken: DATABASE_AUTH_TOKEN as string }); 16 | const db = drizzle(client); 17 | 18 | async function main() { 19 | try { 20 | console.log('Migration started...'); 21 | await migrate(db, { 22 | migrationsFolder: 'drizzle' 23 | }); 24 | console.log('Tables migrated!'); 25 | process.exit(0); 26 | } catch (error) { 27 | console.error('Error performing migration: ', error); 28 | process.exit(1); 29 | } 30 | } 31 | main(); -------------------------------------------------------------------------------- /apps/web/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | 3 | import type { TODO } from '$lib/types'; 4 | 5 | // for information about these interfaces 6 | declare global { 7 | namespace App { 8 | // interface Error {} 9 | interface Locals { 10 | user: import('lucia').User | null; 11 | session: import('lucia').Session | null; 12 | } 13 | // interface PageData {} 14 | interface PageState { 15 | editStash?: { 16 | form: import('sveltekit-superforms').SuperValidated | null | string; 17 | save: TODO; 18 | groups: TODO; 19 | isDialog: boolean; 20 | }; 21 | editGroup?: { 22 | form: import('sveltekit-superforms').SuperValidated | null | string; 23 | groups: TODO; 24 | isDialog: boolean; 25 | }; 26 | } 27 | // interface Platform {} 28 | namespace Superforms { 29 | type Message = { 30 | type: 'error' | 'success'; 31 | text: string; 32 | }; 33 | } 34 | } 35 | } 36 | 37 | export {}; 38 | -------------------------------------------------------------------------------- /packages/ui/components/ui/form/form-field.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | 21 | 22 |
23 | 24 |
25 |
26 | -------------------------------------------------------------------------------- /apps/web/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | {#if !$page.route?.id?.includes(siteConfig.appUrl)} 24 | 25 | {/if} 26 | 27 |
28 | 29 |
30 | 31 | {#if !$page.route?.id?.includes(siteConfig.appUrl)} 32 |