Skip to content
Draft

V3 #4

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
143 commits
Select commit Hold shift + click to select a range
c6a4d37
Clean old files
patrick11514 May 3, 2025
924800a
Initial commit
patrick11514 May 3, 2025
350de87
Init DB schema
patrick11514 May 3, 2025
2f04b2f
Added bootstrap icons
patrick11514 May 3, 2025
6fc7cf2
Added nav + translations
patrick11514 May 3, 2025
c1128a6
Reworked state management
patrick11514 May 3, 2025
c251d37
Added footer
patrick11514 May 3, 2025
5440137
Some basic design for nav
patrick11514 May 3, 2025
d6cd473
Added tw merge
patrick11514 May 3, 2025
161dbd6
Setup origins + csrf
patrick11514 May 4, 2025
bcace21
Correct typing of entries and fromEntries
patrick11514 May 4, 2025
bfc7c96
Create foundation for logging user visits
patrick11514 May 4, 2025
b9c82cf
Added mobile design for navigation
patrick11514 May 4, 2025
4db7f7e
Added clickOutside
patrick11514 May 4, 2025
cc8df5e
Reactive language
patrick11514 May 4, 2025
35955de
Almost done with main page
patrick11514 May 4, 2025
37037e8
Remove default file
patrick11514 May 4, 2025
b4ae3f7
Force redirect to /cs when accessing without any path
patrick11514 May 4, 2025
802fcdc
Main page done
patrick11514 May 4, 2025
ba9625d
Changed navigation size
patrick11514 May 4, 2025
879af10
Reformat
patrick11514 May 4, 2025
fece823
Error console statements
patrick11514 May 4, 2025
48e428d
Fix migration script
patrick11514 May 4, 2025
25cdc72
Removed per page desc + added embed things
patrick11514 May 4, 2025
fd54bfc
Log visitors
patrick11514 May 4, 2025
a187fe4
404 Error page done
patrick11514 May 4, 2025
f51e659
Reformat + eslint things
patrick11514 May 4, 2025
b07c5a1
Copy env file before build
patrick11514 May 4, 2025
99d4371
Move starback into layout
patrick11514 May 5, 2025
7212b7d
Rich text should use target _blank
patrick11514 May 5, 2025
55ff5c5
Added migration for accounts
patrick11514 May 5, 2025
af91134
Update packages
patrick11514 May 9, 2025
6310db8
Wip login
patrick11514 May 9, 2025
9e28514
Don't leave / at the end of url when redirecting
patrick11514 May 9, 2025
94d842b
Finished login
patrick11514 May 9, 2025
3f077ff
Main Admin page done
patrick11514 May 9, 2025
56fc68c
Updated responsivity
patrick11514 May 9, 2025
02dbe93
Finished Dashboard
patrick11514 May 9, 2025
066d2c5
Format + lint
patrick11514 May 9, 2025
4e1f6dc
Create database structure for gallery
patrick11514 May 9, 2025
1c49904
Cenrter vertically
patrick11514 May 9, 2025
d892ed0
Only allow console.error in API routes
patrick11514 May 10, 2025
7fb0095
When redirecting to login, put queryParams + custom redirect function
patrick11514 May 10, 2025
a0856fd
Installed sweet alers
patrick11514 May 10, 2025
5db45bd
Added support for migration up/down
patrick11514 May 10, 2025
dbd3f6a
Resolve translation from string; replace placeholders
patrick11514 May 10, 2025
c87624b
Added required
patrick11514 May 10, 2025
c27c45d
Sync schema
patrick11514 May 10, 2025
d99fc22
Added equipment type things
patrick11514 May 10, 2025
8537777
Reformat
patrick11514 May 10, 2025
f74925d
Fallback to cs langauge
patrick11514 May 11, 2025
db233bd
Added selecti
patrick11514 May 11, 2025
eeb4f8b
Added w-full for FormItem
patrick11514 May 11, 2025
858aa52
Finished equipment things
patrick11514 May 14, 2025
1b5e4ba
Change default target to null
patrick11514 May 20, 2025
3268074
Update button padding
patrick11514 May 20, 2025
69b3b28
Added new colors
patrick11514 May 20, 2025
92141ce
Justify content to start instead of center
patrick11514 May 20, 2025
577ca22
Reworked design
patrick11514 May 20, 2025
51b7108
Refactor Equipment page
patrick11514 May 21, 2025
83998a7
Added Article page
patrick11514 May 21, 2025
1ff8534
Cleaned migrations
patrick11514 May 21, 2025
da5d1e6
Some adjustements
patrick11514 May 21, 2025
ff62497
Fix types
patrick11514 May 21, 2025
fd278d7
Upload images + Image component
patrick11514 May 21, 2025
1f0fd32
Moved uuid of image to name
patrick11514 May 22, 2025
f66aa75
WIP Article create/edit
patrick11514 May 22, 2025
93fedb0
Reformat
patrick11514 May 22, 2025
990537c
Added config for tailwind typography
patrick11514 Jun 3, 2025
c7bbb50
Added markdown component
patrick11514 Jun 3, 2025
ab22a91
Finished uploading + removing images
patrick11514 Jun 3, 2025
02ea674
Moved yes/no to global translates
patrick11514 Jun 3, 2025
aa3b1c9
Added startWith for admin
patrick11514 Jun 3, 2025
48480f1
Added class for FormItem
patrick11514 Jun 3, 2025
feacacb
Added route for uploads API
patrick11514 Jun 3, 2025
653fb11
Set canvas to fixed
patrick11514 Jun 3, 2025
a7060d2
Working on article creation
patrick11514 Jun 3, 2025
d352f68
Match height of input and select
patrick11514 Jun 6, 2025
7c7054a
Added input for dates and date times
patrick11514 Jun 6, 2025
7a7fd28
Some table components
patrick11514 Jun 6, 2025
c63a15e
Bool to format without time
patrick11514 Jun 6, 2025
02fd432
Added proper typing for specific inputs: Text/Number
patrick11514 Jun 6, 2025
7afa4ad
Updated logging
patrick11514 Jun 7, 2025
cc3644e
Reformat
patrick11514 Jun 9, 2025
2e60de6
Added route for update + delete, and moved shemes
patrick11514 Jun 9, 2025
074dd99
Added lang for articles
patrick11514 Jun 9, 2025
66962be
Article management done
patrick11514 Jun 9, 2025
8dcc594
Insert only if some data presentedx
patrick11514 Jun 16, 2025
6987ab4
Added priority to equipment, migrate to table components
patrick11514 Jun 16, 2025
5f86a49
Fix responsive design
patrick11514 Jun 16, 2025
3c9ac59
Unify h1, h2 to component
patrick11514 Jun 16, 2025
c385c53
Update h1 + fix dialog
patrick11514 Jun 16, 2025
9e3fae9
Article must contain at leas one image
patrick11514 Jun 16, 2025
c44689a
Limit inputs, add description
patrick11514 Jun 16, 2025
12350c9
Added gallery main page
patrick11514 Jun 16, 2025
29d991c
Set lang to state, for redirects to use
patrick11514 Jun 16, 2025
b49cee5
Use own redirect function
patrick11514 Jun 16, 2025
ef28819
Remove import + add anchor tag
patrick11514 Jun 16, 2025
fea8dac
Match start for normal pages
patrick11514 Jun 16, 2025
4122ba3
Add exposure to preview, and sort in admin by created
patrick11514 Jun 16, 2025
b4f3121
Use normal redirect for the next parameter
patrick11514 Jun 16, 2025
1d8301a
On mobile, there should be only one article in row
patrick11514 Jun 16, 2025
b91ebdb
Use background color instead of black
patrick11514 Jun 16, 2025
34a9fd2
Special syntax for: 1 předmět, 2 předměty...
patrick11514 Jun 16, 2025
3600f28
Dots for element list
patrick11514 Jun 16, 2025
a7c4db7
Finished gallery
patrick11514 Jun 16, 2025
fe19e4e
Reformat
patrick11514 Jun 16, 2025
f8af7b6
Test deploy on beta website
patrick11514 Jun 16, 2025
3513555
Add tsx for running migrations
patrick11514 Jun 16, 2025
6c2b1c6
Disable darkreader on my site
patrick11514 Jun 16, 2025
0e0475f
Reformat
patrick11514 Jun 16, 2025
5c857a4
Don't reset the exposure info
patrick11514 Jun 17, 2025
c37f050
Fit gallery item to whole width on mobile
patrick11514 Jun 17, 2025
8d4fd63
Fix links + z index of navigation
patrick11514 Jun 17, 2025
7102ded
Cosmetics
patrick11514 Jun 17, 2025
9bca3d1
Links in RichText can disable blank target
patrick11514 Jun 17, 2025
7e88102
Whole article as link + fix equipment showcase
patrick11514 Jun 17, 2025
4e7fce1
Reformat
patrick11514 Jul 4, 2025
3ed3481
fix lint staged
patrick11514 Jul 4, 2025
0b388bd
Added contact page
patrick11514 Jul 4, 2025
d4406ed
Testing logging
patrick11514 Jul 4, 2025
7b10be1
Fixed main bottle neck, when I was reading the original big file alwa…
patrick11514 Jul 4, 2025
2c4646b
Optimize gallery image loading with streaming and proper lazy loading…
Copilot Nov 30, 2025
06475a4
Move the title to same position as in gallery
patrick11514 Jul 6, 2025
3f2d5cf
Fix missing translation for Contact
patrick11514 Jul 6, 2025
a56e7dc
WIP
patrick11514 Jul 6, 2025
b215c34
Finish migration
patrick11514 Jul 9, 2025
c3ab960
Gather dynamic translations, and use it in gallery
patrick11514 Jul 9, 2025
aae92fe
Fix multiple primary key
patrick11514 Jul 11, 2025
2c5a814
Working on translatable form
patrick11514 Jul 28, 2025
35ae216
Changed prettier formatting
patrick11514 Jul 28, 2025
e5e3041
Updated the prop type style
patrick11514 Jul 28, 2025
3960f80
Fix type error
patrick11514 Jul 28, 2025
4c018ad
Rewrite of the form components
patrick11514 Jul 29, 2025
2e8b7af
Allow Input use outside the form
patrick11514 Jul 30, 2025
9502a7d
Allow button use outside the form
patrick11514 Jul 30, 2025
e97cc50
Added nvmrc file
patrick11514 Aug 11, 2025
bc19ebe
Implemented actions + finished the form functionality
patrick11514 Aug 11, 2025
4c99870
Removed unsupported files entry
patrick11514 Aug 23, 2025
04166db
Updated packages
patrick11514 Aug 23, 2025
601ad4c
Finished components
patrick11514 Aug 23, 2025
0e3fe7b
Cleanup
patrick11514 Aug 23, 2025
2b779db
Almost finished the translation thingy
patrick11514 Jan 6, 2026
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
25 changes: 14 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
#webserver config
# node server config
HOST=0.0.0.0
PORT=5178
ORIGIN=http://localhost:5178
PUBLIC_ORIGIN=https://myweb.cz
BODY_SIZE_LIMIT=16777216 # max upload size in bytes
#database config
# database config
DATABASE_IP=10.10.10.223
DATABASE_PORT=3306
DATABASE_USER=superclovek
DATABASE_PASSWORD=tajnyheslo123456
DATABASE_NAME=website
DATABASE_URL=mysql://superclovek:tajnyheslo123456@10.10.10.223:3306/website
#secret pro JWT (tím se bude podepisovat JWT token - https://jwt.io/)
DATABASE_NAME=db
DATABASE_URL=mysql://superclovek:tajnyheslo123456@10.10.10.223:3306/db
# jwt settings
JWT_SECRET=text
#v sekundách (10 min = 10 * 60)
#expiruje pouze pokud uživatel danou dobu nic nedělá (neprochází stránky)
# marks how many seconds until session cookie expire
COOKIE_EXPIRE=1200
#v sekundách (5 minut = 5 * 60)
PUBLIC_CHECK_COOKIE_INTERVAL=300
# default account which will be created in migrations
DEFAULT_USERNAME=patrick115
DEFAULT_PASSWORD=test123
HASH_ROUNDS=12
# folder for uploaded images
FILE_FOLDER=./uploads
MAX_FILE_SIZE=104857600
BODY_SIZE_LIMIT=104857600
319 changes: 319 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
## 🧠 Svelte 5 + TailwindCSS 4: Copilot Coding Guide

