This commit is contained in:
waalge 2025-02-16 11:30:41 +00:00
parent 712c7cac44
commit 194492234e
31 changed files with 2977 additions and 550 deletions

View File

@ -1,16 +1,6 @@
# Kompact.io site
## Commands ## Commands
recompile css Enter devshell, and run `menu`
```sh See flake for details.
tailwindcss -i ./content/css/main.css -o ./content/css/mini.css --minify
```
build, serve and watch
```sh
cabal run site -- watch
```
deploy
```sh
rsync -r --delete ./_site/* genesis:/var/www/kompactio-landing/
```

View File

@ -5,7 +5,8 @@
@font-face { @font-face {
/* Set in tailwindconfig */ /* Set in tailwindconfig */
font-family: "jetbrains-mono"; font-family: "jetbrains-mono";
src: local("jetbrains-mono"), src:
local("jetbrains-mono"),
url("/fonts/JetBrainsMono-Medium.woff2") format("woff2"); url("/fonts/JetBrainsMono-Medium.woff2") format("woff2");
} }
@ -13,59 +14,61 @@ article {
margin-bottom: 2rem; margin-bottom: 2rem;
} }
article>section> :is(pre, p, h1, h2, h3, h4, h5, h6) { article > section > :is(pre, p, h1, h2, h3, h4, h5, h6) {
margin-top: 2rem; margin-top: 2rem;
} }
article>section { article > section {
font-family: "Lucida" Grande, sans-serif; font-family:
"Lucida" Grande,
sans-serif;
} }
article>section> :is(h1, h2, h3, h4, h5, h6, code) { article > section > :is(h1, h2, h3, h4, h5, h6, code) {
font-family: "jetbrains-mono"; font-family: "jetbrains-mono";
} }
article>section>blockquote { article > section > blockquote {
padding: 1rem; padding: 1rem;
border-left-width: 4px; border-left-width: 4px;
border-color: rgb(239 68 68); border-color: rgb(239 68 68);
font-style: italic; font-style: italic;
} }
article>section>h1 { article > section > h1 {
margin-top: 2rem; margin-top: 2rem;
font-size: 3rem; font-size: 3rem;
} }
article>section>h1::before { article > section > h1::before {
content: "# "; content: "# ";
} }
article>section>h2 { article > section > h2 {
font-size: 2rem; font-size: 2rem;
} }
article>section>h2::before { article > section > h2::before {
content: "## "; content: "## ";
} }
article>section>h3 { article > section > h3 {
font-size: 1.5rem; font-size: 1.5rem;
} }
article>section>h3::before { article > section > h3::before {
content: "### "; content: "### ";
} }
article>section>h4 { article > section > h4 {
font-size: 1.3rem; font-size: 1.3rem;
} }
article>section>h4::before { article > section > h4::before {
content: "#### "; content: "#### ";
} }
article>section { article > section {
margin-top: 4rem; margin-top: 4rem;
} }
@ -91,3 +94,15 @@ article ol {
margin-left: 1rem; margin-left: 1rem;
list-style: decimal inside; list-style: decimal inside;
} }
#footnotes {
padding-top: 1rem;
}
#footnotes > ol > li {
margin-top: 1rem;
}
#footnotes > ol > li > p {
display: inline;
}

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,118 @@
/* PrismJS 1.29.0 /* PrismJS 1.29.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+haskell+json+nix+racket+rust+scheme */ https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+haskell+json+nix+racket+rust+scheme */
code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} code[class*="language-"],
pre[class*="language-"] {
color: #000;
background: 0 0;
text-shadow: 0 1px #fff;
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
code[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
pre[class*="language-"]::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
code[class*="language-"] ::selection,
code[class*="language-"]::selection,
pre[class*="language-"] ::selection,
pre[class*="language-"]::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
pre[class*="language-"] {
padding: 1em;
margin: 0.5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
:not(pre) > code[class*="language-"] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
.token.cdata,
.token.comment,
.token.doctype,
.token.prolog {
color: #708090;
}
.token.punctuation {
color: #999;
}
.token.namespace {
opacity: 0.7;
}
.token.boolean,
.token.constant,
.token.deleted,
.token.number,
.token.property,
.token.symbol,
.token.tag {
color: #905;
}
.token.attr-name,
.token.builtin,
.token.char,
.token.inserted,
.token.selector,
.token.string {
color: #690;
}
.language-css .token.string,
.style .token.string,
.token.entity,
.token.operator,
.token.url {
color: #9a6e3a;
background: hsla(0, 0%, 100%, 0.5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.class-name,
.token.function {
color: #dd4a68;
}
.token.important,
.token.regex,
.token.variable {
color: #e90;
}
.token.bold,
.token.important {
font-weight: 700;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,59 @@
---
title: why is building txs hard?
---
## What is a dapp?
A typical dapp has a number of components:
- Validators: also called the _on-chain_ part.
The decentralized network of nodes that maintain the chain run this code as part of the process of deciding
whether a tx is to be added to the chain or rejected.
- Chain indexing: watches the chain and records the data relevant to the dapp.
- Pretty front-end: typically how a user interacts with a dapp.
- Tx-building code: A component of the frontend.
It takes data from the user, the user's wallet, the chain-indexer and possibly elsewhere
to construct txs to be submitted to the chain that the validators will deem acceptable.
Here we have really described a browser-based plutus dapp.
Considering the term _dapp_ more generally, the Daedalus wallet is a dapp which is neither browser based nor involves any Plutus.
Cli-based dapps also exist, such as multi-sig using native scripts.
## What is a tx?
At its core, the chain is a list of transaction outputs.
The chain is changed by submitting a tx which "spends" existing unspent transaction outputs (utxos) and appending new ones.
(There's other possible modifications too, like minting native assets and staking _etc_, but the key part is spending.)
The on-chain part is where the dapp has its integrity, but users can only interact with the on-chain part of the dapp by submitting txs.
The on-chain part is relatively simple.
It inspects each tx that it is concerned with, and if it does not like what it sees, it fails.
Cardano is, in this sense, a lean chain.
The off-chain part is relatively complex.
There may be no, one, or many potential valid txs that would satisfy the user's intent.
At its core, a transaction is a list of inputs and outputs.
The inputs are spent, and the outputs created.
It must also contain the necessary signatures.
## Some history
When Plutus was first dreamed up, it wasn't just a language.
It was whole environment in which dapps would be engaged with.
The on-chain and off-chain code were coupled into a single framework with seamless extensive testing.
Dapps ran in the _PAB_, Plutus Application Backend.
Everything was great.
Except that it didn't work.
The chain-indexer would periodically fall-over,
it required users had to maintain a full node,
and the api never matured in to something stable, complete, and bug-free.
In addition, the validators it produced were bloated and un-optimized and would quickly hit the constraints of the cardano blockchain.
As a result teams turned to coming up with alternatives.
One of the first was MLabs and co in creating pluto and plutarch.
Later Aiken appeared to meet similar needs.
These began resolving issues with the on-chain part.
This left the off-chain part wanting.

View File

@ -1,3 +1,5 @@
--- ---
title: Kompact.io title: Kompact.io
--- ---
## Hero

View File

@ -20,8 +20,8 @@ This post is borne out of a best effort of how far "zk on Cardano" can be pushed
## What is zk? ## What is zk?
There is no shortage of explanations describing what zk is There is no shortage of explanations describing what zk is
( _eg_ [by Vitalik](https://vitalik.ca/general/2021/01/26/snarks.html){target="_blank"} or ( _eg_ [by Vitalik](https://vitalik.ca/general/2021/01/26/snarks.html){target="\_blank"} or
[a full mooc](https://zk-learning.org/){target="_blank"} ). [a full mooc](https://zk-learning.org/){target="\_blank"} ).
There is also a reasonable breath to the field of zk that includes things like distributed compute. There is also a reasonable breath to the field of zk that includes things like distributed compute.
Zk involves some really neat maths that lets you do some seemingly magical feats Zk involves some really neat maths that lets you do some seemingly magical feats
and pairs well with blockchain in extending what is functionally possible. and pairs well with blockchain in extending what is functionally possible.
@ -58,16 +58,15 @@ Snark stands for _Succinct Non-Interactive Argument of Knowledge_.
And without saying anything more, it means that Alice has to do way less algebra than Bob. And without saying anything more, it means that Alice has to do way less algebra than Bob.
In applications this is important because Bob might not be able to lie anymore but he could still waste Alice's time. In applications this is important because Bob might not be able to lie anymore but he could still waste Alice's time.
## Sudoku snark ## Sudoku snark
Sudoku snark was the entrant to Emurgo's hackathon. Sudoku snark was the entrant to Emurgo's hackathon.
The summary-pitch-story deck is [here](https://pub.kompact.io/sudoku-snark){target="_blank"}. The summary-pitch-story deck is [here](https://pub.kompact.io/sudoku-snark){target="\_blank"}.
Links to the associated repos: [plutus-zk](https://github.com/waalge/plutus-zk){target="_blank"} Links to the associated repos: [plutus-zk](https://github.com/waalge/plutus-zk){target="\_blank"}
and [sudoku-snark](https://github.com/waalge/sudoku-snark){target="_blank"}. and [sudoku-snark](https://github.com/waalge/sudoku-snark){target="\_blank"}.
Just after the hackathon got underway there was a Just after the hackathon got underway there was a
[large PR merged](https://github.com/input-output-hk/plutus/pull/5231){target="_blank"} [large PR merged](https://github.com/input-output-hk/plutus/pull/5231){target="\_blank"}
into the main branch of plutus. into the main branch of plutus.
It's a mammoth culmination of many many months of work. It's a mammoth culmination of many many months of work.
In it were some fundamental primitives needed for running zk algorithms. In it were some fundamental primitives needed for running zk algorithms.
@ -84,7 +83,7 @@ this third part is where things got stuck.
We did get as far as running a cluster of nodes in the Conway era with the latest version of plutus We did get as far as running a cluster of nodes in the Conway era with the latest version of plutus
but unrelated changes seemed to thwart any chance of building transactions here. but unrelated changes seemed to thwart any chance of building transactions here.
A quick shout-out to the [modulo-p.io](https://modulo-p.io/){target="_blank"} team. A quick shout-out to the [modulo-p.io](https://modulo-p.io/){target="\_blank"} team.
They had a different approach and managed to implement a zk algorithm with the existing plutus primitives. They had a different approach and managed to implement a zk algorithm with the existing plutus primitives.
This spared the need to play the foolhardy dependency bumping game with the Cardano node. This spared the need to play the foolhardy dependency bumping game with the Cardano node.
However, because zk is so arithmetically intense, However, because zk is so arithmetically intense,

View File

@ -1,14 +1,19 @@
--- ---
title: "Hydra is neat: You don't need Hydra" title: "Hydra is cool: You don't need Hydra"
date: 2023-09-20 date: 2023-09-20
--- ---
## Hydra is neat ## Hydra is cool
Hydra[^1] is a very cool project. It is a layer 2 for Cardano that is _isomorphic_ to the L1. Hydra[^1] is a very cool project. It is a layer 2 for Cardano that is _isomorphic_ to the L1.
Here isomorphic means that Plutus runs in Hydra just like it does on the L1. Here isomorphic means that Plutus runs in Hydra just like it does on the L1.
That dapp you've just toiled over for months to run on the L1 can be put in Hydra and 'just work'. That dapp you've just toiled over for months to run on the L1 can be put in Hydra and 'just work'.
[^1]:
This post does not distinguish between Hydra and Hydra Head referring to both as Hydra.
If you want to know more about Hydra, then check out their
[explainers](https://hydra.family/head-protocol/core-concepts).
## Hydra's compromise ## Hydra's compromise
Hydra boasts it can achieve higher throughput and lower transaction fees compared to the Cardano L1 Hydra boasts it can achieve higher throughput and lower transaction fees compared to the Cardano L1
@ -17,7 +22,7 @@ You may be asking _If my dapp just works on Hydra and it's better in all key res
then why don't we all just use Hydra?_. then why don't we all just use Hydra?_.
The answer is because these improvements come at a cost. The answer is because these improvements come at a cost.
Consensus in Hydra differs from that on the L1. Consensus in Hydra differs from that on the L1.
Hydra doesn't use ouroboros; all participating hydra nodes Hydra doesn't use ouroboros. Instead all participating hydra nodes
must sign-off on all updates to the chain state. must sign-off on all updates to the chain state.
Practically speaking, far fewer nodes can participate in Hydra Practically speaking, far fewer nodes can participate in Hydra
and one quiet node stops the whole Hydra chain updating. and one quiet node stops the whole Hydra chain updating.
@ -27,22 +32,22 @@ Not great for an L1.
Hydra is an example of a way to do state channels. Hydra is an example of a way to do state channels.
A state channel relies on the integrity of the L1, while accumulating state separately from it (L2). A state channel relies on the integrity of the L1, while accumulating state separately from it (L2).
At some point the the layers are brought into sync. At some point the layers are brought into sync.
This is when funds on the L1 can be unlocked, and/or the state of the L2 updated. This is when funds on the L1 can be unlocked, and/or the state of the L2 updated.
Hydra could be thought to be providing some future-proofing. Hydra could be thought to be providing some future-proofing.
It is possible for a Hydra instance to run indefinitely It is possible for a Hydra instance to run indefinitely
and scripts yet written will be executable in some already running instance. and Plutus scripts not yet written will be executable in some already running instance.
However, because Hydra's consensus is so brittle the longevity of an instance is not something to depend on. However, because Hydra's consensus is so brittle the longevity of an instance is not something to depend on.
Each and any transaction may be its last. Each and any transaction may be its last.
A key question is when considering Hydra is _Do I need isomorphic-ness?_. A key question when considering Hydra is _Do I need isomorphic-ness?_.
If you know all your business logic before instantiation If you know all your business logic before instantiation
then the answer is **no, you don't care for isomorphic-ness**. then the answer is **no, you don't care for isomorphic-ness**.
Instead, you can roll-your-own L2. It depends on your use case as to how much work that ends up being. Instead, you can roll-your-own L2.
It depends on your use case as to how much work that ends up being.
It can be very simple. It can be very simple.
## You don't want Hydra ## You don't want Hydra
In Hydra, the latest agreed state in the L2 is the one that the L1 will accept as the most legitimate. In Hydra, the latest agreed state in the L2 is the one that the L1 will accept as the most legitimate.
@ -51,7 +56,7 @@ This is a sensible default.
Suppose however you have a game of poker where one player learns that they've lost and rage quits. Suppose however you have a game of poker where one player learns that they've lost and rage quits.
From the game's perspective, that final transaction should be forced through - the player's loss is inevitable. From the game's perspective, that final transaction should be forced through - the player's loss is inevitable.
At present this isn't possible with Hydra. At present this isn't possible with Hydra.
If a party doesn't sign then a state isn't valid. If a party doesn't sign, then a state isn't valid.
In another use case, suppose there is some particularly intense on-chain verification In another use case, suppose there is some particularly intense on-chain verification
that would be prohibitive on the L1 but that you'd like the results of which to that would be prohibitive on the L1 but that you'd like the results of which to
@ -65,8 +70,8 @@ Both the cases above are resolvable with custom sync logic.
## An Example: Subbit.xyz ## An Example: Subbit.xyz
Probably the simplest, non-trivial example using state channels is [Subbit.xyz][https://subbit.xyz]. Probably the simplest, non-trivial example using state channels is [Subbit.xyz](https://subbit.xyz).
Subbit.xyz is premised on the observation that subscription is very common use case: Subbit.xyz is premised on the observation that subscription is a very common use case:
there are two parties where one pays the other incrementally. there are two parties where one pays the other incrementally.
It sacrifices generality to gain absolutely minimal overhead for both parties. It sacrifices generality to gain absolutely minimal overhead for both parties.
@ -78,7 +83,7 @@ All logic is known at instantiation.
A consumer needs only to keep track of their account balance, A consumer needs only to keep track of their account balance,
ascertain the cost of each outgoing request, ascertain the cost of each outgoing request,
and produce valid signatures for a few dozen bytes of data at a time. and produce valid signatures for a few dozen bytes of data at a time.
They don't need to watch the L1 and its a non-chatty protocol. They don't need to watch the L1 and it's a non-chatty protocol.
The low resource needs opens it up to applications The low resource needs opens it up to applications
on intermittently connected user devices such as laptops and mobile, on intermittently connected user devices such as laptops and mobile,
and even micro-controllers. and even micro-controllers.
@ -90,15 +95,10 @@ The low resource needs for a provider means they have the ability to serve more
## Hydra for QoL ## Hydra for QoL
When Hydra reaches a point of maturity that its plug and play, When Hydra reaches a point of maturity that it's plug and play,
it's potentially far easier to deploy with Hydra then roll-your-own L2. it's potentially far easier to deploy with Hydra then roll-your-own L2.
Isomorphic-ness gives Hydra incredible flexibility and generality. Isomorphic-ness gives Hydra incredible flexibility and generality.
You don't need isomorphic-ness but because of it, Hydra could be an easy and convenient solution. You don't need isomorphic-ness but because of it, Hydra could be an easy and convenient solution.
As for custom sync logic, it is surely the case that there is a tranche on interesting applications where As for custom sync logic, it is surely the case that there is a tranche of interesting applications where
its far easier and more effective to reuse Hydra infra and modify it than creating your own L2 from scratch. it's far easier and more effective to reuse Hydra infra and modify it than creating your own L2 from scratch.
[^1]: This post does not distinguish between Hydra and Hydra Head referring to both as Hydra.
If you want to know more about Hydra, then check out their
[explainers](https://hydra.family/head-protocol/core-concepts).

View File

@ -28,7 +28,7 @@ Possible solutions:
The problems are: The problems are:
1. Requires relentless constructing and deconstructing across the function call. 1. Requires relentless constructing and deconstructing across the function call.
This adds costs. This adds costs.
2. Becomes tedious aligning the definition and function call. 2. Becomes tedious aligning the definition and function call.
3. Ends up with very long validators which are hard to unit test. 3. Ends up with very long validators which are hard to unit test.
@ -245,9 +245,9 @@ Some examples:
- `Air::Var` require 100 LoC to do case handling on different constructors. - `Air::Var` require 100 LoC to do case handling on different constructors.
- Lists in air have no immediate analogue in uplc - Lists in air have no immediate analogue in uplc
- builtins, as in built-in functions (standard shorthand), have to be mediated - builtins, as in built-in functions (standard shorthand), have to be mediated
with some combination of `force` and `delay` in order to behave as they should. with some combination of `force` and `delay` in order to behave as they should.
- user functions must be "uncurried", ie treated as a sequence of single argument functions, - user functions must be "uncurried", ie treated as a sequence of single argument functions,
and recursion must be handled and recursion must be handled
- Do some magic in order to efficiently allow "record updates". - Do some magic in order to efficiently allow "record updates".
#### Cranking the Optimizer #### Cranking the Optimizer

View File

@ -1,15 +1,18 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener("DOMContentLoaded", function () {
// Get all "navbar-burger" elements // Get all "navbar-burger" elements
var $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0); var $navbarBurgers = Array.prototype.slice.call(
document.querySelectorAll(".navbar-burger"),
0,
);
// Check if there are any navbar burgers // Check if there are any navbar burgers
if ($navbarBurgers.length > 0) { if ($navbarBurgers.length > 0) {
// Add a click event on each of them // Add a click event on each of them
$navbarBurgers.forEach(function ($el) { $navbarBurgers.forEach(function ($el) {
$el.addEventListener('click', function () { $el.addEventListener("click", function () {
// Get the "main-nav" element // Get the "main-nav" element
var $target = document.getElementById('main-nav'); var $target = document.getElementById("main-nav");
// Toggle the class on "main-nav" // Toggle the class on "main-nav"
$target.classList.toggle('hidden'); $target.classList.toggle("hidden");
}); });
}); });
} }

File diff suppressed because one or more lines are too long

View File

@ -2,15 +2,14 @@
"nodes": { "nodes": {
"devshell": { "devshell": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs"
"systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1688380630, "lastModified": 1735644329,
"narHash": "sha256-8ilApWVb1mAi4439zS3iFeIT0ODlbrifm/fegWwgHjA=", "narHash": "sha256-tO3HrHriyLvipc4xr+Ewtdlo7wM1OjXNjlWRgmM7peY=",
"owner": "numtide", "owner": "numtide",
"repo": "devshell", "repo": "devshell",
"rev": "f9238ec3d75cefbb2b42a44948c4e8fb1ae9a205", "rev": "f7795ede5b02664b57035b3b757876703e2c3eac",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -24,11 +23,11 @@
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": "nixpkgs-lib"
}, },
"locked": { "locked": {
"lastModified": 1683560683, "lastModified": 1738453229,
"narHash": "sha256-XAygPMN5Xnk/W2c1aW0jyEa6lfMDZWlQgiNtmHXytPc=", "narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "006c75898cf814ef9497252b022e91c946ba8e17", "rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -38,11 +37,11 @@
}, },
"flake-root": { "flake-root": {
"locked": { "locked": {
"lastModified": 1680964220, "lastModified": 1723604017,
"narHash": "sha256-dIdTYcf+KW9a4pKHsEbddvLVSfR1yiAJynzg2x0nfWg=", "narHash": "sha256-rBtQ8gg+Dn4Sx/s+pvjdq3CB2wQNzx9XGFq/JVGCB6k=",
"owner": "srid", "owner": "srid",
"repo": "flake-root", "repo": "flake-root",
"rev": "f1c0b93d05bdbea6c011136ba1a135c80c5b326c", "rev": "b759a56851e10cb13f6b8e5698af7b59c44be26e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -53,11 +52,11 @@
}, },
"haskell-flake": { "haskell-flake": {
"locked": { "locked": {
"lastModified": 1684180957, "lastModified": 1739669127,
"narHash": "sha256-qtEZf4gcmQU5ePbFtltqpAS0PajWLURVC7nuoS46dSk=", "narHash": "sha256-2s3wYTqKq7aBa41VHWg/G2XAOii8MW+WAMtLdgy1cek=",
"owner": "srid", "owner": "srid",
"repo": "haskell-flake", "repo": "haskell-flake",
"rev": "4e1c76de8795608bb47295c018b37a563c492fd2", "rev": "eabf8cf32e5f6a267ea637e1b3eabc9b7ddf29e1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -68,11 +67,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1677383253, "lastModified": 1722073938,
"narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=", "narHash": "sha256-OpX0StkL8vpXyWOGUD6G+MA26wAXK6SpT94kLJXo6B4=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9952d6bc395f5841262b006fbace8dd7e143b634", "rev": "e36e9f57337d0ff0cf77aceb58af4c805472bfae",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -84,29 +83,23 @@
}, },
"nixpkgs-lib": { "nixpkgs-lib": {
"locked": { "locked": {
"dir": "lib", "lastModified": 1738452942,
"lastModified": 1682879489, "narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=",
"narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=", "type": "tarball",
"owner": "NixOS", "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
"repo": "nixpkgs",
"rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0",
"type": "github"
}, },
"original": { "original": {
"dir": "lib", "type": "tarball",
"owner": "NixOS", "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
} }
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1684385584, "lastModified": 1739446958,
"narHash": "sha256-O7y0gK8OLIDqz+LaHJJyeu09IGiXlZIS3+JgEzGmmJA=", "narHash": "sha256-+/bYK3DbPxMIvSL4zArkMX0LQvS7rzBKXnDXLfKyRVc=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "48a0fb7aab511df92a17cf239c37f2bd2ec9ae3a", "rev": "2ff53fe64443980e139eaa286017f53f88336dd0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -118,16 +111,16 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1680945546, "lastModified": 1735554305,
"narHash": "sha256-8FuaH5t/aVi/pR1XxnF0qi4WwMYC+YxlfdsA0V+TEuQ=", "narHash": "sha256-zExSA1i/b+1NMRhGGLtNfFGXgLtgo+dcuzHzaWA6w3Q=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "d9f759f2ea8d265d974a6e1259bd510ac5844c5d", "rev": "0e82ab234249d8eee3e8c91437802b32c74bb3fd",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-unstable", "ref": "nixpkgs-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -142,31 +135,16 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
} }
}, },
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": { "treefmt-nix": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_3" "nixpkgs": "nixpkgs_3"
}, },
"locked": { "locked": {
"lastModified": 1684416994, "lastModified": 1738953846,
"narHash": "sha256-KkZ9diPRl3Y05TngWYs/QhZKnI/3tA3s+2Hhmei8FnE=", "narHash": "sha256-yrK3Hjcr8F7qS/j2F+r7C7o010eVWWlm4T1PrbKBOxQ=",
"owner": "numtide", "owner": "numtide",
"repo": "treefmt-nix", "repo": "treefmt-nix",
"rev": "42045102f90cfd23ca44ae4ef8362180fefcd7fd", "rev": "4f09b473c936d41582dd744e19f34ec27592c5fd",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -28,10 +28,11 @@
# system. # system.
haskellProjects.default = { haskellProjects.default = {
# packages.haskell-template.root = ./.; # Auto-discovered by haskell-flake
overrides = self: super: { };
devShell = { devShell = {
tools = hp: { tools = hp: {
fourmolu = hp.fourmolu;
hoogle = hp.hoogle;
haskell-language-server = hp.haskell-language-server;
treefmt = config.treefmt.build.wrapper; treefmt = config.treefmt.build.wrapper;
} // config.treefmt.build.programs; } // config.treefmt.build.programs;
hlsCheck.enable = false; hlsCheck.enable = false;
@ -65,21 +66,47 @@
# Equivalent to inputs'.nixpkgs.legacyPackages.hello; # Equivalent to inputs'.nixpkgs.legacyPackages.hello;
devShells.default = pkgs.mkShell { devShells.default =
inputsFrom = [ let
config.haskellProjects.default.outputs.devShell menu = pkgs.writeShellScriptBin "menu"
config.flake-root.devShell ''
]; echo -e "\nCommands available: \n${
packages = with pkgs; [ builtins.foldl' (x: y: x + " -> " + (pkgs.lib.getName y) + "\n") "" my-packages
caddy }"
nil '';
nodePackages_latest.vscode-langservers-extracted my-packages = [
nodePackages_latest.tailwindcss menu
nodePackages_latest.typescript-language-server build
haskellPackages.hakyll watch
zlib deploy
]; ];
}; build = pkgs.writeShellScriptBin "build" ''
tailwindcss -i ./content/css/main.css -o ./content/css/mini.css --minify
cabal run site -- build
'';
watch = pkgs.writeShellScriptBin "watch" ''
tailwindcss -i ./content/css/main.css -o ./content/css/mini.css --minify
cabal run site -- watch
'';
deploy = pkgs.writeShellScriptBin "deploy" ''
rsync -r --delete ./docs/* genesis:/var/www/kompactio-landing/
'';
in
pkgs.mkShell {
inputsFrom = [
config.haskellProjects.default.outputs.devShell
config.flake-root.devShell
];
packages = with pkgs; [
caddy
nil
nodePackages_latest.vscode-langservers-extracted
nodePackages_latest.tailwindcss
nodePackages_latest.typescript-language-server
haskellPackages.hakyll
zlib
] ++ my-packages;
};
}; };
flake = { flake = {
# The usual flake attributes can be defined here, including system- # The usual flake attributes can be defined here, including system-

View File

@ -1,13 +0,0 @@
name: example
version: 0.1.0.0
build-type: Simple
cabal-version: >= 1.10
executable site
main-is: site.hs
build-depends: base == 4.*
, hakyll == 4.15.*
, hip == 1.5.*
, filepath
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010

15
site.cabal Normal file
View File

@ -0,0 +1,15 @@
name: site
version: 0.1.0.0
build-type: Simple
cabal-version: >=1.10
executable site
main-is: site.hs
build-depends:
base >=4 && <5
, filepath
, hakyll >=4.16 && <4.17
, hip >=1.5 && <1.6
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010

36
site.hs
View File

@ -1,9 +1,9 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
import Data.Monoid (mappend)
import Hakyll
import System.FilePath (splitExtension, joinPath, splitDirectories, replaceExtension)
import Data.Monoid (mappend)
import Hakyll
import System.FilePath (joinPath, replaceExtension, splitDirectories, splitExtension)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
main :: IO () main :: IO ()
@ -17,38 +17,43 @@ main = hakyll $ do
compile copyFileCompiler compile copyFileCompiler
match "content/scripts/*" $ do match "content/scripts/*" $ do
route rmPrefix route rmPrefix
compile copyFileCompiler compile copyFileCompiler
match "content/css/*" $ do match "content/css/*" $ do
route rmPrefix route rmPrefix
compile compressCssCompiler compile compressCssCompiler
match "content/fonts/*" $ do match "content/fonts/*" $ do
route rmPrefix route rmPrefix
compile copyFileCompiler compile copyFileCompiler
match "content/posts/*.md" $ do match "content/posts/*.md" $ do
route rmPrefixMd route rmPrefixMd
compile $ pandocCompiler compile $
>>= loadAndApplyTemplate "templates/post.html" postCtx pandocCompiler
>>= loadAndApplyTemplate "templates/default.html" postCtx >>= loadAndApplyTemplate "templates/post.html" postCtx
>>= relativizeUrls >>= loadAndApplyTemplate "templates/default.html" postCtx
>>= relativizeUrls
create ["blog.html"] $ do create ["blog.html"] $ do
route idRoute route idRoute
compile $ do compile $ do
posts <- recentFirst =<< loadAll "content/posts/*.md" posts <- recentFirst =<< loadAll "content/posts/*.md"
let archiveCtx = let archiveCtx =
listField "posts" postCtx (return posts) `mappend` listField "posts" postCtx (return posts)
constField "title" "Blog" `mappend` `mappend` constField "title" "Blog"
defaultContext `mappend` defaultContext
makeItem "" makeItem ""
>>= loadAndApplyTemplate "templates/blog.html" archiveCtx >>= loadAndApplyTemplate "templates/blog.html" archiveCtx
>>= loadAndApplyTemplate "templates/default.html" archiveCtx >>= loadAndApplyTemplate "templates/default.html" archiveCtx
>>= relativizeUrls >>= relativizeUrls
-- match "content/index/*" $ do
-- compile $
-- pandocCompilerWith x
match "content/index.md" $ do match "content/index.md" $ do
route rmPrefixMd route rmPrefixMd
@ -63,12 +68,11 @@ main = hakyll $ do
match "templates/*" $ compile templateBodyCompiler match "templates/*" $ compile templateBodyCompiler
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
postCtx :: Context String postCtx :: Context String
postCtx = postCtx =
dateField "date" "%Y-%m-%d" `mappend` dateField "date" "%Y-%m-%d"
defaultContext `mappend` defaultContext
setExtensionInner :: String -> FilePath -> FilePath setExtensionInner :: String -> FilePath -> FilePath
setExtensionInner = flip replaceExtension setExtensionInner = flip replaceExtension

View File

@ -1,19 +1,15 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: [ content: ["./content/**/*.{html,js}", "./templates/**/*.{html,js}"],
"./content/**/*.{html,js}",
"./templates/**/*.{html,js}",
],
theme: { theme: {
extend: {}, extend: {},
fontFamily: { fontFamily: {
'sans' : ['jetbrains-mono',], sans: ["jetbrains-mono"],
}, },
typography: (theme) => ({}), typography: (theme) => ({}),
}, },
darkMode: 'class', darkMode: "class",
variants: {}, variants: {},
// plugins: [require('@tailwindcss/typography')], // plugins: [require('@tailwindcss/typography')],
plugins: [], plugins: [],
} };

View File

@ -1,27 +1,15 @@
<section id="about" class="py-12 px-2 flex flex-col gap-12"> <section id="about" class="py-12 px-2 flex flex-col gap-12">
<header class="text-3xl"> <header class="text-3xl"># about</header>
# about
</header>
<div> <div>
Kompact.io is dapp dev house. Kompact.io is dapp dev house. Our focus:
Our focus:
<ul class="list-decoration"> <ul class="list-decoration">
<li> <li>safety-first</li>
safety-first <li>fast turn around</li>
</li> <li>integration support</li>
<li>
fast turn around
</li>
<li>
integration support
</li>
</ul> </ul>
<div> <div>
Our typical process: Our typical process:
<div> <div>Idea -> Spec -> Impl -> Test -> Handover</div>
Idea -> Spec -> Impl -> Test -> Handover
</div>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,7 +1,5 @@
<section id="services" class="py-6 px-2 flex flex-col gap-12"> <section id="services" class="py-6 px-2 flex flex-col gap-12">
<header class="text-3xl"> <header class="text-3xl"># blog</header>
# blog
</header>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
A nascent initiative sharing some of the things happening at Kompact.io. A nascent initiative sharing some of the things happening at Kompact.io.
</div> </div>

View File

@ -1,9 +1,8 @@
<section id="contact" class="py-12 px-2 flex flex-col gap-12"> <section id="contact" class="py-12 px-2 flex flex-col gap-12">
<header class="text-3xl"> <header class="text-3xl"># contact</header>
# contact
</header>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Questions? We'll be happy to help answer any of your questions. Send us an email and we'll get back to you shortly. Questions? We'll be happy to help answer any of your questions. Send us an
email and we'll get back to you shortly.
</div> </div>
<div> <div>
Reach us on : <a href="mailto:kompactio@proton.me">kompactio@proton.me</a> Reach us on : <a href="mailto:kompactio@proton.me">kompactio@proton.me</a>

View File

@ -1,42 +1,41 @@
<!doctype html> <!doctype html>
<html class=""> <html class="">
<head>
<head> <meta charset="UTF-8" />
<meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" type="image/x-icon" href="/favicon.png" />
<link rel="icon" type="image/x-icon" href="/favicon.png"> <link href="/css/mini.css" rel="stylesheet" />
<link href="/css/mini.css" rel="stylesheet"> <link href="/css/prism.css" rel="stylesheet" />
<link href="/css/prism.css" rel="stylesheet" /> <title>$title$</title>
<title>$title$</title> </head>
</head> <script>
<script> // On page load or when changing themes, best to add inline in `head` to avoid FOUC
// On page load or when changing themes, best to add inline in `head` to avoid FOUC function updateTheme() {
function updateTheme() { if (
if ( localStorage.theme === "dark" ||
localStorage.theme === 'dark' || (!("theme" in localStorage) &&
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches) window.matchMedia("(prefers-color-scheme: dark)").matches)
) { ) {
document.documentElement.classList.add('dark') document.documentElement.classList.add("dark");
} else { } else {
document.documentElement.classList.remove('dark') document.documentElement.classList.remove("dark");
}
} }
updateTheme();
</script>
} <body
updateTheme() class="bg-white text-gray-900 min-h-screen dark:bg-gradient-to-br dark:from-slate-950 dark:to-black dark:text-white"
</script> >
<div class="container mx-auto">
<body class="bg-white text-gray-900 min-h-screen <hr />
dark:bg-gradient-to-br dark:from-slate-950 dark:to-black dark:text-white"> $partial("templates/nav.html")$
<div class="container mx-auto "> <hr />
<hr /> $body$
$partial("templates/nav.html")$ <hr />
<hr /> $partial("templates/footer.html")$
$body$ </div>
<hr /> </body>
$partial("templates/footer.html")$
</div>
</body>
<script src="/scripts/prism.js"></script>
<script src="/scripts/prism.js"></script>
</html> </html>

View File

@ -1,21 +1,33 @@
<section id="footer" class="py-12 px-2 flex flex-row gap-12 mx-2 sm:mx-4 items-start justify-between <section
text-gray-800 dark:text-gray-200 dark:fill-white"> id="footer"
<div class="text-sm"> class="py-12 px-2 flex flex-row gap-12 mx-2 sm:mx-4 items-start justify-between text-gray-800 dark:text-gray-200 dark:fill-white"
&reg; 2023 kompact.io &trade; All Rights Reserved. >
</div> <div class="text-sm">&reg; 2023 kompact.io &trade; All Rights Reserved.</div>
<div class="flex flex-row gap-4"> <div class="flex flex-row gap-4">
<a href="https://www.linkedin.com/in/dominic-algernon-wallis-123b42187/"> <a href="https://www.linkedin.com/in/dominic-algernon-wallis-123b42187/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" height="20" preserveAspectRatio="xMidYMid meet"> <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512"
height="20"
preserveAspectRatio="xMidYMid meet"
>
<!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --> <!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path <path
d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z" /> d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"
/>
</svg> </svg>
</a> </a>
<a href="https://twitter.com/waalge"> <a href="https://twitter.com/waalge">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="20" preserveAspectRatio="xMidYMid meet"> <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="20"
preserveAspectRatio="xMidYMid meet"
>
<!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --> <!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path <path
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z" /> d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
/>
</svg> </svg>
</a> </a>
</div> </div>

View File

@ -1,12 +1,13 @@
<section id="hero" class="py-8 px-2 h-96 min-h-[50vh] m-auto"> <section id="hero" class="py-8 px-2 h-96 min-h-[50vh] m-auto">
<div class="h-full flex justify-around align-center items-center"> <div class="h-full flex justify-around align-center items-center">
<div class="text-6xl"> <div class="text-6xl">⟨K⟩</div>
⟨K⟩
</div>
<div class="flex flex-col gap-2 truncate"> <div class="flex flex-col gap-2 truncate">
<div>withKompact &#36; <span class="text-red-500 dark:text-yellow-400">do</span> </div> <div>
<div><span class="text-gray-400">· ·</span> dapp <- lean dev </div> withKompact &#36;
<div><span class="text-gray-400">· ·</span> run dapp </div> <span class="text-red-500 dark:text-yellow-400">do</span>
</div> </div>
<div><span class="text-gray-400">· ·</span> dapp <- lean dev</div>
<div><span class="text-gray-400">· ·</span> run dapp</div>
</div> </div>
</div>
</section> </section>

View File

@ -9,7 +9,8 @@
<div> <div>
<ul class="flex flex-row gap-4 md:gap-8"> <ul class="flex flex-row gap-4 md:gap-8">
<li> <li>
<button onClick=" <button
onClick="
(() => { (() => {
if (!('theme' in localStorage)) { if (!('theme' in localStorage)) {
localStorage.theme = 'light' localStorage.theme = 'light'
@ -22,17 +23,16 @@
} }
updateTheme() updateTheme()
})() })()
">◧</button> "
>
</button>
</li> </li>
<li> <li>
<a href="/index.html#contact"> <a href="/index.html#contact"> contact </a>
contact
</a>
</li> </li>
<li> <li>
<a href="/blog.html"> <a href="/blog.html"> blog </a>
blog
</a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -2,9 +2,7 @@
$for(posts)$ $for(posts)$
<li class="mt-4"> <li class="mt-4">
<a href="$url$"> <a href="$url$">
<span class="text-gray-800 dark:text-gray-200"> <span class="text-gray-800 dark:text-gray-200"> $date$ :: </span>
$date$ ::
</span>
$title$ $title$
</a> </a>
</li> </li>

View File

@ -1,20 +1,11 @@
<article class="mx-auto px-4 max-w-prose"> <article class="mx-auto px-4 max-w-prose">
<section class="header"> <section class="header">
<h1> <h1>$title$</h1>
$title$
</h1>
$if(date)$ $if(date)$
<p> <p>Posted on $date$</p>
Posted on $date$ $endif$ $if(author)$
</p> <p>by $author$</p>
$endif$
$if(author)$
<p>
by $author$
</p>
$endif$ $endif$
</section> </section>
<section> <section>$body$</section>
$body$
</section>
</article> </article>

View File

@ -1,46 +1,39 @@
<section id="pricing" class="py-12 px-2 flex flex-col gap-12"> <section id="pricing" class="py-12 px-2 flex flex-col gap-12">
<header class="text-3xl"> <header class="text-3xl"># pricing</header>
# pricing
</header>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Plutus development has traditionally meant long development schedules, and expensive ( &#36; 25k+/mo FTE) engineers. Plutus development has traditionally meant long development schedules, and
We can work with you at competitive rates in either deliverable or retainer based engagements. expensive ( &#36; 25k+/mo FTE) engineers. We can work with you at
competitive rates in either deliverable or retainer based engagements.
</div> </div>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-8 md:mx-24"> <div class="flex flex-col justify-between gap-4 sm:flex-row sm:gap-8">
<div class="max-w-48"> <div class="flex-1">
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">## retainer</div>
## retainer <p class="text-gray-800 dark:text-gray-200 mt-4">Time-based</p>
</div> <p class="text-gray-800 dark:text-gray-200 mt-4">
<div class="text-gray-800 dark:text-gray-200 mt-4">
Time-based
</div>
<div class="text-gray-800 dark:text-gray-200 mt-4">
Still figuring out your project scope? Still figuring out your project scope?
</div> </p>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <p class="text-gray-800 dark:text-gray-200 mt-4">
Need an extra pair of hands on an existing project? Need an extra pair of hands on an existing project?
</div> </p>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <p class="text-gray-800 dark:text-gray-200 mt-4">
Then a retainer based engagement is for you. Then a retainer based engagement is for you.
</div> </p>
</div> </div>
<div class="max-w-48"> <div class="flex-1">
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">## deliverable</div>
## deliverable <p class="text-gray-800 dark:text-gray-200 mt-4">Output-based</p>
</div> <p class="text-gray-800 dark:text-gray-200 mt-4">
<div class="text-gray-800 dark:text-gray-200 mt-4">
Output-based
</div>
<div class="text-gray-800 dark:text-gray-200 mt-4">
You know what you want and need help implementing it? You know what you want and need help implementing it?
</div> </p>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <p class="text-gray-800 dark:text-gray-200 mt-4">
We'll first produce a spec on how the dapp will operate technically. We'll first produce a spec on how the dapp will operate technically.
This involves discussing different options and trade-offs on things from UX to validator complexity. This involves discussing different options and trade-offs on things from
</div> UX to validator complexity.
<div class="text-gray-800 dark:text-gray-200 mt-4"> </p>
Once settled we'll begin the implementation phase and finally integration phase. <p class="text-gray-800 dark:text-gray-200 mt-4">
</div> Once settled we'll begin the implementation phase and finally
integration phase.
</p>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,34 +1,29 @@
<section id="services" class="py-12 px-2 flex flex-col gap-12"> <section id="services" class="py-12 px-2 flex flex-col gap-12">
<header class="text-3xl"> <header class="text-3xl"># services</header>
# services
</header>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
We are cardano native dapp dev outfit focused on helping you going from 0 to launch ASAP. We are cardano native dapp dev outfit focused on helping you going from 0 to
launch ASAP.
</div> </div>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3 sm:gap-8"> <div class="grid grid-cols-1 gap-4 sm:grid-cols-3 sm:gap-8">
<div class="max-w-48"> <div class="max-w-48">
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">## strategy</div>
## strategy
</div>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
We'll work with you to validate your concept, and translate it into an implementable Proof of Concept We'll work with you to validate your concept, and translate it into an
implementable Proof of Concept
</div> </div>
</div> </div>
<div class="max-w-48"> <div class="max-w-48">
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">## implementation</div>
## implementation
</div>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Cook up appropriate Plutus validators to meet your needs Cook up appropriate Plutus validators to meet your needs
</div> </div>
</div> </div>
<div class="max-w-48"> <div class="max-w-48">
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">## deployment</div>
## deployment
</div>
<div class="text-gray-800 dark:text-gray-200 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
We facilitate integrating the on-chain aspects with the rest of your stack We facilitate integrating the on-chain aspects with the rest of your
stack
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,55 +3,135 @@
<div class="relative flex h-16 items-center justify-between"> <div class="relative flex h-16 items-center justify-between">
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden"> <div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
<!-- Mobile menu button--> <!-- Mobile menu button-->
<button type="button" class="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white" aria-controls="mobile-menu" aria-expanded="false"> <button
type="button"
class="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
aria-controls="mobile-menu"
aria-expanded="false"
>
<span class="sr-only">Open main menu</span> <span class="sr-only">Open main menu</span>
<!-- <!--
Icon when menu is closed. Icon when menu is closed.
Menu open: "hidden", Menu closed: "block" Menu open: "hidden", Menu closed: "block"
--> -->
<svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> <svg
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> class="block h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
/>
</svg> </svg>
<!-- <!--
Icon when menu is open. Icon when menu is open.
Menu open: "block", Menu closed: "hidden" Menu open: "block", Menu closed: "hidden"
--> -->
<svg class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> <svg
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> class="hidden h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6 18L18 6M6 6l12 12"
/>
</svg> </svg>
</button> </button>
</div> </div>
<div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start"> <div
class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start"
>
<div class="flex flex-shrink-0 items-center"> <div class="flex flex-shrink-0 items-center">
<img class="block h-8 w-auto lg:hidden" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company"> <img
<img class="hidden h-8 w-auto lg:block" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company"> class="block h-8 w-auto lg:hidden"
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500"
alt="Your Company"
/>
<img
class="hidden h-8 w-auto lg:block"
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500"
alt="Your Company"
/>
</div> </div>
<div class="hidden sm:ml-6 sm:block"> <div class="hidden sm:ml-6 sm:block">
<div class="flex space-x-4"> <div class="flex space-x-4">
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" --> <!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
<a href="#" class="bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium" aria-current="page">Dashboard</a> <a
<a href="#" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Team</a> href="#"
<a href="#" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Projects</a> class="bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium"
<a href="#" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Calendar</a> aria-current="page"
>Dashboard</a
>
<a
href="#"
class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium"
>Team</a
>
<a
href="#"
class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium"
>Projects</a
>
<a
href="#"
class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium"
>Calendar</a
>
</div> </div>
</div> </div>
</div> </div>
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0"> <div
<button type="button" class="rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800"> class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0"
>
<button
type="button"
class="rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800"
>
<span class="sr-only">View notifications</span> <span class="sr-only">View notifications</span>
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> <svg
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" /> class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0"
/>
</svg> </svg>
</button> </button>
<!-- Profile dropdown --> <!-- Profile dropdown -->
<div class="relative ml-3"> <div class="relative ml-3">
<div> <div>
<button type="button" class="flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800" id="user-menu-button" aria-expanded="false" aria-haspopup="true"> <button
type="button"
class="flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800"
id="user-menu-button"
aria-expanded="false"
aria-haspopup="true"
>
<span class="sr-only">Open user menu</span> <span class="sr-only">Open user menu</span>
<img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""> <img
class="h-8 w-8 rounded-full"
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
alt=""
/>
</button> </button>
</div> </div>
@ -65,11 +145,38 @@
From: "transform opacity-100 scale-100" From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95" To: "transform opacity-0 scale-95"
--> -->
<div class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1"> <div
class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
role="menu"
aria-orientation="vertical"
aria-labelledby="user-menu-button"
tabindex="-1"
>
<!-- Active: "bg-gray-100", Not Active: "" --> <!-- Active: "bg-gray-100", Not Active: "" -->
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-0">Your Profile</a> <a
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-1">Settings</a> href="#"
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-2">Sign out</a> class="block px-4 py-2 text-sm text-gray-700"
role="menuitem"
tabindex="-1"
id="user-menu-item-0"
>Your Profile</a
>
<a
href="#"
class="block px-4 py-2 text-sm text-gray-700"
role="menuitem"
tabindex="-1"
id="user-menu-item-1"
>Settings</a
>
<a
href="#"
class="block px-4 py-2 text-sm text-gray-700"
role="menuitem"
tabindex="-1"
id="user-menu-item-2"
>Sign out</a
>
</div> </div>
</div> </div>
</div> </div>
@ -80,10 +187,27 @@
<div class="sm:hidden" id="mobile-menu"> <div class="sm:hidden" id="mobile-menu">
<div class="space-y-1 px-2 pb-3 pt-2"> <div class="space-y-1 px-2 pb-3 pt-2">
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" --> <!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
<a href="#" class="bg-gray-900 text-white block rounded-md px-3 py-2 text-base font-medium" aria-current="page">Dashboard</a> <a
<a href="#" class="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Team</a> href="#"
<a href="#" class="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Projects</a> class="bg-gray-900 text-white block rounded-md px-3 py-2 text-base font-medium"
<a href="#" class="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Calendar</a> aria-current="page"
>Dashboard</a
>
<a
href="#"
class="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium"
>Team</a
>
<a
href="#"
class="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium"
>Projects</a
>
<a
href="#"
class="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium"
>Calendar</a
>
</div> </div>
</div> </div>
</nav> </nav>

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en-US"> <html lang="en-US">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
@ -12,13 +12,13 @@
/> />
<meta name="theme-color" content="#ffffff" /> <meta name="theme-color" content="#ffffff" />
<title>$title$</title> <title>$title$</title>
<meta <meta name="description" content="Lean dapp development" />
name="description" <link rel="preconnect" href="https://fonts.googleapis.com" />
content="Lean dapp development" <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap"
rel="stylesheet"
/> />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/normalize.css" /> <link rel="stylesheet" href="/css/normalize.css" />
<link rel="stylesheet" href="/css/terminal.css" /> <link rel="stylesheet" href="/css/terminal.css" />
<link rel="stylesheet" href="/css/custom.css" /> <link rel="stylesheet" href="/css/custom.css" />