From c2f179e8ab2e8293806d7017083742f475346015 Mon Sep 17 00:00:00 2001
From: Wanjohi
Date: Fri, 18 Jul 2025 19:41:51 +0300
Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=A7=B9=20chore(infra):=20Wipe=20out?=
=?UTF-8?q?=20everything?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
infra/api.ts | 120 ---------------
infra/auth.ts | 32 ----
infra/bus.ts | 70 ---------
infra/cluster.ts | 6 -
infra/dns.ts | 5 -
infra/email.ts | 6 -
infra/postgres.ts | 67 ---------
infra/realtime.ts | 9 --
infra/secret.ts | 18 ---
infra/stage.ts | 2 -
infra/storage.ts | 1 -
infra/vpc.ts | 11 --
infra/www.ts | 23 ---
infra/zero.ts | 186 ------------------------
packages/web/.astro/content-assets.mjs | 1 +
packages/web/.astro/content-modules.mjs | 1 +
packages/web/.astro/data-store.json | 1 +
packages/web/.astro/settings.json | 5 +
packages/web/.astro/types.d.ts | 1 +
19 files changed, 9 insertions(+), 556 deletions(-)
delete mode 100644 infra/api.ts
delete mode 100644 infra/auth.ts
delete mode 100644 infra/bus.ts
delete mode 100644 infra/cluster.ts
delete mode 100644 infra/dns.ts
delete mode 100644 infra/email.ts
delete mode 100644 infra/postgres.ts
delete mode 100644 infra/realtime.ts
delete mode 100644 infra/secret.ts
delete mode 100644 infra/stage.ts
delete mode 100644 infra/storage.ts
delete mode 100644 infra/vpc.ts
delete mode 100644 infra/www.ts
delete mode 100644 infra/zero.ts
create mode 100644 packages/web/.astro/content-assets.mjs
create mode 100644 packages/web/.astro/content-modules.mjs
create mode 100644 packages/web/.astro/data-store.json
create mode 100644 packages/web/.astro/settings.json
create mode 100644 packages/web/.astro/types.d.ts
diff --git a/infra/api.ts b/infra/api.ts
deleted file mode 100644
index a93e8539..00000000
--- a/infra/api.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-import { bus } from "./bus";
-import { vpc } from "./vpc";
-import { auth } from "./auth";
-import { domain } from "./dns";
-import { secret } from "./secret";
-import { postgres } from "./postgres";
-
-const urls = new sst.Linkable("Urls", {
- properties: {
- api: `https://api.${domain}`,
- auth: `https://auth.${domain}`,
- site: $dev ? "http://localhost:3000" : `https://console.${domain}`,
- }
-})
-
-const apiFn = new sst.aws.Function("ApiFn", {
- vpc,
- handler: "packages/functions/src/api/index.handler",
- streaming: !$dev,
- link: [
- bus,
- urls,
- auth,
- postgres,
- secret.SteamApiKey,
- secret.PolarSecret,
- secret.PolarWebhookSecret,
- secret.NestriFamilyMonthly,
- secret.NestriFamilyYearly,
- secret.NestriFreeMonthly,
- secret.NestriProMonthly,
- secret.NestriProYearly,
- ],
- url: true,
-});
-
-const provider = new aws.Provider("UsEast1", { region: "us-east-1" });
-
-const webAcl = new aws.wafv2.WebAcl(
- "ApiWaf",
- {
- scope: "CLOUDFRONT",
- defaultAction: {
- allow: {},
- },
- visibilityConfig: {
- cloudwatchMetricsEnabled: true,
- metricName: "api-rate-limit-metric",
- sampledRequestsEnabled: true,
- },
- rules: [
- {
- name: "rate-limit-rule",
- priority: 1,
- action: {
- block: {
- customResponse: {
- responseCode: 429,
- customResponseBodyKey: "rate-limit-response",
- },
- },
- },
- statement: {
- rateBasedStatement: {
- limit: 2 * 60, // 2 rps per authorization header
- evaluationWindowSec: 60,
- aggregateKeyType: "CUSTOM_KEYS",
- customKeys: [
- {
- header: {
- name: "Authorization",
- textTransformations: [{ priority: 0, type: "NONE" }],
- },
- },
- ],
- },
- },
- visibilityConfig: {
- cloudwatchMetricsEnabled: true,
- metricName: "rate-limit-rule-metric",
- sampledRequestsEnabled: true,
- },
- },
- ],
- customResponseBodies: [
- {
- key: "rate-limit-response",
- content: JSON.stringify({
- type: "rate_limit",
- code: "too_many_requests",
- message: "Rate limit exceeded. Please try again later.",
- }),
- contentType: "APPLICATION_JSON",
- },
- ],
- },
- { provider },
-);
-
-export const api = new sst.aws.Router("Api", {
- routes: {
- "/*": apiFn.url,
- },
- domain: {
- name: "api." + domain,
- dns: sst.cloudflare.dns(),
- },
- transform: {
- cdn(args) {
- if (!args.transform) {
- args.transform = {
- distribution: {},
- };
- }
- args.transform!.distribution = {
- webAclId: webAcl.arn,
- };
- },
- },
-});
\ No newline at end of file
diff --git a/infra/auth.ts b/infra/auth.ts
deleted file mode 100644
index e10fb4e9..00000000
--- a/infra/auth.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { bus } from "./bus";
-import { vpc } from "./vpc";
-import { domain } from "./dns";
-import { secret } from "./secret";
-import { postgres } from "./postgres";
-
-export const auth = new sst.aws.Auth("Auth", {
- authorizer: {
- vpc,
- link: [
- bus,
- postgres,
- secret.PolarSecret,
- secret.GithubClientID,
- secret.DiscordClientID,
- secret.GithubClientSecret,
- secret.DiscordClientSecret,
- ],
- permissions: [
- {
- actions: ["ses:SendEmail"],
- resources: ["*"],
- },
- ],
- handler: "packages/functions/src/auth/index.handler",
- },
- domain: {
- name: "auth." + domain,
- dns: sst.cloudflare.dns(),
- },
- forceUpgrade: "v2",
-});
\ No newline at end of file
diff --git a/infra/bus.ts b/infra/bus.ts
deleted file mode 100644
index db624c33..00000000
--- a/infra/bus.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { vpc } from "./vpc";
-import { secret } from "./secret";
-import { storage } from "./storage";
-import { postgres } from "./postgres";
-
-export const dlq = new sst.aws.Queue("Dlq");
-
-export const retryQueue = new sst.aws.Queue("RetryQueue");
-
-export const bus = new sst.aws.Bus("Bus");
-
-export const eventSub = bus.subscribe("Event", {
- vpc,
- handler: "packages/functions/src/events/index.handler",
- link: [
- // email,
- bus,
- storage,
- postgres,
- retryQueue,
- secret.PolarSecret,
- secret.SteamApiKey
- ],
- environment: {
- RETRIES: "2",
- },
- memory: "3002 MB",// For faster processing of large(r) images
- timeout: "10 minutes",
-});
-
-new aws.lambda.FunctionEventInvokeConfig("EventConfig", {
- functionName: $resolve([eventSub.nodes.function.name]).apply(
- ([name]) => name,
- ),
- maximumRetryAttempts: 1,
- destinationConfig: {
- onFailure: {
- destination: retryQueue.arn,
- },
- },
-});
-
-retryQueue.subscribe({
- vpc,
- handler: "packages/functions/src/queues/retry.handler",
- timeout: "30 seconds",
- environment: {
- RETRIER_QUEUE_URL: retryQueue.url,
- },
- link: [
- dlq,
- retryQueue,
- eventSub.nodes.function,
- ],
- permissions: [
- {
- actions: ["lambda:GetFunction", "lambda:InvokeFunction"],
- resources: [
- $interpolate`arn:aws:lambda:${aws.getRegionOutput().name}:${aws.getCallerIdentityOutput().accountId}:function:*`,
- ],
- },
- ],
- transform: {
- function: {
- deadLetterConfig: {
- targetArn: dlq.arn,
- },
- },
- },
-});
\ No newline at end of file
diff --git a/infra/cluster.ts b/infra/cluster.ts
deleted file mode 100644
index d2afc758..00000000
--- a/infra/cluster.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { vpc } from "./vpc";
-
-export const cluster = new sst.aws.Cluster("Cluster", {
- vpc,
- forceUpgrade: "v2"
-});
\ No newline at end of file
diff --git a/infra/dns.ts b/infra/dns.ts
deleted file mode 100644
index aa54d355..00000000
--- a/infra/dns.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const domain =
- {
- production: "nestri.io",
- dev: "dev.nestri.io",
- }[$app.stage] || $app.stage + ".dev.nestri.io";
\ No newline at end of file
diff --git a/infra/email.ts b/infra/email.ts
deleted file mode 100644
index 70a3f381..00000000
--- a/infra/email.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { domain } from "./dns";
-
-export const email = new sst.aws.Email("Email",{
- sender: domain,
- dns: sst.cloudflare.dns(),
-})
\ No newline at end of file
diff --git a/infra/postgres.ts b/infra/postgres.ts
deleted file mode 100644
index 9993f380..00000000
--- a/infra/postgres.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { vpc } from "./vpc";
-import { isPermanentStage } from "./stage";
-
-export const postgres = !isPermanentStage
- ? sst.aws.Aurora.get("Database", "nestri-dev-databasecluster-vmeeabek")
- : new sst.aws.Aurora("Database", {
- vpc,
- engine: "postgres",
- scaling: {
- min: "0 ACU",
- max: "1 ACU",
- },
- transform: {
- clusterParameterGroup: {
- parameters: [
- {
- name: "rds.logical_replication",
- value: "1",
- applyMethod: "pending-reboot",
- },
- {
- name: "max_slot_wal_keep_size",
- value: "10240",
- applyMethod: "pending-reboot",
- },
- {
- name: "rds.force_ssl",
- value: "0",
- applyMethod: "pending-reboot",
- },
- {
- name: "max_connections",
- value: "1000",
- applyMethod: "pending-reboot",
- },
- ],
- },
- },
- });
-
-
-new sst.x.DevCommand("Studio", {
- link: [postgres],
- dev: {
- command: "bun db:dev studio",
- directory: "packages/core",
- autostart: true,
- },
-});
-
-// const migrator = new sst.aws.Function("DatabaseMigrator", {
-// handler: "packages/functions/src/migrator.handler",
-// link: [postgres],
-// copyFiles: [
-// {
-// from: "packages/core/migrations",
-// to: "./migrations",
-// },
-// ],
-// });
-
-// if (!$dev) {
-// new aws.lambda.Invocation("DatabaseMigratorInvocation", {
-// input: Date.now().toString(),
-// functionName: migrator.name,
-// });
-// }
diff --git a/infra/realtime.ts b/infra/realtime.ts
deleted file mode 100644
index 8f7b2bb6..00000000
--- a/infra/realtime.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// import { auth } from "./auth";
-import { postgres } from "./postgres";
-
-export const device = new sst.aws.Realtime("Realtime", {
- authorizer: {
- link: [ postgres],
- handler: "packages/functions/src/realtime/authorizer.handler"
- }
-})
\ No newline at end of file
diff --git a/infra/secret.ts b/infra/secret.ts
deleted file mode 100644
index ddadb712..00000000
--- a/infra/secret.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export const secret = {
- PolarSecret: new sst.Secret("PolarSecret", process.env.POLAR_API_KEY),
- SteamApiKey: new sst.Secret("SteamApiKey"),
- GithubClientID: new sst.Secret("GithubClientID"),
- DiscordClientID: new sst.Secret("DiscordClientID"),
- PolarWebhookSecret: new sst.Secret("PolarWebhookSecret"),
- GithubClientSecret: new sst.Secret("GithubClientSecret"),
- DiscordClientSecret: new sst.Secret("DiscordClientSecret"),
-
- // Pricing
- NestriFreeMonthly: new sst.Secret("NestriFreeMonthly"),
- NestriProMonthly: new sst.Secret("NestriProMonthly"),
- NestriProYearly: new sst.Secret("NestriProYearly"),
- NestriFamilyMonthly: new sst.Secret("NestriFamilyMonthly"),
- NestriFamilyYearly: new sst.Secret("NestriFamilyYearly"),
-};
-
-export const allSecrets = Object.values(secret);
\ No newline at end of file
diff --git a/infra/stage.ts b/infra/stage.ts
deleted file mode 100644
index 3f4f5335..00000000
--- a/infra/stage.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export const isPermanentStage =
- $app.stage === "production" || $app.stage === "dev";
\ No newline at end of file
diff --git a/infra/storage.ts b/infra/storage.ts
deleted file mode 100644
index ef5af0c6..00000000
--- a/infra/storage.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const storage = new sst.aws.Bucket("Storage");
\ No newline at end of file
diff --git a/infra/vpc.ts b/infra/vpc.ts
deleted file mode 100644
index 1af7b7b7..00000000
--- a/infra/vpc.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { isPermanentStage } from "./stage";
-
-export const vpc = isPermanentStage
- ? new sst.aws.Vpc("VPC", {
- az: 2,
- // For lambdas to work in this VPC
- nat: "ec2",
- // For SST tunnel to work
- bastion: true,
- })
- : sst.aws.Vpc.get("VPC", "vpc-0beb1cdc21a725748");
\ No newline at end of file
diff --git a/infra/www.ts b/infra/www.ts
deleted file mode 100644
index 360c373f..00000000
--- a/infra/www.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// This is the website part where people play and connect
-import { api } from "./api";
-import { auth } from "./auth";
-import { zero } from "./zero";
-import { domain } from "./dns";
-
-new sst.aws.StaticSite("Web", {
- path: "packages/www",
- build: {
- output: "./dist",
- command: "bun run build",
- },
- domain: {
- dns: sst.cloudflare.dns(),
- name: "console." + domain
- },
- environment: {
- VITE_API_URL: api.url,
- VITE_STAGE: $app.stage,
- VITE_AUTH_URL: auth.url,
- VITE_ZERO_URL: zero.url,
- },
-})
\ No newline at end of file
diff --git a/infra/zero.ts b/infra/zero.ts
deleted file mode 100644
index ff8755a8..00000000
--- a/infra/zero.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-import { auth } from "./auth";
-import { domain } from "./dns";
-import { readFileSync } from "fs";
-import { cluster } from "./cluster";
-import { storage } from "./storage";
-import { postgres } from "./postgres";
-
-const connectionString = $interpolate`postgresql://${postgres.username}:${postgres.password}@${postgres.host}:${postgres.port}/${postgres.database}`;
-
-const tag = $dev
- ? `latest`
- : JSON.parse(
- readFileSync("./node_modules/@rocicorp/zero/package.json").toString(),
- ).version.replace("+", "-");
-
-const zeroEnv = {
- FORCE: "1",
- NO_COLOR: "1",
- ZERO_LOG_LEVEL: "info",
- ZERO_LITESTREAM_LOG_LEVEL: "info",
- ZERO_UPSTREAM_DB: connectionString,
- ZERO_IMAGE_URL: `rocicorp/zero:${tag}`,
- ZERO_CVR_DB: connectionString,
- ZERO_CHANGE_DB: connectionString,
- ZERO_REPLICA_FILE: "/tmp/nestri.db",
- ZERO_LITESTREAM_RESTORE_PARALLELISM: "64",
- ZERO_APP_ID: $app.stage,
- ZERO_AUTH_JWKS_URL: $interpolate`${auth.url}/.well-known/jwks.json`,
- ZERO_INITIAL_SYNC_ROW_BATCH_SIZE: "30000",
- NODE_OPTIONS: "--max-old-space-size=8192",
- ...($dev
- ? {
- }
- : {
- ZERO_LITESTREAM_BACKUP_URL: $interpolate`s3://${storage.name}/zero/0`,
- }),
-};
-
-// Replication Manager Service
-const replicationManager = !$dev
- ? new sst.aws.Service(`ZeroReplication`, {
- cluster,
- wait: true,
- cpu: "0.5 vCPU",
- memory: "1 GB",
- capacity: "spot",
- architecture: "arm64",
- image: zeroEnv.ZERO_IMAGE_URL,
- link: [storage, postgres],
- health: {
- command: ["CMD-SHELL", "curl -f http://localhost:4849/ || exit 1"],
- interval: "5 seconds",
- retries: 3,
- startPeriod: "300 seconds",
- },
- environment: {
- ...zeroEnv,
- ZERO_CHANGE_MAX_CONNS: "3",
- ZERO_NUM_SYNC_WORKERS: "0",
- },
- logging: {
- retention: "1 month",
- },
- loadBalancer: {
- public: false,
- ports: [
- {
- listen: "80/http",
- forward: "4849/http",
- },
- ],
- },
- transform: {
- loadBalancer: {
- idleTimeout: 3600,
- },
- service: {
- healthCheckGracePeriodSeconds: 900,
- },
- },
- }) : undefined;
-
-// Permissions deployment
-// const permissions = new sst.aws.Function(
-// "ZeroPermissions",
-// {
-// vpc,
-// link: [postgres],
-// handler: "packages/functions/src/zero.handler",
-// // environment: { ["ZERO_UPSTREAM_DB"]: connectionString },
-// copyFiles: [{
-// from: "packages/zero/permissions.sql",
-// to: "./.permissions.sql"
-// }],
-// }
-// );
-
-// if (replicationManager) {
-// new aws.lambda.Invocation(
-// "ZeroPermissionsInvocation",
-// {
-// input: Date.now().toString(),
-// functionName: permissions.name,
-// },
-// { dependsOn: replicationManager }
-// );
-// // new command.local.Command(
-// // "ZeroPermission",
-// // {
-// // dir: process.cwd() + "/packages/zero",
-// // environment: {
-// // ZERO_UPSTREAM_DB: connectionString,
-// // },
-// // create: "bun run zero-deploy-permissions",
-// // triggers: [Date.now()],
-// // },
-// // {
-// // dependsOn: [replicationManager],
-// // },
-// // );
-// }
-
-export const zero = new sst.aws.Service("Zero", {
- cluster,
- image: zeroEnv.ZERO_IMAGE_URL,
- link: [storage, postgres],
- architecture: "arm64",
- cpu: "0.5 vCPU",
- memory: "1 GB",
- capacity: "spot",
- environment: {
- ...zeroEnv,
- ...($dev
- ? {
- ZERO_NUM_SYNC_WORKERS: "1",
- }
- : {
- ZERO_CHANGE_STREAMER_URI: replicationManager.url.apply((val) =>
- val.replace("http://", "ws://"),
- ),
- ZERO_UPSTREAM_MAX_CONNS: "15",
- ZERO_CVR_MAX_CONNS: "160",
- }),
- },
- health: {
- retries: 3,
- command: ["CMD-SHELL", "curl -f http://localhost:4848/ || exit 1"],
- interval: "5 seconds",
- startPeriod: "300 seconds",
- },
- loadBalancer: {
- domain: {
- name: "zero." + domain,
- dns: sst.cloudflare.dns()
- },
- rules: [
- { listen: "443/https", forward: "4848/http" },
- { listen: "80/http", forward: "4848/http" },
- ],
- },
- scaling: {
- min: 1,
- max: 4,
- },
- logging: {
- retention: "1 month",
- },
- transform: {
- service: {
- healthCheckGracePeriodSeconds: 900,
- },
- // taskDefinition: {
- // ephemeralStorage: {
- // sizeInGib: 200,
- // },
- // },
- loadBalancer: {
- idleTimeout: 3600,
- },
- },
- dev: {
- command: "bun dev",
- directory: "packages/zero",
- url: "http://localhost:4848",
- },
-});
\ No newline at end of file
diff --git a/packages/web/.astro/content-assets.mjs b/packages/web/.astro/content-assets.mjs
new file mode 100644
index 00000000..2b8b8234
--- /dev/null
+++ b/packages/web/.astro/content-assets.mjs
@@ -0,0 +1 @@
+export default new Map();
\ No newline at end of file
diff --git a/packages/web/.astro/content-modules.mjs b/packages/web/.astro/content-modules.mjs
new file mode 100644
index 00000000..2b8b8234
--- /dev/null
+++ b/packages/web/.astro/content-modules.mjs
@@ -0,0 +1 @@
+export default new Map();
\ No newline at end of file
diff --git a/packages/web/.astro/data-store.json b/packages/web/.astro/data-store.json
new file mode 100644
index 00000000..c42784d5
--- /dev/null
+++ b/packages/web/.astro/data-store.json
@@ -0,0 +1 @@
+[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.11.2","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false},\"legacy\":{\"collections\":false}}"]
\ No newline at end of file
diff --git a/packages/web/.astro/settings.json b/packages/web/.astro/settings.json
new file mode 100644
index 00000000..8fa98c8f
--- /dev/null
+++ b/packages/web/.astro/settings.json
@@ -0,0 +1,5 @@
+{
+ "_variables": {
+ "lastUpdateCheck": 1752741260450
+ }
+}
\ No newline at end of file
diff --git a/packages/web/.astro/types.d.ts b/packages/web/.astro/types.d.ts
new file mode 100644
index 00000000..f964fe0c
--- /dev/null
+++ b/packages/web/.astro/types.d.ts
@@ -0,0 +1 @@
+///
From 2db52f107e5f476dc347f6611900a0a27d3575e7 Mon Sep 17 00:00:00 2001
From: Wanjohi
Date: Sat, 19 Jul 2025 00:08:57 +0300
Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9D=20docs:=20Start=20work=20on=20?=
=?UTF-8?q?the=20README?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 24 ++++++++---
packages/web/public/logo.black.svg | 65 ++++++++++++++++++++++++++++++
packages/web/public/logo.white.svg | 65 ++++++++++++++++++++++++++++++
3 files changed, 148 insertions(+), 6 deletions(-)
create mode 100644 packages/web/public/logo.black.svg
create mode 100644 packages/web/public/logo.white.svg
diff --git a/README.md b/README.md
index 7ccbd4b0..25d1ca7d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,18 @@
-# nestri
-
-Opensource and selfhostable cloud gaming platform
-
-> TIP
-> TODO: Finish up on this README
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+Deploy and stream games or apps in the cloud. Use our GPU or bring your own.
+
+
+
+
+
+
diff --git a/packages/web/public/logo.black.svg b/packages/web/public/logo.black.svg
new file mode 100644
index 00000000..36cf3fb9
--- /dev/null
+++ b/packages/web/public/logo.black.svg
@@ -0,0 +1,65 @@
+
+
+
+
diff --git a/packages/web/public/logo.white.svg b/packages/web/public/logo.white.svg
new file mode 100644
index 00000000..3de4a9e6
--- /dev/null
+++ b/packages/web/public/logo.white.svg
@@ -0,0 +1,65 @@
+
+
+
+
From 8a02f019e9b5d31f59d7f74caf76e9fa079a9e71 Mon Sep 17 00:00:00 2001
From: Wanjohi
Date: Sat, 19 Jul 2025 00:12:03 +0300
Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=90=9C=C3=B0=C2=9F=20fix(readme):=20R?=
=?UTF-8?q?emoving=20unnecessary=20filetype=20annotation=20fixes=20media?=
=?UTF-8?q?=20query?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 25d1ca7d..57d74165 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-
-
+
+
@@ -15,4 +15,4 @@
-
+
From a2461cf59d0db89220e3563a145c86121c8c9ff1 Mon Sep 17 00:00:00 2001
From: Wanjohi
Date: Sat, 19 Jul 2025 12:23:59 +0300
Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9C=20fix(readme):=20Fix=20wording?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 57d74165..c5a18ffe 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
-Deploy and stream games or apps in the cloud. Use our GPU or bring your own.
+Deploy and stream games/apps in the cloud. Use our GPUs or bring your own.
@@ -15,4 +15,9 @@
-
+
+
+
+
+
+