Use the following patterns to ensure consistency across components. These examples define the **expected structure**, especially for `$props()`, `twMerge`, runes, and children rendering.

---

### 🟣 Runes Instead of Legacy Syntax

Always use Svelte 5 runes:

```ts
// ✅ Access props
const { label }: InputProps = $props();

// ✅ Local state
const count = $state(0);

// ✅ Reactivity
$effect(() => {
console.log(count);
});

// ✅ Derived value
const doubled = $derived(() => count * 2);

// ✅ Bindable value
const { value = $bindable('') }: { value: string } = $props();
```

Avoid legacy syntax:

```ts
// ❌ Don't use export let
export let label: string;

// ❌ Don't use $:
$: something = ...
```

---

### 🔡 Prop Typing and Usage

Always define a named prop type. Avoid inline types inside `$props()`:

```ts
type ButtonProps = {
label: string;
onClick?: () => void;
};

const { label, onClick }: ButtonProps = $props();
```

---

### 🧩 Extending HTML Elements

When wrapping native elements like `<input>`, use `SvelteHTMLElements`:

```ts
import type { SvelteHTMLElements } from 'svelte/elements';

type InputProps = {
label: string;
} & SvelteHTMLElements['input'];

const { label, class: cls = '', ...props }: InputProps = $props();
```

