+5
assets/css/app.css
+5
assets/css/app.css
+1
assets/js/app.js
+1
assets/js/app.js
+6
-2
config/config.exs
+6
-2
config/config.exs
···
36
version: "0.25.4",
37
comet: [
38
args:
39
-
~w(js/app.js --bundle --target=es2022 --outdir=../priv/static/assets/js --external:/fonts/* --external:/images/* --alias:@=.),
40
cd: Path.expand("../assets", __DIR__),
41
env: %{"NODE_PATH" => [Path.expand("../deps", __DIR__), Mix.Project.build_path()]}
42
]
···
52
cd: Path.expand("..", __DIR__)
53
],
54
version_check: false,
55
-
path: System.get_env("TAILWINDCSS_PATH", Path.expand("../assets/node_modules/.bin/tailwindcss", __DIR__))
56
57
# Configure Elixir's Logger
58
config :logger, :default_formatter,
···
36
version: "0.25.4",
37
comet: [
38
args:
39
+
~w(js/app.js --bundle --target=es2022 --outdir=../priv/static/assets/js --external:/fonts/* --external:/images/* --loader:.woff2=file --alias:@=.),
40
cd: Path.expand("../assets", __DIR__),
41
env: %{"NODE_PATH" => [Path.expand("../deps", __DIR__), Mix.Project.build_path()]}
42
]
···
52
cd: Path.expand("..", __DIR__)
53
],
54
version_check: false,
55
+
path:
56
+
System.get_env(
57
+
"TAILWINDCSS_PATH",
58
+
Path.expand("../assets/node_modules/.bin/tailwindcss", __DIR__)
59
+
)
60
61
# Configure Elixir's Logger
62
config :logger, :default_formatter,
-16
lib/comet_app/components/post_preview.ex
-16
lib/comet_app/components/post_preview.ex
···
1
-
defmodule CometApp.Components.PostPreview do
2
-
use Hologram.Component
3
-
alias Hologram.UI.Link
4
-
5
-
prop :post, :map
6
-
7
-
def template do
8
-
~HOLO"""
9
-
<article class="post-preview">
10
-
<h2>{@post.title}</h2>
11
-
<p>{@post.excerpt}</p>
12
-
<Link to={CometApp.PostPage, id: @post.id}>Read more</Link>
13
-
</article>
14
-
"""
15
-
end
16
-
end
···
+11
lib/comet_app/components/title.ex
+11
lib/comet_app/components/title.ex
+22
-1
lib/comet_app/layouts/main.ex
+22
-1
lib/comet_app/layouts/main.ex
···
1
defmodule CometApp.MainLayout do
2
use Hologram.Component
3
4
+
alias CometApp.Components.Title
5
alias Hologram.UI.Runtime
6
+
7
+
prop :page_title, :string, default: nil
8
+
9
+
def template do
10
+
~HOLO"""
11
+
<!DOCTYPE html>
12
+
<html lang="en">
13
+
<head>
14
+
<meta charset="utf-8" />
15
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
16
+
<link rel="stylesheet" href="/assets/js/app.css" />
17
+
<link rel="stylesheet" href="/assets/css/app.css" />
18
+
<Title text={@page_title} />
19
+
<Runtime />
20
+
</head>
21
+
<body class="from-amber-900 bg-linear-to-tl to-stone-950 to-80% bg-fixed text-white p-10 w-screen h-screen flex justify-center flex-col">
22
+
<slot/>
23
+
</body>
24
+
</html>
25
+
"""
26
+
end
27
end
-18
lib/comet_app/layouts/main.holo
-18
lib/comet_app/layouts/main.holo
···
1
-
<!DOCTYPE html>
2
-
<html lang="en">
3
-
<head>
4
-
<meta charset="utf-8" />
5
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
6
-
<title>Comet App</title>
7
-
<link phx-track-static rel="stylesheet" href="/assets/css/app.css" />
8
-
<Runtime />
9
-
</head>
10
-
<body>
11
-
<nav class="bg-red-500 text-2xl">
12
-
<Link to={CometApp.HomePage}>Home</Link>
13
-
</nav>
14
-
<main>
15
-
<slot />
16
-
</main>
17
-
</body>
18
-
</html>
···
+15
-17
lib/comet_app/pages/home.ex
+15
-17
lib/comet_app/pages/home.ex
···
1
defmodule CometApp.HomePage do
2
use Hologram.Page
3
-
alias CometApp.Components.PostPreview
4
5
route "/"
6
7
-
layout CometApp.MainLayout
8
9
-
def init(_params, component, _server) do
10
-
# In real app, fetch from database
11
-
posts = [
12
-
%{id: 1, title: "First Post", excerpt: "This is my first post"},
13
-
%{id: 2, title: "Second Post", excerpt: nil}
14
-
]
15
16
-
put_state(component, :posts, posts)
17
-
end
18
19
def template do
20
~HOLO"""
21
-
<h1>Welcome to my Blog</h1>
22
-
23
-
<div class="posts">
24
-
{%for post <- @posts}
25
-
<PostPreview post={post} />
26
-
{/for}
27
-
</div>
28
"""
29
end
30
end
···
1
defmodule CometApp.HomePage do
2
use Hologram.Page
3
4
route "/"
5
6
+
layout CometApp.MainLayout, page_title: "Home"
7
8
+
# def init(_params, component, _server) do
9
+
# # In real app, fetch from database
10
+
# posts = [
11
+
# %{id: 1, title: "First Post", excerpt: "This is my first post"},
12
+
# %{id: 2, title: "Second Post", excerpt: nil}
13
+
# ]
14
15
+
# put_state(component, :posts, posts)
16
+
# end
17
18
def template do
19
~HOLO"""
20
+
<h1 class="italic text-9xl tracking-tighter leading-30 mb-10 font-thin">
21
+
<span class="font-medium">Comet</span> is the next-generation of music streaming.
22
+
</h1>
23
+
<p class="text-2xl font-light">
24
+
Powered by the AT Protocol, we're putting the power back in the hands of musicians.
25
+
</p>
26
"""
27
end
28
end
-48
lib/comet_app/pages/post_view.ex
-48
lib/comet_app/pages/post_view.ex
···
1
-
defmodule CometApp.PostPage do
2
-
use Hologram.Page
3
-
4
-
route "/posts/:id"
5
-
6
-
param :id, :integer
7
-
8
-
layout CometApp.MainLayout
9
-
10
-
def init(params, component, _server) do
11
-
# In real app, fetch from database
12
-
post = %{
13
-
id: params.id,
14
-
title: "Example Post",
15
-
content: "This is the full content...",
16
-
likes: 0
17
-
}
18
-
19
-
put_state(component, :post, post)
20
-
end
21
-
22
-
def template do
23
-
~HOLO"""
24
-
<article>
25
-
<h1>{@post.title}</h1>
26
-
<p>{@post.content}</p>
27
-
28
-
<div class="likes">
29
-
Likes: {@post.likes}
30
-
<button $click="like_post">Like</button>
31
-
</div>
32
-
</article>
33
-
"""
34
-
end
35
-
36
-
def action(:like_post, _params, component) do
37
-
# Update likes locally first for instant feedback
38
-
component
39
-
|> put_state([:post, :likes], component.state.post.likes + 1)
40
-
|> put_command(:save_like, post_id: component.state.post.id)
41
-
end
42
-
43
-
def command(:save_like, params, server) do
44
-
# In real app, save to database
45
-
IO.puts("Liked post #{params.post_id}")
46
-
server
47
-
end
48
-
end
···
+1
lib/comet_web/components/layouts/root.html.heex
+1
lib/comet_web/components/layouts/root.html.heex
···
7
<.live_title default="Comet" suffix=" · Phoenix Framework">
8
{assigns[:page_title]}
9
</.live_title>
10
+
<link phx-track-static rel="stylesheet" href={~p"/assets/js/app.css"} />
11
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
12
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"}>
13
</script>
+4
-1
package.json
+4
-1
package.json
+9
pnpm-lock.yaml
+9
pnpm-lock.yaml
···
7
importers:
8
9
.:
10
devDependencies:
11
'@tailwindcss/cli':
12
specifier: ^4.1.17
···
25
version: 5.9.3
26
27
packages:
28
29
'@jridgewell/gen-mapping@0.3.13':
30
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
···
431
hasBin: true
432
433
snapshots:
434
435
'@jridgewell/gen-mapping@0.3.13':
436
dependencies:
···
7
importers:
8
9
.:
10
+
dependencies:
11
+
'@fontsource-variable/work-sans':
12
+
specifier: ^5.2.8
13
+
version: 5.2.8
14
devDependencies:
15
'@tailwindcss/cli':
16
specifier: ^4.1.17
···
29
version: 5.9.3
30
31
packages:
32
+
33
+
'@fontsource-variable/work-sans@5.2.8':
34
+
resolution: {integrity: sha512-8uWtTt0/B5NxGie9xUVD5y5Ch4Q+Hy7kFYKtUpwYbzSAgJEoaMxT8rMnfnK7zfAYSLC8GnGO1/tXrFtKIYYQVQ==}
35
36
'@jridgewell/gen-mapping@0.3.13':
37
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
···
438
hasBin: true
439
440
snapshots:
441
+
442
+
'@fontsource-variable/work-sans@5.2.8': {}
443
444
'@jridgewell/gen-mapping@0.3.13':
445
dependencies: