Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Our images #638

Merged
merged 7 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ publish-experimental:
./scripts/publish_packages.clj experimental

build-email:
$(MAKE) replace-email-images
$(MAKE) text-email
$(MAKE) html-email

replace-email-images:
echo "Replacing images..."
cd www/_emails/replace-images && pnpm i
node www/_emails/replace-images/index.mjs $(slug)

text-email:
echo "Generating text verison of email..."
sed -e 's/!\[[^]]*\]([^)]*)//g' www/_emails/markdown/$(slug).md | sed '/^$$/N;/^\n$$/D' > www/_emails/txt/$(slug).txt
Expand Down
12 changes: 6 additions & 6 deletions client/www/_emails/html/nov2024.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png" /></p>
src="https://www.instantdb.com/img/emails/nov2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png" /></p>
<p>Hey crew! It’s time for another edition of Instant News 🙂 Here’s a
slice of what happened in November!</p>
<p><strong>Announcing enforced types on the backend</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450241867_image.png" /></p>
src="https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450241867_image.png" /></p>
<p>Previously you could define types for intellisense but there wasn’t a
way to strictly enforce them on the backend. You can now define these
attributes in <a href="https://www.instantdb.com/docs/schema">code</a>,
Expand All @@ -15,7 +15,7 @@
your schema we’ve got you covered :)</p>
<p>C<strong>omparison operators in InstaQL</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450981289_image.png" /></p>
src="https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450981289_image.png" /></p>
<p>With typed attributes, queries get more powerful too. Starting from
<code>v0.16.0</code> You can use <a
href="https://www.instantdb.com/docs/instaql#comparison-operators">comparison
Expand All @@ -26,7 +26,7 @@
to index attributes for comparison, which end up being footguns)</p>
<p><strong>Fuzzy-search in InstaQL</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451107349_image.png" /></p>
src="https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451107349_image.png" /></p>
<p>With indexing and comparison operators landing, it was a fast-follow
to also enable <code>$like</code> queries!. When you index your string
fields, you can now use things like <code>startsWith</code>,
Expand All @@ -39,10 +39,10 @@
<code>$default</code> keyword it’ll be much easier to apply the same set
of rules across actions and namespaces :)</p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451831476_image.png" /></p>
src="https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451831476_image.png" /></p>
<p><strong>Instant at Clojure Conj 2024</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733449686289_image.png" /></p>
src="https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733449686289_image.png" /></p>
<p>In last month’s edition we mentioned that Stopa (CTO of Instant) was
giving a talk at Clojure Conj 2024. Super excited to share that the
video has now been uploaded!</p>
Expand Down
12 changes: 6 additions & 6 deletions client/www/_emails/html/oct2024.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png" /></p>
src="https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png" /></p>
<p>Hello and welcome to Instant’s first newsletter! We’re going to start
sending you updates every month to keep you in the loop with what’s new
:)</p>
Expand All @@ -8,7 +8,7 @@
Francisco, and are actively hiring! More info below :)</p>
<p><strong>Open Source</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729122912083_image.png" /></p>
src="https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729122912083_image.png" /></p>
<p>We were heads down for two years before we finally open sourced at
the end of August. The same day we announced on Hacker News and had one
of the <a href="https://news.ycombinator.com/item?id=41322281">biggest
Expand All @@ -19,7 +19,7 @@
energizing to hear your feedback and we’re excited to grow with you!</p>
<p><strong>Fundraising Announcement</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_B8A06116D3803694CDA0C13F9F97E92EA0220D4E377317F0F00D7831E3E41E9E_1727988124731_image.png" /></p>
src="https://www.instantdb.com/img/emails/oct2024/s_B8A06116D3803694CDA0C13F9F97E92EA0220D4E377317F0F00D7831E3E41E9E_1727988124731_image.png" /></p>
<p>A month after open sourcing we announced <a
href="https://techcrunch.com/2024/10/02/instant-harkens-back-to-a-pre-google-firebase/">our
fundraising on Techcrunch</a>. We’re honored to be backed by these
Expand All @@ -29,7 +29,7 @@
out our <a href="https://instantdb.com/hiring">hiring page</a>.</p>
<p><strong>Clojure Conj 2024</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729123513053_image.png" /></p>
src="https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729123513053_image.png" /></p>
<p>Our very own Stopa (CTO of Instant), gave a talk about building
Instant at <a href="https://2024.clojure-conj.org/">Clojure Conj</a>
last week! This is the oldest gathering of the Clojure community, which
Expand All @@ -40,7 +40,7 @@
when the video is ready!</p>
<p><strong>Announcing $users table!</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244149277_users_table.png" /></p>
src="https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244149277_users_table.png" /></p>
<p>With Instant, whether it’s magic codes, Google OAuth, or the Clerk
integration, you can set up auth in a few minutes. But where did those
users live? What if you wanted to query your users, or link them to
Expand All @@ -53,7 +53,7 @@
docs</a>.</p>
<p><strong>Announcing queryOnce!</strong></p>
<p><img
src="https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244001267_image.png" /></p>
src="https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244001267_image.png" /></p>
<p><code>useQuery</code> is great, but sometimes you just want to get a
query…once. Well now you can via <code>queryOnce</code></p>
<p>This has been one of the most requested functions on Instant. It’s
Expand Down
27 changes: 8 additions & 19 deletions client/www/_emails/markdown/nov2024.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,42 @@
![](https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png)