Don’t re-declare built-in HTML attributes (like `value`, `name`, or `children`). They're already included.

```ts
// ❌ Don't do this:
type Bad = {
value?: string;
name?: string;
} & SvelteHTMLElements['input'];
```

---

### 🔄 Bindable Props

For bindable values (e.g. `bind:value`), use `$bindable()`:

```ts
const { value = $bindable('') }: { value: string } = $props();
```

Or when combining with other props:

```ts
const { value = $bindable(''), class: cls = '', ...props }: InputProps = $props();
```

---

### 🧱 Tailwind Class Merging

Use `twMerge` to merge Tailwind classes:

```ts
import { twMerge } from "tailwind-merge";

const { class: cls = "" } = $props();

<input class={twMerge("px-3 py-2 border rounded", cls)} />
```

Avoid manual concatenation:

```ts
// ❌ Don't do this:
class={"base " + cls}
```

---

### 🧒 Children Rendering and Snippets

Use `@render` for rendering children:

```svelte
{@render children?.()}
```

Children are either passed inline:

```svelte
<Select>
<option value="a">A</option>
<option value="b">B</option>
</Select>
```

Or wrapped in a named snippet:

```svelte
<Select>
{#snippet children()}
<option value="a">A</option>
<option value="b">B</option>
{/snippet}
</Select>
```

