diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6d7460f --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +PUBLIC_HANDLE=blento.app +PUBLIC_IS_SELFHOSTED= +PUBLIC_DOMAIN=https://blento.app \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 451f67a..841fab1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,13 +19,16 @@ Blento is a Bluesky-powered customizable bento grid website builder. Users authe ## Architecture ### Tech Stack + - **Framework**: SvelteKit 2 with Svelte 5 (using runes: `$state`, `$derived`, `$props`) - **Styling**: Tailwind CSS 4 with container queries (`@container`) - **Deployment**: Cloudflare Workers via `@sveltejs/adapter-cloudflare` - **UI Components**: `@foxui/core`, `@foxui/social` (custom component libraries) ### Grid System + The site uses an 8-column grid layout (`COLUMNS = 8` in `src/lib/index.ts`). Each card has: + - Desktop position/size: `x`, `y`, `w`, `h` - Mobile position/size: `mobileX`, `mobileY`, `mobileW`, `mobileH` @@ -34,26 +37,34 @@ Grid margins: 20px desktop, 12px mobile. ### Key Components **Website Rendering:** + - `Website.svelte` - Read-only view of a user's bento grid - `EditableWebsite.svelte` - Full editing interface with drag-and-drop, card creation, and save functionality +- Styling: two colors: base color (one the gray-ish tailwind colors: `gray`, `neutral`, `stone`, ...) and accent color (one of the not-gray-ish tailwind color: `rose`, `red`, `amber`, ...) **Card System (`src/lib/cards/`):** + - `CardDefinition` type in `types.ts` defines the interface for card types -- Each card type exports a definition with: `type`, `contentComponent`, `editingContentComponent`, optional `creationModalComponent`, `sidebarComponent`, `loadData`, `upload` +- Each card type exports a definition with: `type`, `contentComponent`, optional `editingContentComponent`, `creationModalComponent`, `sidebarComponent`, `loadData`, `upload` (see more info and description in `src/lib/cards/types.ts`) - Card types: Text, Link, Image, Youtube, BlueskyPost, Embed, Map, Livestream, ATProtoCollections, Section - `AllCardDefinitions` and `CardDefinitionsByType` in `index.ts` aggregate all card types +- See e.g. `src/lib/cards/EmbedCard/` and `src/lib/cards/LivestreamCard/` for examples of implementation. +- Cards should be styled to work in light and dark mode (with `dark:` class modifier) as well as when cards are colorful (= bg-color-500 for the card background) (with `accent:` modifier). **ATProto Integration (`src/lib/oauth/`):** + - `auth.svelte.ts` - OAuth client state and login/logout flow using `@atcute/oauth-browser-client` - `atproto.ts` - ATProto API helpers: `resolveHandle`, `listRecords`, `getRecord`, `putRecord`, `deleteRecord`, `uploadImage` - Data is stored in user's PDS under collection `app.blento.card` **Data Loading (`src/lib/website/`):** + - `load.ts` - Fetches user data from their PDS, with Cloudflare KV caching (`USER_DATA_CACHE`) - `data.ts` - Defines which collections/records to fetch - `context.ts` - Svelte contexts for passing DID, handle, and data down the component tree ### Routes + - `/` - Landing page - `/[handle]` - View a user's bento site (loads from their PDS) - `/[handle]/edit` - Edit mode for the user's site @@ -62,10 +73,13 @@ Grid margins: 20px desktop, 12px mobile. - `/api/geocoding` - Geocoding API for map cards ### Item Type + Cards are represented by the `Item` type (`src/lib/types.ts`) with grid position, size, cardType, and cardData properties. ### Collision/Layout Helpers + `src/lib/helper.ts` contains grid layout algorithms: + - `fixCollisions` - Push cards down when they overlap - `compactItems` - Move cards up to fill gaps - `simulateFinalPosition` - Preview where a dragged card will land diff --git a/README.md b/README.md index 9eb1794..f01a781 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,16 @@ WORK IN PROGRESS, not ready for use yet, but you can test it out at: https://ble your personal website in a bento style layout, using your bluesky PDS as a backend. -made with svelte, tailwind. +made with svelte, tailwind and hosted on cloudflare workers. + +## Development + +``` +git clone https://github.com/flo-bit/blento.git +cp .env.example .env +pnpm install +pnpm run dev +``` ## Selfhosting diff --git a/docs/CustomCards.md b/docs/CustomCards.md index 896785b..aa2853f 100644 --- a/docs/CustomCards.md +++ b/docs/CustomCards.md @@ -2,20 +2,8 @@ WORK IN PROGRESS, EARLY STATE, MIGHT CHANGE. -see `src/lib/cards` for how cards are made. +see `src/lib/cards` for how cards are made (and e.g. `src/lib/cards/EmbedCard/` and `src/lib/cards/LivestreamCard/` for examples of implementation). -Current card definition: +Notes: -```ts -export type CardDefinition = { - type: string; - contentComponent: Component; // this is what your card shows - - editingContentComponent?: Component; // if this is not given, defaults to showing contentComponent in edit mode too - creationModalComponent?: Component; // if this is not given will just add a card - - createNew?: (item: Item) => void; // this is run before the card is added, set some settings here - - sidebarComponent?: Component; // this is the button that will be shown in the sidebar to add your card -}; -``` +Cards should be styled to work in light and dark mode (with dark: class modifier) as well as when cards are colorful (= bg-color-500 for the card) (with accent: modifier). diff --git a/src/lib/cards/types.ts b/src/lib/cards/types.ts index c632cb2..7bcc168 100644 --- a/src/lib/cards/types.ts +++ b/src/lib/cards/types.ts @@ -22,33 +22,37 @@ export type ContentComponentProps = { }; export type CardDefinition = { - type: string; - contentComponent: Component; - editingContentComponent?: Component; + type: string; // should be unique + contentComponent: Component; // content of card + editingContentComponent?: Component; // optional content of card in editing mode - createNew?: (item: Item) => void; + createNew?: (item: Item) => void; // set some custom cardData stuff here (or custom default sizes) creationModalComponent?: Component; - settingsModalComponent?: Component; - - upload?: (item: Item) => Promise; + upload?: (item: Item) => Promise; // optionally upload some other data needed for this card + // one of those two has to be set for a card to appear in the sidebar sidebarComponent?: Component; sidebarButtonText?: string; + // if this component exists, a settings button with a popover will be shown containing this component settingsComponent?: Component; + // optionally load some extra data loadData?: ( items: Item[], { did, handle, platform }: { did: string; handle: string; platform?: App.Platform } ) => Promise; - dataKey?: string; + // show color selection popup allowSetColor?: boolean; + // default card background color one of 'base', 'accent', 'transparent', or one of the tailwind colors + // (actual colors only, without 'gray', 'neutral', 'stone', etc) defaultColor?: string; + // for resizing: minW?: number; maxW?: number; @@ -56,4 +60,4 @@ export type CardDefinition = { maxH?: number; canResize?: boolean; -}; +}; \ No newline at end of file diff --git a/wrangler.jsonc b/wrangler.jsonc index 63e29a0..3ca904d 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -42,8 +42,7 @@ "kv_namespaces": [ { "binding": "USER_DATA_CACHE", - "id": "d6ff203259de48538d332b0a5df258a7", - "remote": true + "id": "d6ff203259de48538d332b0a5df258a7" } ] /**