Compare commits

..
5 Commits
Author SHA1 Message Date
github-actions[bot] b8a87d1626 chore: bump version to 0.3.3 2026-03-07 07:04:44 +00:00
Frederic CabassutandClaude Opus 4.6 b7b9bca29a fix: update docker-compose only after Docker image is pushed
Move docker-compose.yml update from release.sh (pre-build) to a
post-release job in both bump.yml and release.yml. This ensures the
image tag in docker-compose only appears on main after the image
exists on ghcr.io, preventing Dokploy from trying to pull a
non-existent image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 08:04:18 +01:00
github-actions[bot] bd5819da61 chore: bump version to 0.3.2 2026-03-07 06:56:57 +00:00
Frederic CabassutandClaude Opus 4.6 96e0212d55 fix: include tags in sync pull response and update API spec
- GET /api/sync now attaches tags to notes (matching GET /api/notes
  and GET /api/search behavior)
- Add trashedAt field to Note schema in OpenAPI spec
- Add optional id field to NoteInput schema
- Add 400 error response for POST /api/sync
- Add response schema for GET attachments list
- Regenerate API.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 07:52:36 +01:00
Frederic CabassutandClaude Opus 4.6 5cccaa911a docs: update FEATURES.md, DEPLOYMENT.md, and CLAUDE.md
- FEATURES.md: add rich text editor section (Tiptap, formatting toolbar,
  raw markdown mode) and expand text formatting list
- DEPLOYMENT.md: fix docker-compose example to use image from ghcr.io
  instead of local build
- CLAUDE.md: add documentation maintenance instructions, update CI/CD
  section to reflect consolidated bump.yml workflow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 07:50:10 +01:00