Never use unnamed snippet blocks:

```svelte
// ❌ Invalid
{#snippet}
<option>A</option>
{/snippet}
```

Do not declare `children?: Snippet` if it is already part of the extended HTML element type.

---

### ✅ Summary Cheat Sheet

- Always use `$props()`, `$bindable()`, `$state()`, `$effect()`, `$derived()`
- Avoid `export let`, `$:`, and `<slot>`
- Type props with `ComponentNameProps`
- Extend HTML props with `SvelteHTMLElements['tag']`
- Don’t re-declare built-in HTML attributes like `value`, `name`, or `children`
- Use `twMerge()` for class merging
- Render children using `@render children?.()`
- Never generate `{#snippet}` without a name

---

# Project Architecture

## Overview

This project is a web application built using **SvelteKit** (Svelte 5) with the **Node.js adapter**. It uses **MySQL** as the database, managed by **Kysely** query builder. The frontend is styled with **TailwindCSS 4**.

## Tech Stack

### Core Framework

- **SvelteKit**: Full-stack framework using File-System Based Routing.
- **Svelte 5**: Utilizing Runes system (`$state`, `$props`, `$derived`, `$effect`) for reactivity.
- **Vite**: Build tool for fast HMR and bundling.
- **TypeScript**: Strictly typed development.

### Database & Backend

- **MySQL**: Relational database (driver: `mysql2`).
- **Kysely**: Type-safe SQL query builder.
- **Kysely Codegen**: Generates TypeScript interfaces from the live database schema (DB First approach).
- **Core Library**: `@patrick115/sveltekitapi` (Custom wrapper for type-safe API, Router, and Procedure handling).
- **Auth**: `jsonwebtoken` (JWT) for session management & `bcrypt` for password hasing.
- **Zod**: Schema validation for API inputs and environment variables.

### Styling & UI

- **TailwindCSS 4**: Utility-first CSS framework.
- **Bootstrap Icons**: Iconography.
- **SweetAlert2**: Modal popups and alerts.
- **Chart.js**: Data visualization.

### Utilities

- **Marked**: Markdown parsing for rendering articles.
- **Sharp**: High-performance image processing (resizing, format conversion).
- **Dotenv**: Environment variable management.

## Project Structure

### `/src`

The source code and logic of the application.

- **`lib/`**: Shared library code, accesible via import alias `$lib/` or `$/`.

