Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/nikoheikkila/photo-browser

A modern frontend application architecture built with SvelteKit and Hexagonal / Clean Architecture principles
https://github.com/nikoheikkila/photo-browser

clean-architecture dracula hexagonal-architecture playwright svelte sveltekit typescript vite vitest zod

Last synced: 3 months ago
JSON representation

A modern frontend application architecture built with SvelteKit and Hexagonal / Clean Architecture principles

Awesome Lists containing this project

README

        

# 🌅 SvelteKit Photo Browser 🌉

A website for browsing photos and albums delivered via Typicode API.

The real purpose of this project is to demonstrate building a modern frontend application architecture with **SvelteKit** and **Hexagonal / Clean Architecture** principles.

## Clean Frontend Architecture with SvelteKit

Read [the guide](https://nikoheikkila.fi/blog/clean-frontend-architecture-with-sveltekit) in my blog where I'm building the application and explaining the design process behind it.

## Demo

See the demo application on [**Netlify**](https://sveltekit-photo-browser.netlify.app/).

## Instructions

1. Install [Task](https://taskfile.dev/installation)
2. Install project dependencies with `task install`
3. Run application development mode with `task dev`
4. Make changes
5. Run tests with `task test`

## Architecture

Overview of the software architecture and design is visualised in a Mermaid diagram below.

```mermaid
classDiagram
direction

class SvelteKit {
<>
}

class Layout {
load(LayoutParams params) LayoutData
}

class Page {
ssr : boolean
csr : boolean
load(RouteParams params) PageData
}

class Component
class Script
class HTML
class Style

class PhotoBrowser {
<>
withLimit(int limit) self
loadPhotos() Array~Photo~
loadPhoto(int id) Photo
loadFromAlbum(int albumId) Array~Photo~
groupPhotosByAlbum() Array~Album~
}

class PhotoCalculator {
<>
parseFullSize() Tuple~int~
parseThumbnailSize() Tuple~int~
}

class Photo {
<>
id : int
albumId : int
title : string
url : URL
thumbnailUrl : URL
}

class PhotoGateway~T~ {
<>
fetchPhotos(FetchParams args) Array~T~
fetchPhoto(int id) T
fetchPhotosByAlbumId(int albumId, FetchParams params) Dictionary~T~
}

class APIGateway~T~ {
<>
}

class Typicode {
<>
}

class Vitest {
<>
}

class FakeGateway~T~ {
<>
}

class FakerJS {
<>
}

SvelteKit "1" --> "1" PhotoBrowser : uses
SvelteKit "1" --> "1" PhotoCalculator : uses
SvelteKit "1" --> "1" Layout : loads
Layout "1" --> "*" Page : contains
Page "1" --o "*" Component : renders
Component "1" --> "1" Script : contains
Component "1" --> "1" HTML : contains
Component "1" --> "1" Style : contains

PhotoBrowser --> APIGateway : uses
Vitest --> FakeGateway : uses
PhotoGateway "1" --> "*" Photo : fetches

APIGateway --|> PhotoGateway : implements
APIGateway ..> Typicode : uses
FakeGateway --|> PhotoGateway : implements
FakeGateway ..> FakerJS : uses
```