11 changed files with 136 additions and 13 deletions
+25
View File
@@ -95,3 +95,28 @@ jobs:
with:
tag_name: ${{ needs.bump.outputs.tag }}
generate_release_notes: true
pin-docker-compose:
name: Pin docker-compose to released version
runs-on: ubuntu-latest
needs: [bump, release]
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: main
token: ${{ secrets.GITHUB_TOKEN }}
- name: Update docker-compose.yml
env:
TAG: ${{ needs.bump.outputs.tag }}
run: |
VERSION="${TAG#v}"
sed -i "s|image: ghcr.io/bretzel-app/crumbs:.*|image: ghcr.io/bretzel-app/crumbs:${VERSION}|" docker-compose.yml
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docker-compose.yml
git diff --cached --quiet && exit 0
git commit -m "chore: pin docker-compose to ${TAG} [skip ci]"
git push origin main
+25
View File
@@ -54,3 +54,28 @@ jobs:
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
pin-docker-compose:
name: Pin docker-compose to released version
runs-on: ubuntu-latest
needs: release
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: main
token: ${{ secrets.GITHUB_TOKEN }}
- name: Update docker-compose.yml
env:
TAG: ${{ github.ref_name }}
run: |
VERSION="${TAG#v}"
sed -i "s|image: ghcr.io/bretzel-app/crumbs:.*|image: ghcr.io/bretzel-app/crumbs:${VERSION}|" docker-compose.yml
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docker-compose.yml
git diff --cached --quiet && exit 0
git commit -m "chore: pin docker-compose to ${TAG} [skip ci]"
git push origin main
+17 -2
View File
@@ -135,10 +135,14 @@ GitHub Actions with two workflows:
4. **E2E Tests** — Playwright with Chromium (depends on step 3, uploads report on failure)
5. **Docker Build** — validates the Docker image builds (depends on step 3)
**Release** (`.github/workflows/release.yml`) — runs on `v*` tags:
- Runs full CI pipeline, then builds + pushes Docker image to `ghcr.io` (GitHub Container Registry)
**Bump & Release** (`.github/workflows/bump.yml`) — workflow_dispatch (primary release method):
- Runs `scripts/release.sh` to bump version in `package.json` + `docker-compose.yml`, tag, and push
- Runs full CI pipeline, then builds + pushes Docker image to `ghcr.io`
- Creates a GitHub Release with auto-generated notes
**Release** (`.github/workflows/release.yml`) — runs on `v*` tags (fallback for manual/local tag pushes):
- Same as above: CI pipeline, Docker build/push, GitHub Release
**Docker**: Multi-stage Dockerfile (node:22-slim), exposes port 3000, persists data to `/data` volume.
## Testing philosophy: BDD/TDD
@@ -188,3 +192,14 @@ E2E tests follow Cucumber BDD conventions via comments. Follow the [Better Gherk
```
**Resilience test** — ask: *"Will this comment need to change if the UI implementation changes?"* If yes, rewrite it to remove implementation details. The Playwright code underneath handles the *how*; the comments describe the *what*.
## Documentation
Keep docs in `docs/` up to date when making changes. If a feature, API endpoint, deployment config, or architectural decision changes, update the relevant doc file in the same commit or PR:
| Doc | Covers |
|-----|--------|
| `docs/FEATURES.md` | User-facing feature list |
| `docs/ARCHITECTURE.md` | System design, data flow, schema, tech stack |
| `docs/DEPLOYMENT.md` | Docker, env vars, reverse proxy, backups |
| `docs/openapi.yaml` | API spec (run `pnpm docs:api` to regenerate `docs/API.md`) |
+1 -1
View File
@@ -1,6 +1,6 @@
services:
crumbs:
image: ghcr.io/bretzel-app/crumbs:0.3.1
image: ghcr.io/bretzel-app/crumbs:0.3.2
container_name: crumbs
ports:
- "3000:3000"
+24
View File
@@ -103,6 +103,7 @@ List notes
"pinned": true,
"archived": true,
"trashed": true,
"trashedAt": "2025-01-01T00:00:00.000Z",
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
@@ -125,6 +126,7 @@ Create a note
```json
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
@@ -147,6 +149,7 @@ Create a note
"pinned": true,
"archived": true,
"trashed": true,
"trashedAt": "2025-01-01T00:00:00.000Z",
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
@@ -181,6 +184,7 @@ Get a note
"pinned": true,
"archived": true,
"trashed": true,
"trashedAt": "2025-01-01T00:00:00.000Z",
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
@@ -212,6 +216,7 @@ Partial update — only include changed fields.
```json
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
@@ -234,6 +239,7 @@ Partial update — only include changed fields.
"pinned": true,
"archived": true,
"trashed": true,
"trashedAt": "2025-01-01T00:00:00.000Z",
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
@@ -288,6 +294,19 @@ Without `attachmentId`, lists all attachments. With `attachmentId`, returns the
**Response:** `200`
```json
[
{
"id": "id",
"noteId": "noteId",
"filename": "filename",
"mimeType": "mimeType",
"size": 1,
"createdAt": "2025-01-01T00:00:00.000Z"
}
]
```
---
### `POST /api/notes/{id}/attachments`
@@ -366,6 +385,7 @@ Searches across note titles, content, and tags. Excludes trashed notes.
"pinned": true,
"archived": true,
"trashed": true,
"trashedAt": "2025-01-01T00:00:00.000Z",
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
@@ -423,6 +443,7 @@ Pull changes since timestamp
"pinned": true,
"archived": true,
"trashed": true,
"trashedAt": "2025-01-01T00:00:00.000Z",
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
@@ -451,6 +472,7 @@ Push local changes
"operation": "create",
"timestamp": 1,
"data": {
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
@@ -473,4 +495,6 @@ Push local changes
}
```
**Errors:** `400` Invalid changes payload
---
+1 -1
View File
@@ -16,7 +16,7 @@ Open http://localhost:3000 and set your password.
# docker-compose.yml
services:
crumbs:
build: .
image: ghcr.io/bretzel-app/crumbs:latest
ports:
- "8080:3000" # Change external port
volumes:
+15 -4
View File
@@ -8,16 +8,27 @@
- Content supports full Markdown syntax
- Auto-save on editor close
### Markdown Support
- **Bold** (`**text**`)
- *Italic* (`*text*`)
### Rich Text Editor
- WYSIWYG editing powered by Tiptap
- Formatting toolbar with visual controls
- Raw Markdown mode toggle for direct editing
- Undo/Redo with keyboard shortcuts
### Text Formatting
- **Bold** (`**text**` / Ctrl+B)
- *Italic* (`*text*` / Ctrl+I)
- Underline (Ctrl+U)
- ~~Strikethrough~~ (`~~text~~` / Ctrl+Shift+X)
- Headings (`# H1` through `###### H6`)
- Blockquotes (`> quote`)
- Unordered lists (`- item`)
- Ordered lists (`1. item`)
- Code blocks (triple backtick)
- Inline code (single backtick)
- Tables
- Links (auto-linkified URLs)
- Links — insert, edit, and remove with URL input
- Dividers (horizontal rules)
- Text alignment (left, center, right, justify)
- Line breaks
### Checklists / Task Lists
+17 -1
View File
@@ -187,7 +187,13 @@ paths:
type: string
responses:
'200':
description: Attachment list or file content
description: Attachment list (without attachmentId) or file content (with attachmentId)
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Attachment'
post:
summary: Upload an image attachment
tags: [Attachments]
@@ -306,6 +312,8 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Success'
'400':
description: Invalid changes payload
components:
securitySchemes:
@@ -340,6 +348,10 @@ components:
type: boolean
trashed:
type: boolean
trashedAt:
type: string
format: date-time
nullable: true
checklistMode:
type: boolean
sortOrder:
@@ -360,6 +372,10 @@ components:
NoteInput:
type: object
properties:
id:
type: string
format: uuid
description: Optional — generated if omitted
title:
type: string
content:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "crumbs",
"private": true,
"version": "0.3.1",
"version": "0.3.3",
"type": "module",
"scripts": {
"dev": "vite dev",
+1 -2
View File
@@ -60,8 +60,7 @@ echo "Bumping $BUMP version..."
npm version "$BUMP" -m "chore: bump version to %s" --no-git-tag-version
NEW_VERSION=$(node -p "require('./package.json').version")
sed -i'' -e "s|image: ghcr.io/bretzel-app/crumbs:.*|image: ghcr.io/bretzel-app/crumbs:${NEW_VERSION}|" docker-compose.yml
git add package.json docker-compose.yml
git add package.json
git commit -m "chore: bump version to $NEW_VERSION"
git tag "v$NEW_VERSION"
+9 -1
View File
@@ -1,6 +1,7 @@
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types.js';
import { processSyncPush, getChangesSince } from '$lib/sync/server.js';
import { fetchTagsForNotes } from '$lib/server/tags.js';
export const POST: RequestHandler = async ({ request }) => {
const { changes } = await request.json();
@@ -16,5 +17,12 @@ export const POST: RequestHandler = async ({ request }) => {
export const GET: RequestHandler = async ({ url }) => {
const since = parseInt(url.searchParams.get('since') || '0', 10);
const changes = await getChangesSince(since);
return json(changes);
const tagMap = fetchTagsForNotes(changes.map((n) => n.id));
const changesWithTags = changes.map((note) => ({
...note,
tags: tagMap.get(note.id) ?? []
}));
return json(changesWithTags);
};