![](https://www.instantdb.com/img/emails/nov2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png)

Hey crew! It’s time for another edition of Instant News 🙂 Here’s a slice of what happened in November!

**Announcing enforced types on the backend**

![](https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450241867_image.png)

![](https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450241867_image.png)

Previously you could define types for intellisense but there wasn’t a way to strictly enforce them on the backend. You can now define these attributes in [code](https://www.instantdb.com/docs/schema), or in the [dashboard](https://www.instantdb.com/dash) and they will be enforced on the backend.

You can still use Instant without defining a schema up-front. This is great for rapid prototyping. Once you’re ready to start locking down your schema we’ve got you covered :)

C**omparison operators in InstaQL**

![](https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450981289_image.png)

![](https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733450981289_image.png)

With typed attributes, queries get more powerful too. Starting from `v0.16.0` You can use [comparison operators](https://www.instantdb.com/docs/instaql#comparison-operators) in your queries!

In order to use comparison operators, you need to set the type and index an attribute. This makes it so any query you write with comparison operators stays fast as heck (Fun fact, most databases will not tell you to index attributes for comparison, which end up being footguns)

**Fuzzy-search in InstaQL**

![](https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451107349_image.png)

![](https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451107349_image.png)

With indexing and comparison operators landing, it was a fast-follow to also enable `$like` queries!. When you index your string fields, you can now use things like `startsWith`, `endsWith`, and `includes` in your InstaQL queries!

**Default Permissions**

All user namespaces have default permissions of true. This makes it easy for getting started. Once you want to start locking down your data model, you’ll likely want to add permission rules. With the `$default` keyword it’ll be much easier to apply the same set of rules across actions and namespaces :)


![](https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451831476_image.png)

![](https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733451831476_image.png)

**Instant at Clojure Conj 2024**

![](https://paper-attachments.dropboxusercontent.com/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733449686289_image.png)

![](https://www.instantdb.com/img/emails/nov2024/s_B097BA2FA68FBDBEF71F30F95558A3D23729AED0A557430F53FE49A682293BBC_1733449686289_image.png)

In last month’s edition we mentioned that Stopa (CTO of Instant) was giving a talk at Clojure Conj 2024. Super excited to share that the video has now been uploaded!

Following up from [A Graph-Based Firebase](https://www.instantdb.com/essays/next_firebase), Stopa discusses the common schleps developers face when building apps, and how Instant compresses them. [Give this a watch](https://youtu.be/6FikTQf8qho?feature=shared&t=8) if you’re interested in learning more about how Instant works under the hood!
Following up from [A Graph-Based Firebase](https://www.instantdb.com/essays/next_firebase), Stopa discusses the common schleps developers face when building apps, and how Instant compresses them. [Give this a watch](https://youtu.be/6FikTQf8qho?feature=shared\&t=8) if you’re interested in learning more about how Instant works under the hood!

**What’s next?**

Expand All @@ -53,8 +46,4 @@ We shipped a ton of platform upgrades in November and we’ve got a slew of upgr

If you’re interested in working on some of the hardest problems for modern app development drop us a line at [email protected] with a resume and a side project you’ve worked on (including a Github is a huge plus!)


![](https://pbs.twimg.com/media/GZd_xO0akAETvju?format=jpg&name=large)



![](https://pbs.twimg.com/media/GZd_xO0akAETvju?format=jpg\&name=large)
20 changes: 7 additions & 13 deletions client/www/_emails/markdown/oct2024.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
![](https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png)
![](https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730238267270_instant_header.png)

Hello and welcome to Instant’s first newsletter! We’re going to start sending you updates every month to keep you in the loop with what’s new :)

Two months ago we launched on Hacker News and open sourced Instant. Since then we’ve announced our fundraising, set up an office in San Francisco, and are actively hiring! More info below :)

**Open Source**

![](https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729122912083_image.png)

![](https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729122912083_image.png)

We were heads down for two years before we finally open sourced at the end of August. The same day we announced on Hacker News and had one of the [biggest show HNs](https://news.ycombinator.com/item?id=41322281) for any YC company, amassing over 1k points. Since then we’ve gotten over [6k Github stars](https://github.com/instantdb/instant) and over 1k of you are now in [the discord](https://discord.com/invite/VU53p7uQcE). It’s energizing to hear your feedback and we’re excited to grow with you!

**Fundraising Announcement**

![](https://paper-attachments.dropboxusercontent.com/s_B8A06116D3803694CDA0C13F9F97E92EA0220D4E377317F0F00D7831E3E41E9E_1727988124731_image.png)

![](https://www.instantdb.com/img/emails/oct2024/s_B8A06116D3803694CDA0C13F9F97E92EA0220D4E377317F0F00D7831E3E41E9E_1727988124731_image.png)

A month after open sourcing we announced [our fundraising on Techcrunch](https://techcrunch.com/2024/10/02/instant-harkens-back-to-a-pre-google-firebase/). We’re honored to be backed by these fantastic technical angels. We now have an office in San Francisco and are actively hiring engineers. If you or someone you know are interested in building infrastructure to power applications of the future, check out our [hiring page](https://instantdb.com/hiring).

**Clojure Conj 2024**

![](https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729123513053_image.png)

![](https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1729123513053_image.png)

Our very own Stopa (CTO of Instant), gave a talk about building Instant at [Clojure Conj](https://2024.clojure-conj.org/) last week! This is the oldest gathering of the Clojure community, which is the language Instant uses on the backend! During this talk Stopa discusses how Instant works under the hood. If you enjoyed reading [A Graph-Based Firebase](https://www.instantdb.com/essays/next_firebase), you’ll love watching this talk. Will follow-up next month when the video is ready!

**Announcing $users table!**

![](https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244149277_users_table.png)
![](https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244149277_users_table.png)

With Instant, whether it’s magic codes, Google OAuth, or the Clerk integration, you can set up auth in a few minutes. But where did those users live? What if you wanted to query your users, or link them to objects?

Well now you get a nifty `$users` table in the explorer to manage your users. You can query, create links, and and even reference `$users` with permissions. These improvements make it much easier to build role-based apps with security! To learn more, [check out our $users docs](https://www.instantdb.com/docs/users).

**Announcing queryOnce!**

![](https://paper-attachments.dropboxusercontent.com/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244001267_image.png)

![](https://www.instantdb.com/img/emails/oct2024/s_DF8F10A9009F2A236BC7D07C4EC05DDA50E4FB82F40AA98593D3B98A1A7EA3DC_1730244001267_image.png)

`useQuery` is great, but sometimes you just want to get a query…once. Well now you can via `queryOnce`

Expand All @@ -52,6 +48,4 @@ Stay tuned :)

We’re a team of 3 right now hacking away in our new San Francisco office and we’re looking to grow! If you’re interested in working on some of the hardest problems for modern app development drop us a line at [email protected] with a resume and a side project you’ve worked on (including a Github is a huge plus!)

![](https://pbs.twimg.com/media/GZd_xO0akAETvju?format=jpg&name=large)


![](https://pbs.twimg.com/media/GZd_xO0akAETvju?format=jpg\&name=large)
66 changes: 66 additions & 0 deletions client/www/_emails/replace-images/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { fileURLToPath } from 'url';
import { dirname, resolve } from 'path';
import { writeFile, readFile, mkdir } from 'node:fs/promises';
import { Readable } from 'node:stream';
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';

const scriptDir = dirname(fileURLToPath(import.meta.url));

// Resolve relative path
const relativePath = (path) => resolve(scriptDir, path);

export async function replaceImages(slug, markdown) {
const processor = unified()
.use(remarkParse)
.use(imgModifier.bind(null, slug))
.use(remarkStringify);

const result = await processor.process(markdown);
return String(result);
}

async function writeImage(slug, href) {
const fileName = new URL(href).pathname;
console.log('downloading image', fileName);
const path = relativePath(`../../public/img/emails/${slug}${fileName}`);
const response = await fetch(href);
const stream = Readable.fromWeb(response.body);
await mkdir(dirname(path), { recursive: true });
await writeFile(path, stream);

return `https://www.instantdb.com/img/emails/${slug}${fileName}`;
}

function imgModifier(slug) {
return async (tree) => {
const visit = async (node) => {
if (Array.isArray(node.children)) {
for (const child of node.children) {
await visit(child);
}
}
if (
node.type === 'image' &&
node.url?.startsWith('https://paper-attachments.dropboxusercontent.com')
) {
const newUrl = await writeImage(slug, node.url);
node.url = newUrl;
}
};
await visit(tree);
};
}

export async function run(slug) {
const path = relativePath(`../markdown/${slug}.md`);
const markdown = await readFile(path);
const updatedMarkdown = await replaceImages(slug, markdown);
await writeFile(path, updatedMarkdown);
}

if (import.meta.url === `file://${process.argv[1]}`) {
const slug = process.argv[2];
await run(slug);
}
18 changes: 18 additions & 0 deletions client/www/_emails/replace-images/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "replace-images",
"version": "1.0.0",
"description": "",
"main": "index.mjs",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"remark": "^15.0.1",
"remark-parse": "^11.0.0",
"remark-stringify": "^11.0.0",
"unified": "^11.0.5"
}
}
Loading
Loading