diff --git a/README.md b/README.md
index 8858c65..d931122 100644
--- a/README.md
+++ b/README.md
@@ -113,3 +113,47 @@ sudo iptables-restore < /etc/iptables/rules.v4
```
[Credits](https://github.com/canonical/microk8s/issues/854#issuecomment-1716576495)
+
+# Welcome
+
+## What is this website about?
+
+This website is a place where I test out new concepts and technologies that interest me. While I don't focus on the
+visual or responsive part of the website, I do aim to learn as much as possible from each project.
+
+## What is the technology stack?
+
+Here are the base frameworks used for this:
+
+- Backend: Spring Boot
+- API: GraphQL
+- Frontend: Sveltekit
+
+In the lower section, you will find the packages or dependencies used.
+
+## What's working?
+
+Currently, this machine is running in the Oracle Cloud on an always-free VM. I set up a microk8s cluster which features:
+
+- TLS certificate fetching via Let's Encrypt ACME
+- SSR rendering with direct connection via service discovery
+- Redis for temporary data
+
+As full-stack features, there is currently only the live chat. There is definitely more to come.
+
+## What's coming?
+
+There is a lot of stuff planned for this.
+
+Currently, the focus is set to:
+
+- OAuth 2 via Spring
+- Remote Kubernetes rollout without SSH
+
+## Dependencies
+
+- Backend
+ - Netflix DGS
+- Frontend
+ - Houdini GraphQL
+ - Shadcn Svelte
\ No newline at end of file
diff --git a/frontend/package.json b/frontend/package.json
index 38478ff..c327bcf 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -18,6 +18,7 @@
"@sveltejs/adapter-node": "^2.0.2",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
+ "@tailwindcss/typography": "^0.5.10",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"autoprefixer": "^10.4.16",
@@ -45,6 +46,7 @@
"clsx": "^2.0.0",
"graphql-ws": "^5.14.3",
"lucide-svelte": "^0.302.0",
+ "mode-watcher": "^0.1.2",
"tailwind-merge": "^2.2.0",
"tailwind-variants": "^0.1.19"
}
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index d1e1d1a..c0e59d6 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -17,6 +17,9 @@ dependencies:
lucide-svelte:
specifier: ^0.302.0
version: 0.302.0(svelte@4.2.8)
+ mode-watcher:
+ specifier: ^0.1.2
+ version: 0.1.2(svelte@4.2.8)
tailwind-merge:
specifier: ^2.2.0
version: 2.2.0
@@ -37,6 +40,9 @@ devDependencies:
'@sveltejs/vite-plugin-svelte':
specifier: ^3.0.0
version: 3.0.1(svelte@4.2.8)(vite@5.0.10)
+ '@tailwindcss/typography':
+ specifier: ^0.5.10
+ version: 0.5.10(tailwindcss@3.4.0)
'@typescript-eslint/eslint-plugin':
specifier: ^6.0.0
version: 6.15.0(@typescript-eslint/parser@6.15.0)(eslint@8.56.0)(typescript@5.3.3)
@@ -1210,6 +1216,18 @@ packages:
tslib: 2.6.2
dev: false
+ /@tailwindcss/typography@0.5.10(tailwindcss@3.4.0):
+ resolution: {integrity: sha512-Pe8BuPJQJd3FfRnm6H0ulKIGoMEQS+Vq01R6M5aCrFB/ccR/shT+0kXLjouGC1gFLm9hopTFN+DMP0pfwRWzPw==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders'
+ dependencies:
+ lodash.castarray: 4.4.0
+ lodash.isplainobject: 4.0.6
+ lodash.merge: 4.6.2
+ postcss-selector-parser: 6.0.10
+ tailwindcss: 3.4.0
+ dev: true
+
/@types/braces@3.0.4:
resolution: {integrity: sha512-0WR3b8eaISjEW7RpZnclONaLFDf7buaowRHdqLp4vLj54AsSAYWfh3DRbfiYJY9XDxMgx1B4sE1Afw2PGpuHOA==}
dev: true
@@ -2780,6 +2798,14 @@ packages:
p-locate: 5.0.0
dev: true
+ /lodash.castarray@4.4.0:
+ resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
+ dev: true
+
+ /lodash.isplainobject@4.0.6:
+ resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+ dev: true
+
/lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
dev: true
@@ -2893,6 +2919,14 @@ packages:
ufo: 1.3.2
dev: true
+ /mode-watcher@0.1.2(svelte@4.2.8):
+ resolution: {integrity: sha512-XTdPCdqC3kqSvB+Q262Kor983YJkkB2Z3vj9uqg5IqKQpOdiz+xB99Jihp8sWbyM67drC7KKp0Nt5FzCypZi2g==}
+ peerDependencies:
+ svelte: ^4.0.0
+ dependencies:
+ svelte: 4.2.8
+ dev: false
+
/mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -3256,6 +3290,14 @@ packages:
postcss: 8.4.32
dev: true
+ /postcss-selector-parser@6.0.10:
+ resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+ dev: true
+
/postcss-selector-parser@6.0.13:
resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==}
engines: {node: '>=4'}
diff --git a/frontend/schema.graphql b/frontend/schema.graphql
index 8ebc618..4e5199e 100644
--- a/frontend/schema.graphql
+++ b/frontend/schema.graphql
@@ -4,9 +4,7 @@ directive @external on FIELD_DEFINITION
directive @key(fields: _FieldSet!) on INTERFACE | OBJECT
-"""
-Indicates an Input Object is a OneOf Input Object.
-"""
+"""Indicates an Input Object is a OneOf Input Object."""
directive @oneOf on INPUT_OBJECT
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
@@ -14,291 +12,290 @@ directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
enum ErrorDetail {
- """
- The deadline expired before the operation could complete.
-
- For operations that change the state of the system, this error
- may be returned even if the operation has completed successfully.
- For example, a successful response from a server could have been
- delayed long enough for the deadline to expire.
-
- HTTP Mapping: 504 Gateway Timeout
- Error Type: UNAVAILABLE
- """
- DEADLINE_EXCEEDED
-
- """
- The server detected that the client is exhibiting a behavior that
- might be generating excessive load.
-
- HTTP Mapping: 429 Too Many Requests or 420 Enhance Your Calm
- Error Type: UNAVAILABLE
- """
- ENHANCE_YOUR_CALM
-
- """
- The requested field is not found in the schema.
-
- This differs from `NOT_FOUND` in that `NOT_FOUND` should be used when a
- query is valid, but is unable to return a result (if, for example, a
- specific video id doesn't exist). `FIELD_NOT_FOUND` is intended to be
- returned by the server to signify that the requested field is not known to exist.
- This may be returned in lieu of failing the entire query.
- See also `PERMISSION_DENIED` for cases where the
- requested field is invalid only for the given user or class of users.
-
- HTTP Mapping: 404 Not Found
- Error Type: BAD_REQUEST
- """
- FIELD_NOT_FOUND
-
- """
- The client specified an invalid argument.
-
- Note that this differs from `FAILED_PRECONDITION`.
- `INVALID_ARGUMENT` indicates arguments that are problematic
- regardless of the state of the system (e.g., a malformed file name).
-
- HTTP Mapping: 400 Bad Request
- Error Type: BAD_REQUEST
- """
- INVALID_ARGUMENT
-
- """
- The provided cursor is not valid.
-
- The most common usage for this error is when a client is paginating
- through a list that uses stateful cursors. In that case, the provided
- cursor may be expired.
-
- HTTP Mapping: 404 Not Found
- Error Type: NOT_FOUND
- """
- INVALID_CURSOR
-
- """
- Unable to perform operation because a required resource is missing.
-
- Example: Client is attempting to refresh a list, but the specified
- list is expired. This requires an action by the client to get a new list.
-
- If the user is simply trying GET a resource that is not found,
- use the NOT_FOUND error type. FAILED_PRECONDITION.MISSING_RESOURCE
- is to be used particularly when the user is performing an operation
- that requires a particular resource to exist.
-
- HTTP Mapping: 400 Bad Request or 500 Internal Server Error
- Error Type: FAILED_PRECONDITION
- """
- MISSING_RESOURCE
-
- """
- Service Error.
-
- There is a problem with an upstream service.
-
- This may be returned if a gateway receives an unknown error from a service
- or if a service is unreachable.
- If a request times out which waiting on a response from a service,
- `DEADLINE_EXCEEDED` may be returned instead.
- If a service returns a more specific error Type, the specific error Type may
- be returned instead.
-
- HTTP Mapping: 502 Bad Gateway
- Error Type: UNAVAILABLE
- """
- SERVICE_ERROR
-
- """
- Request failed due to network errors.
-
- HTTP Mapping: 503 Unavailable
- Error Type: UNAVAILABLE
- """
- TCP_FAILURE
-
- """
- Request throttled based on server concurrency limits.
-
- HTTP Mapping: 503 Unavailable
- Error Type: UNAVAILABLE
- """
- THROTTLED_CONCURRENCY
-
- """
- Request throttled based on server CPU limits
-
- HTTP Mapping: 503 Unavailable.
- Error Type: UNAVAILABLE
- """
- THROTTLED_CPU
-
- """
- The operation is not implemented or is not currently supported/enabled.
-
- HTTP Mapping: 501 Not Implemented
- Error Type: BAD_REQUEST
- """
- UNIMPLEMENTED
-
- """
- Unknown error.
-
- This error should only be returned when no other error detail applies.
- If a client sees an unknown errorDetail, it will be interpreted as UNKNOWN.
-
- HTTP Mapping: 500 Internal Server Error
- """
- UNKNOWN
+ """
+ The deadline expired before the operation could complete.
+
+ For operations that change the state of the system, this error
+ may be returned even if the operation has completed successfully.
+ For example, a successful response from a server could have been
+ delayed long enough for the deadline to expire.
+
+ HTTP Mapping: 504 Gateway Timeout
+ Error Type: UNAVAILABLE
+ """
+ DEADLINE_EXCEEDED
+
+ """
+ The server detected that the client is exhibiting a behavior that
+ might be generating excessive load.
+
+ HTTP Mapping: 429 Too Many Requests or 420 Enhance Your Calm
+ Error Type: UNAVAILABLE
+ """
+ ENHANCE_YOUR_CALM
+
+ """
+ The requested field is not found in the schema.
+
+ This differs from `NOT_FOUND` in that `NOT_FOUND` should be used when a
+ query is valid, but is unable to return a result (if, for example, a
+ specific video id doesn't exist). `FIELD_NOT_FOUND` is intended to be
+ returned by the server to signify that the requested field is not known to exist.
+ This may be returned in lieu of failing the entire query.
+ See also `PERMISSION_DENIED` for cases where the
+ requested field is invalid only for the given user or class of users.
+
+ HTTP Mapping: 404 Not Found
+ Error Type: BAD_REQUEST
+ """
+ FIELD_NOT_FOUND
+
+ """
+ The client specified an invalid argument.
+
+ Note that this differs from `FAILED_PRECONDITION`.
+ `INVALID_ARGUMENT` indicates arguments that are problematic
+ regardless of the state of the system (e.g., a malformed file name).
+
+ HTTP Mapping: 400 Bad Request
+ Error Type: BAD_REQUEST
+ """
+ INVALID_ARGUMENT
+
+ """
+ The provided cursor is not valid.
+
+ The most common usage for this error is when a client is paginating
+ through a list that uses stateful cursors. In that case, the provided
+ cursor may be expired.
+
+ HTTP Mapping: 404 Not Found
+ Error Type: NOT_FOUND
+ """
+ INVALID_CURSOR
+
+ """
+ Unable to perform operation because a required resource is missing.
+
+ Example: Client is attempting to refresh a list, but the specified
+ list is expired. This requires an action by the client to get a new list.
+
+ If the user is simply trying GET a resource that is not found,
+ use the NOT_FOUND error type. FAILED_PRECONDITION.MISSING_RESOURCE
+ is to be used particularly when the user is performing an operation
+ that requires a particular resource to exist.
+
+ HTTP Mapping: 400 Bad Request or 500 Internal Server Error
+ Error Type: FAILED_PRECONDITION
+ """
+ MISSING_RESOURCE
+
+ """
+ Service Error.
+
+ There is a problem with an upstream service.
+
+ This may be returned if a gateway receives an unknown error from a service
+ or if a service is unreachable.
+ If a request times out which waiting on a response from a service,
+ `DEADLINE_EXCEEDED` may be returned instead.
+ If a service returns a more specific error Type, the specific error Type may
+ be returned instead.
+
+ HTTP Mapping: 502 Bad Gateway
+ Error Type: UNAVAILABLE
+ """
+ SERVICE_ERROR
+
+ """
+ Request failed due to network errors.
+
+ HTTP Mapping: 503 Unavailable
+ Error Type: UNAVAILABLE
+ """
+ TCP_FAILURE
+
+ """
+ Request throttled based on server concurrency limits.
+
+ HTTP Mapping: 503 Unavailable
+ Error Type: UNAVAILABLE
+ """
+ THROTTLED_CONCURRENCY
+
+ """
+ Request throttled based on server CPU limits
+
+ HTTP Mapping: 503 Unavailable.
+ Error Type: UNAVAILABLE
+ """
+ THROTTLED_CPU
+
+ """
+ The operation is not implemented or is not currently supported/enabled.
+
+ HTTP Mapping: 501 Not Implemented
+ Error Type: BAD_REQUEST
+ """
+ UNIMPLEMENTED
+
+ """
+ Unknown error.
+
+ This error should only be returned when no other error detail applies.
+ If a client sees an unknown errorDetail, it will be interpreted as UNKNOWN.
+
+ HTTP Mapping: 500 Internal Server Error
+ """
+ UNKNOWN
}
enum ErrorType {
- """
- Bad Request.
-
- There is a problem with the request.
- Retrying the same request is not likely to succeed.
- An example would be a query or argument that cannot be deserialized.
-
- HTTP Mapping: 400 Bad Request
- """
- BAD_REQUEST
-
- """
- The operation was rejected because the system is not in a state
- required for the operation's execution. For example, the directory
- to be deleted is non-empty, an rmdir operation is applied to
- a non-directory, etc.
-
- Service implementers can use the following guidelines to decide
- between `FAILED_PRECONDITION` and `UNAVAILABLE`:
-
- - Use `UNAVAILABLE` if the client can retry just the failing call.
- - Use `FAILED_PRECONDITION` if the client should not retry until
- the system state has been explicitly fixed. E.g., if an "rmdir"
- fails because the directory is non-empty, `FAILED_PRECONDITION`
- should be returned since the client should not retry unless
- the files are deleted from the directory.
-
- HTTP Mapping: 400 Bad Request or 500 Internal Server Error
- """
- FAILED_PRECONDITION
-
- """
- Internal error.
-
- An unexpected internal error was encountered. This means that some
- invariants expected by the underlying system have been broken.
- This error code is reserved for serious errors.
-
- HTTP Mapping: 500 Internal Server Error
- """
- INTERNAL
-
- """
- The requested entity was not found.
-
- This could apply to a resource that has never existed (e.g. bad resource id),
- or a resource that no longer exists (e.g. cache expired.)
-
- Note to server developers: if a request is denied for an entire class
- of users, such as gradual feature rollout or undocumented allowlist,
- `NOT_FOUND` may be used. If a request is denied for some users within
- a class of users, such as user-based access control, `PERMISSION_DENIED`
- must be used.
-
- HTTP Mapping: 404 Not Found
- """
- NOT_FOUND
-
- """
- The caller does not have permission to execute the specified
- operation.
-
- `PERMISSION_DENIED` must not be used for rejections
- caused by exhausting some resource or quota.
- `PERMISSION_DENIED` must not be used if the caller
- cannot be identified (use `UNAUTHENTICATED`
- instead for those errors).
-
- This error Type does not imply the
- request is valid or the requested entity exists or satisfies
- other pre-conditions.
-
- HTTP Mapping: 403 Forbidden
- """
- PERMISSION_DENIED
-
- """
- The request does not have valid authentication credentials.
-
- This is intended to be returned only for routes that require
- authentication.
-
- HTTP Mapping: 401 Unauthorized
- """
- UNAUTHENTICATED
-
- """
- Currently Unavailable.
-
- The service is currently unavailable. This is most likely a
- transient condition, which can be corrected by retrying with
- a backoff.
-
- HTTP Mapping: 503 Unavailable
- """
- UNAVAILABLE
-
- """
- Unknown error.
-
- For example, this error may be returned when
- an error code received from another address space belongs to
- an error space that is not known in this address space. Also
- errors raised by APIs that do not return enough error information
- may be converted to this error.
-
- If a client sees an unknown errorType, it will be interpreted as UNKNOWN.
- Unknown errors MUST NOT trigger any special behavior. These MAY be treated
- by an implementation as being equivalent to INTERNAL.
-
- When possible, a more specific error should be provided.
-
- HTTP Mapping: 520 Unknown Error
- """
- UNKNOWN
+ """
+ Bad Request.
+
+ There is a problem with the request.
+ Retrying the same request is not likely to succeed.
+ An example would be a query or argument that cannot be deserialized.
+
+ HTTP Mapping: 400 Bad Request
+ """
+ BAD_REQUEST
+
+ """
+ The operation was rejected because the system is not in a state
+ required for the operation's execution. For example, the directory
+ to be deleted is non-empty, an rmdir operation is applied to
+ a non-directory, etc.
+
+ Service implementers can use the following guidelines to decide
+ between `FAILED_PRECONDITION` and `UNAVAILABLE`:
+
+ - Use `UNAVAILABLE` if the client can retry just the failing call.
+ - Use `FAILED_PRECONDITION` if the client should not retry until
+ the system state has been explicitly fixed. E.g., if an "rmdir"
+ fails because the directory is non-empty, `FAILED_PRECONDITION`
+ should be returned since the client should not retry unless
+ the files are deleted from the directory.
+
+ HTTP Mapping: 400 Bad Request or 500 Internal Server Error
+ """
+ FAILED_PRECONDITION
+
+ """
+ Internal error.
+
+ An unexpected internal error was encountered. This means that some
+ invariants expected by the underlying system have been broken.
+ This error code is reserved for serious errors.
+
+ HTTP Mapping: 500 Internal Server Error
+ """
+ INTERNAL
+
+ """
+ The requested entity was not found.
+
+ This could apply to a resource that has never existed (e.g. bad resource id),
+ or a resource that no longer exists (e.g. cache expired.)
+
+ Note to server developers: if a request is denied for an entire class
+ of users, such as gradual feature rollout or undocumented allowlist,
+ `NOT_FOUND` may be used. If a request is denied for some users within
+ a class of users, such as user-based access control, `PERMISSION_DENIED`
+ must be used.
+
+ HTTP Mapping: 404 Not Found
+ """
+ NOT_FOUND
+
+ """
+ The caller does not have permission to execute the specified
+ operation.
+
+ `PERMISSION_DENIED` must not be used for rejections
+ caused by exhausting some resource or quota.
+ `PERMISSION_DENIED` must not be used if the caller
+ cannot be identified (use `UNAUTHENTICATED`
+ instead for those errors).
+
+ This error Type does not imply the
+ request is valid or the requested entity exists or satisfies
+ other pre-conditions.
+
+ HTTP Mapping: 403 Forbidden
+ """
+ PERMISSION_DENIED
+
+ """
+ The request does not have valid authentication credentials.
+
+ This is intended to be returned only for routes that require
+ authentication.
+
+ HTTP Mapping: 401 Unauthorized
+ """
+ UNAUTHENTICATED
+
+ """
+ Currently Unavailable.
+
+ The service is currently unavailable. This is most likely a
+ transient condition, which can be corrected by retrying with
+ a backoff.
+
+ HTTP Mapping: 503 Unavailable
+ """
+ UNAVAILABLE
+
+ """
+ Unknown error.
+
+ For example, this error may be returned when
+ an error code received from another address space belongs to
+ an error space that is not known in this address space. Also
+ errors raised by APIs that do not return enough error information
+ may be converted to this error.
+
+ If a client sees an unknown errorType, it will be interpreted as UNKNOWN.
+ Unknown errors MUST NOT trigger any special behavior. These MAY be treated
+ by an implementation as being equivalent to INTERNAL.
+
+ When possible, a more specific error should be provided.
+
+ HTTP Mapping: 520 Unknown Error
+ """
+ UNKNOWN
}
type Message {
- creator: String!
- id: ID!
- text: String!
- timestamp: String!
+ creator: String!
+ id: ID!
+ text: String!
+ timestamp: String!
}
input MessageInput {
- creator: String!
- text: String!
+ creator: String!
+ text: String!
}
type Mutation {
- messageSend(input: MessageInput!): Message!
+ messageSend(input: MessageInput!): Message!
}
type Query {
- _service: _Service!
- messages: [Message!]!
+ _service: _Service!
+ messages: [Message!]!
}
type Subscription {
- messageSent: Message!
+ messageSent: Message!
}
-"""
-"""
+""""""
scalar _FieldSet
type _Service {
- sdl: String!
+ sdl: String!
}
diff --git a/frontend/src/app.html b/frontend/src/app.html
index f273cc5..0c70a0f 100644
--- a/frontend/src/app.html
+++ b/frontend/src/app.html
@@ -3,6 +3,7 @@
+
%sveltekit.head%
diff --git a/frontend/src/lib/SiteFooter.svelte b/frontend/src/lib/SiteFooter.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/lib/SiteHeader.svelte b/frontend/src/lib/SiteHeader.svelte
new file mode 100644
index 0000000..5512169
--- /dev/null
+++ b/frontend/src/lib/SiteHeader.svelte
@@ -0,0 +1,46 @@
+
+
+
+
diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte
new file mode 100644
index 0000000..1c6afd2
--- /dev/null
+++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte
new file mode 100644
index 0000000..347119a
--- /dev/null
+++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
new file mode 100644
index 0000000..fb4dc59
--- /dev/null
+++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/frontend/src/lib/components/ui/alert-dialog/index.ts b/frontend/src/lib/components/ui/alert-dialog/index.ts
new file mode 100644
index 0000000..0cf3d72
--- /dev/null
+++ b/frontend/src/lib/components/ui/alert-dialog/index.ts
@@ -0,0 +1,40 @@
+import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
+
+const Root = AlertDialogPrimitive.Root;
+const Trigger = AlertDialogPrimitive.Trigger;
+
+import Title from './alert-dialog-title.svelte';
+import Action from './alert-dialog-action.svelte';
+import Cancel from './alert-dialog-cancel.svelte';
+import Portal from './alert-dialog-portal.svelte';
+import Footer from './alert-dialog-footer.svelte';
+import Header from './alert-dialog-header.svelte';
+import Overlay from './alert-dialog-overlay.svelte';
+import Content from './alert-dialog-content.svelte';
+import Description from './alert-dialog-description.svelte';
+
+export {
+ Root,
+ Title,
+ Action,
+ Cancel,
+ Portal,
+ Footer,
+ Header,
+ Trigger,
+ Overlay,
+ Content,
+ Description,
+ //
+ Root as AlertDialog,
+ Title as AlertDialogTitle,
+ Action as AlertDialogAction,
+ Cancel as AlertDialogCancel,
+ Portal as AlertDialogPortal,
+ Footer as AlertDialogFooter,
+ Header as AlertDialogHeader,
+ Trigger as AlertDialogTrigger,
+ Overlay as AlertDialogOverlay,
+ Content as AlertDialogContent,
+ Description as AlertDialogDescription
+};
diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte
index bf1faec..d841503 100644
--- a/frontend/src/routes/+layout.svelte
+++ b/frontend/src/routes/+layout.svelte
@@ -1,5 +1,8 @@
@@ -11,4 +14,11 @@
-
+
+
+
+
+
+
+
+
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index 1de02f6..f36674f 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -1,89 +1,53 @@
-
-
-
-
-
- Please enter your username
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {#each $AllMessage.data?.messages || [] as message (message.id)}
-
-
-
-
{message.text}
-
-{message.creator} at {message.timestamp}
-
-
- {/each}
-
-
-
-
-
-
-
-
-
-
+
+
Welcome
+
What is this website about?
+
+ This website is a place where I test out new concepts and technologies that interest me. While I
+ don't focus on the visual or responsive part of the website, I do aim to learn as much as
+ possible from each project.
+
+
What is the technology stack?
+
Here are the base frameworks used for this:
+
+
Backend: Spring Boot
+
API: GraphQL
+
Frontend: Sveltekit
+
+
In the lower section, you will find the packages or dependencies used.
+
What's working?
+
+ Currently, this machine is running in the Oracle Cloud on an always-free VM. I set up a microk8s
+ cluster which features:
+
+
+
TLS certificate fetching via Let's Encrypt ACME
+
SSR rendering with direct connection via service discovery
+
Redis for temporary data
+
+
+ As full-stack features, there is currently only the live chat. There is definitely more to come.
+
+
What's coming?
+
There is a lot of stuff planned for this.
+
Currently, the focus is set to:
+
+
OAuth 2 via Spring
+
Remote Kubernetes rollout without SSH
+
+
Dependencies
+
+
+ Backend
+
+
Netflix DGS
+
+
+
+ Frontend
+
+
Houdini GraphQL
+
Shadcn Svelte
+
+
+
+
diff --git a/frontend/src/routes/+page.gql b/frontend/src/routes/chat/+page.gql
similarity index 100%
rename from frontend/src/routes/+page.gql
rename to frontend/src/routes/chat/+page.gql
diff --git a/frontend/src/routes/chat/+page.svelte b/frontend/src/routes/chat/+page.svelte
new file mode 100644
index 0000000..a1d1691
--- /dev/null
+++ b/frontend/src/routes/chat/+page.svelte
@@ -0,0 +1,85 @@
+
+
+
+
+
+ Please enter your username
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#each $AllMessage.data?.messages || [] as message (message.id)}
+
+
+
+
{message.text}
+
+ {message.creator} at {new Date(message.timestamp).toLocaleString('en-US')}
+
+
+
+ {/each}
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte
new file mode 100644
index 0000000..3c3087d
--- /dev/null
+++ b/frontend/src/routes/login/+page.svelte
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ Under Construction
+
+
+
+ This feature is currently under development. Although you cannot log in at the moment, this
+ functionality will be available in the future. Stay tuned for updates!
+
+
+
+
+
+
+
+
+
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index 38fb24e..6d6524f 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -58,7 +58,8 @@ const config = {
sans: [...fontFamily.sans]
}
}
- }
+ },
+ plugins: [require('@tailwindcss/typography')]
};
export default config;