- **`server/`**: **Server-side only** code. Can strictly be imported in `+page.server.ts`, `+server.ts`, etc.
- `api.ts`: Helper to create type-safe API definitions.
- `context.ts`: Defines the request context (authentication state, database connection, etc.).
- `cookies/`: Helper class `JWTCookies` for managing secure HTTP-only cookies.
- `routes.ts`: Main API router definition/aggregate.
- `server.ts`: Initializes the `APIServer` instance with the router and context.
- `variables.ts`: **Source of Truth** for server configuration. Initializes:
- `conn`: The Kysely MySQL connection instance.
- `jwt`: JWT configuration.
- Loads environment variables (`$env/static/private`).
- **`components/`**: Reusable Svelte UI components.
- **`lang/`**: Internationalization (i18n) logic.
- `index.ts`: Exports available languages and helper functions for translation resolution alongside `getPath` for localized routing.
- `state.svelte.ts`: **Global Client State**. Uses Svelte 5 runes (`$state`) to manage:
- `lang`: Current language dictionary.
- `selectedLang`: Current language key (e.g., 'en', 'cs').
- `userState`: Logged-in user information.
- **`types/`**: Application-wide TypeScript definitions.
- `database.ts`: **Autogenerated** Kysely database types. Reflects the actual DB schema handles by `pnpm genDatabaseSchema`.
- `schemes.ts`: Zod schemas for validation.

- **`routes/`**: File-system based routing.
- **`[[lang=lang]]/`**: Main application routes wrapped in an optional language parameter.
- Allows routes like `/about` (default lang) and `/cs/about` (explicit lang).
- Contains sub-routes: `admin/`, `gallery/`, `about/`, `contact/`.
- **`api/[...data]/`**: Catch-all API endpoint.
- Takes all requests starting with `/api/`.
- Delegates processing to `Server.handler` defined in `src/lib/server/server.ts`.
- This creates a centralized entry point for the type-safe API.
- **`image/[name]/`**: Image serving endpoint.
- Likely processes/serves images dynamically (e.g., resizing or retrieving from storage).

### `/migrations`

Contains database migration files written in TypeScript.

- Using a custom migration runner (`script/runMigration.ts`).
- Migrations are timestamped (e.g., `20250504223140_logging.ts`).
- Tracks history to ensure the database schema is consistent across environments.

### `/script`

Utility scripts for maintenance.

- `createMigration.sh`: Helper to scaffold a new migration file.
- `runMigration.ts`: The runner script for executing migrations (up/down).

### `/uploads`

Storage directory for user-uploaded content (images, scripts, etc.), often excluded from version control.

## Implementation Details

### State Management (Client)

State is managed globally via `src/lib/state.svelte.ts`. It exports a reactive `state` object created with `$state()` rune. Components can import getters/setters to react to changes in:

- Language (`lang`)
- User Authentication (`userState`)

### API Architecture

The project uses a TRPC-like pattern via `@patrick115/sveltekitapi`:

1. **Context**: Created in `context.ts`, checking headers/cookies for JWT to determine `logged` status.
2. **Procedures**: Defined in `api.ts`.
- `procedure`: Public endpoint.
- `loggedProcedure`: Protected endpoint (throws 401 if not logged in).
3. **Router**: Multiple procedures are bundled into a router (`routes.ts`).
4. **Handling**: `src/routes/api/[...data]/+server.ts` maps HTTP methods (GET, POST, etc.) to the `Server.handler`.

### Internationalization (i18n)

- **URL Strategy**: Uses the `[[lang=lang]]` param matcher.
- **Dictionary**: Loaded from `src/lib/lang/`.
- **Resolution**: `resolveTranslation` function recursively looks up keys in the language object.

## Useful Commands

These commands are defined in `package.json` for development and maintenance.

### Development

- `pnpm dev`: Start the development server.
- `pnpm build`: Build the application for production.
- `pnpm preview`: Preview the production build locally.
- `pnpm check`: Run Svelte-check (TypeScript validation).
- `pnpm lint`: Run ESLint and Prettier checks.
- `pnpm format`: Automatically format code with Prettier.

### Database

- `pnpm genDatabaseSchema`: Introspect the database and regenerate TypeScript definitions in `src/types/database.ts`. **Run this after applying migrations.**
- `pnpm migration:create`: Create a new empty migration file in `migrations/` (prompts for name).
- `pnpm migrate:up`: Apply pending migrations.
- `pnpm migrate:down`: Revert the last batch of migrations.
- `pnpm migrate`: Run migrations (alias for checking status/running).

### Deployment

- `pnpm start`: Start the built Node.js server (requires `pnpm build` first).
Loading
Loading