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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,3 @@ jobs:
- run: bun install --frozen-lockfile
- run: bun run build

e2e:
name: E2E Tests
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bunx playwright install chromium --with-deps
- run: bun run test:e2e
9 changes: 0 additions & 9 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
},
"devDependencies": {
"@biomejs/biome": "^2.3.10",
"@playwright/test": "^1.57.0",
"@sveltejs/adapter-node": "^5.4.0",
"@sveltejs/kit": "^2.49.2",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
Expand Down Expand Up @@ -255,8 +254,6 @@

"@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="],

"@playwright/test": ["@playwright/test@1.57.0", "", { "dependencies": { "playwright": "1.57.0" }, "bin": { "playwright": "cli.js" } }, "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA=="],

"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],

"@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@28.0.9", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-PIR4/OHZ79romx0BVVll/PkwWpJ7e5lsqFa3gFfcrFPWwLXLV39JVUzQV9RKjWerE7B845Hqjj9VYlQeieZ2dA=="],
Expand Down Expand Up @@ -633,10 +630,6 @@

"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],

"playwright": ["playwright@1.57.0", "", { "dependencies": { "playwright-core": "1.57.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw=="],

"playwright-core": ["playwright-core@1.57.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ=="],

"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],

"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
Expand Down Expand Up @@ -813,8 +806,6 @@

"libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="],

"playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],

"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],

"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
Expand Down
3 changes: 3 additions & 0 deletions docs/knowledges/data-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ members
├── name TEXT NOT NULL
├── bio TEXT
├── imageUrl TEXT
├── githubUrl TEXT
├── twitterUrl TEXT
├── websiteUrl TEXT
├── pageContent TEXT
├── viewCount INTEGER NOT NULL DEFAULT 0
├── createdAt INTEGER NOT NULL
Expand Down
30 changes: 30 additions & 0 deletions docs/knowledges/image-upload.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,38 @@ const MAX_BASE64_SIZE = Math.ceil(10 * 1024 * 1024 * 1.37);
- Base64 adds ~37% overhead
- 10MB file → ~13.7MB base64

## S3 Key Format

Keys follow the format: `{folder}/{uuid}-{filename}.{ext}`

Example: `articles/a1b2c3d4-e5f6-7890-abcd-ef1234567890-cover.webp`

Allowed folders: `images`, `uploads`, `covers`, `avatars`, `articles`, `members`, `projects`

## S3 Cleanup

When images are changed or removed, the old S3 file is automatically deleted:

- **Change**: Old image deleted after new upload succeeds
- **Remove**: Image deleted immediately when "Remove" button clicked
- **External URLs**: Non-S3 URLs (different host) are ignored safely

The `removeByUrl` command in `storage.remote.ts` handles URL-to-key conversion server-side.

## User Input Methods

The `ImageUpload` component supports:

1. **Click**: Click to open file picker
2. **Drag & Drop**: Drag image files onto the component
3. **Paste (Ctrl+V)**: Paste from clipboard anywhere on the page

Paste is handled globally via `svelte:window onpaste` and skips INPUT/TEXTAREA elements to avoid conflicts.

## Design Decisions

- **Never reject user uploads**: Compress instead of refusing
- **Quality over size**: Try high quality first, only reduce if needed
- **GIF exception**: GIFs skip compression (animation would be lost)
- **Clean up S3**: Delete old files on change/remove to avoid orphans
- **Fire-and-forget cleanup**: S3 deletion errors don't block the UI
3 changes: 3 additions & 0 deletions drizzle/0006_add-member-social-links.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE "member" ADD COLUMN "github_url" text;--> statement-breakpoint
ALTER TABLE "member" ADD COLUMN "twitter_url" text;--> statement-breakpoint
ALTER TABLE "member" ADD COLUMN "website_url" text;
Loading