Compare commits
18 commits
main
...
refactor/d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b4b4c9982 | ||
|
|
462cd5483a | ||
|
|
37d44b6216 | ||
|
|
40838e3f1e | ||
|
|
cac710880e | ||
|
|
b64e830acd | ||
|
|
4f8e6ba55f | ||
|
|
0e0bff902b | ||
|
|
ae83ed48fd | ||
|
|
58f89f8915 | ||
|
|
060f413336 | ||
|
|
73fdec95ef | ||
|
|
a61d95cba3 | ||
|
|
885f3f6a74 | ||
|
|
a6d4064af8 | ||
|
|
7651afaa0b | ||
|
|
897b10d229 | ||
|
|
00006a013d |
4 changed files with 145 additions and 2 deletions
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Deploy to Netlify
|
||||
run: pnpm dlx --package=netlify-cli@27 netlify deploy --prod --dir=build --auth "$NETLIFY_AUTH_TOKEN" --site "$NETLIFY_SITE_ID"
|
||||
run: pnx netlify-cli deploy --prod --dir=build --auth $NETLIFY_AUTH_TOKEN --site $NETLIFY_SITE_ID
|
||||
env:
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||
|
|
|
|||
83
src/lib/posts/godot-dotnet-with-spacetimedb.md
Normal file
83
src/lib/posts/godot-dotnet-with-spacetimedb.md
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
layout: blog
|
||||
title: Godot .NET with SpacetimeDB
|
||||
description: First post.
|
||||
image:
|
||||
url: https://spacetimedb.com/meta-tags.png
|
||||
alt: SpacetimeDB
|
||||
date: '2026-1-22'
|
||||
categories:
|
||||
- development
|
||||
published: false
|
||||
---
|
||||
|
||||
I've been on and off again experimenting with Godot since the great Unity [controversy of 2023.](https://www.geekwire.com/2023/heres-why-so-many-video-game-developers-are-suddenly-abandoning-the-unity-engine/) At the time Godot came up pretty quickly as the open-source alternative, I'll spare you the history lesson we are here to talk SpacetimeDB! If you found this article I assume you already know what SpacetimeDB is.
|
||||
|
||||
# Setting up our workspace
|
||||
|
||||
Before we get into any programming we are going to do some setup on our project workspace to help things along, we will be thankful for this later! I'm going to be painfully explicit in the details here so bare with me.
|
||||
|
||||
## Create a project directory
|
||||
|
||||
We are going to sidestep creating the root project directory with Godot, this will become apparent as to why later but for now just trust me! 😉
|
||||
|
||||
```bash
|
||||
mkdir massive
|
||||
```
|
||||
|
||||
## Init Git
|
||||
|
||||
```bash
|
||||
git init
|
||||
```
|
||||
|
||||
## Set tool version with mise
|
||||
|
||||
We are going to use [mise-en-place](https://mise.jdx.dev/) to handle our tool versions at the project level, this is a great tool that I now use by default for any new project Im working on. It allows us to keep our tool versions independent of our global settings.
|
||||
|
||||
```bash
|
||||
mise use dotnet@8 bun@latest
|
||||
```
|
||||
|
||||
> This will generate a `mise.toml` file in our project root.
|
||||
|
||||
The first tool is obvious, we are writing in C# so of course we need dotnet! Using bun however, let me explain.
|
||||
|
||||
## Create a new Godot project
|
||||
|
||||
## Create docker-compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
spacetime:
|
||||
image: clockworklabs/spacetime
|
||||
ports:
|
||||
- 3000:3000
|
||||
command: start
|
||||
```
|
||||
|
||||
## Create package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "massive",
|
||||
"scripts": {
|
||||
"database:up": "docker compose up -d",
|
||||
"database:down": "docker compose down",
|
||||
"database:publish": "spacetime publish --project-path server massive",
|
||||
"database:generate": "spacetime generate --lang csharp --out-dir client/module_bindings --project-path server"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## .editorconfig
|
||||
|
||||
```editorconfig
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
```
|
||||
60
src/lib/posts/the-art-of-simple-design.md
Normal file
60
src/lib/posts/the-art-of-simple-design.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
title: The Art of Simple Design
|
||||
description: Functional Decomposition as a Method of handling Contextual Shifts during project development
|
||||
image:
|
||||
url: https://images.unsplash.com/photo-1766811474703-6e86727d7f95?q=80&w=687&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D
|
||||
alt: This is an image
|
||||
date: '2026-1-22'
|
||||
categories:
|
||||
- development
|
||||
published: false
|
||||
---
|
||||
|
||||
Project degradation as a result of contextual shifts during development is a common occurrence, contextual shifts are a natural part of the project development process, and we should always try to account for them in our design and as we develop. Some design frameworks like IDesign seek to solve this through functional decomposition, by reducing a project to a set of functional interactions, i.e a data access calls, business logic, orchestration, etc... This is certainly the correct path, but in the process of trying to develop a perfect solution, often falls into the pit of overdesign with strict naming conventions and complicated architecture. This actively becomes a hindrance to development cadence, the problem we were seeking to fix.
|
||||
|
||||
A strong design methodology should not be a strict instruction manual, but an informative pamphlet. It should impart a new perspective on the same problems we have seen a million times, and give new tools to use.
|
||||
|
||||
```typescript
|
||||
interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
hashed_password: string;
|
||||
}
|
||||
|
||||
interface IUserAccessor {
|
||||
findUser(user_id: string): Promise<User>;
|
||||
createUser(user: User): Promise<User>;
|
||||
updateUser(user: User): Promise<User>;
|
||||
deleteUser(user_id: string): Promise<boolean>;
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { Client } from 'pg';
|
||||
|
||||
class PostgresUserAccessor implements IUserAccessor {
|
||||
|
||||
private readonly Client _client;
|
||||
|
||||
constructor PostgresUserAccessor() {
|
||||
_client = new Client();
|
||||
}
|
||||
|
||||
async findUser(id: string): Promise<User> {
|
||||
await _client.connect()
|
||||
const res = await client.query("SELECT * FROM users WHERE users.id = '$1::text'", [id]);
|
||||
await _client.end()
|
||||
return res.rows[0];
|
||||
}
|
||||
```
|
||||
|
||||
Over the years, between the projects I have worked on, I started to notice that teams tended to gravitate towards one side of a spectrum.
|
||||
|
||||
On one side you have the people who don't follow design patterns, this is the wild west and anything goes, maybe they don't know what patterns to use or even care that they exist? Their architecture is based on vibes, or what has come before, it tends to be disorganized and inconsistent.
|
||||
|
||||
On the other side of the spectrum are the people who are design pattern evangelists, they have either seen these projects and understand the importance of design, or are from a theoretical/academic background. They know their pattern(s) well, but perhaps are too vigorous in their application, this can result in an over-designed mess. What this looks like
|
||||
|
||||
They try so hard to strictly adhere to a chosen design pattern, but either out of misunderstanding or overcommitment, their code becomes rigid and unnatural. Think of it like this, Bridges are a great structure for traversing difficult terrain, but they have their uses. If I was trying to travel upstream on a winding river, I would not build a bridge straight up the river, when completed it may be the fastest option but it would certainly not be cheap or sensible, a boat would be a better option. Now if the context changes and I am trying to traverse from one side of this river to the other? A boat still works, but now the bridge is making a lot more sense! My point is, if all you know is bridge design then everything starts to look like a bridge problem, or... something something hammer and nails.
|
||||
|
||||
Perhaps this leads into another topic about overspecialization and the benefits of generalization in a specialized world. The greatest tools you can have on your belt are new perspectives!
|
||||
|
|
@ -17,7 +17,7 @@ export async function sendContactMessage(name: string, email: string, message: s
|
|||
form.append('content', content);
|
||||
|
||||
if (!env.DISCORD_CONTACT_WEBHOOK) {
|
||||
throw new Error('Undefined discord webhook');
|
||||
return;
|
||||
}
|
||||
const url = new URL(env.DISCORD_CONTACT_WEBHOOK);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue