write an actual readme

Changed files
+106 -76
src
+47 -30
README.md
···
-
# Astro Starter Kit: Minimal
+
# Fanfics on AtProto
+
+
## Background
+
+
This was an idea that sparked off a great discussion around decentralizing archives for fanfics and fan works. What if we could have archives that:
+
+
1. ... are censorship resistant,
+
2. ... are easy (and CHEAP) to host,
+
3. ... are easy to configure and extend,
+
4. ... have moderation tools built-in,
+
5. ... give users on both sides (authors AND readers) more ownership over their data,
+
6. ... AND have a cool sixth thing here!
+
+
I'm setting out to explore these questions by building a prototype of a fanfic archive on Astro and AtProto.
+
+
## Infrastructure
+
+
### Notes
+
+
AtProto, to my understanding, is made of multiple layers. There's:
+
+
1. The client (the actual site that displays data)
+
2. The PDS (the server that stores user's data)
+
3. The AppView (the thing that grabs only relevant data)
+
4. The Lexicon (the blueprint for data to be used in AppViews and clients)
+
+
... And probably more, and there's a lot of discussion around how user data ownership / censorship / etc gets handled on those layers.
+
+
In our case, we'll only worry about making the client and then get drafts of the lexicons from the community later.
+
+
Currently, I'm using these technologies:
-
```sh
-
bun create astro@latest -- --template minimal
-
```
+
- Astro
+
- Drizzle ORM
+
- Turso
+
- Unstorage
-
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
+
Mainly because: 1, Astro is a really well-documented web framework that's pretty approachable as someone who used to handwrite HTML pages; 2, SQLite / LibSQL are (to my knowledge) fairly cheap databases to run; and 3, Unstorage is pretty dead simple for setting up auth sessions from scratch.
-
## 🚀 Project Structure
+
### Structure
-
Inside of your Astro project, you'll see the following folders and files:
+
#### `src/actions`
-
```text
-
/
-
├── public/
-
├── src/
-
│ └── pages/
-
│ └── index.astro
-
└── package.json
-
```
+
These hold actions that run every time a user wants to publish a new work or signs up for the archive.
-
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
+
#### `src/assets`
-
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
+
This has images / libre font / `.css` files to be used stylistically throughout the site.
-
Any static assets, like images, can be placed in the `public/` directory.
+
#### `src/components`
-
## 🧞 Commands
+
These hold components that are reused throughout `src/pages`. Like PHP includes but in HTML and JavaScript (well, technically it's JSX).
-
All commands are run from the root of the project, from a terminal:
+
#### `src/lib/db`
-
| Command | Action |
-
| :------------------------ | :----------------------------------------------- |
-
| `bun install` | Installs dependencies |
-
| `bun dev` | Starts local dev server at `localhost:4321` |
-
| `bun build` | Build your production site to `./dist/` |
-
| `bun preview` | Preview your build locally, before deploying |
-
| `bun astro ...` | Run CLI commands like `astro add`, `astro check` |
-
| `bun astro -- --help` | Get help using the Astro CLI |
+
This holds all the relevant database connecting code. This also contains the types for database tables.
-
## 👀 Want to learn more?
+
#### `src/pages`
-
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
+
These are the actual pages where data, user interactions, etc happen. So this would be more HTML/CSS/JavaScript-oriented.
-46
src/lib/db.ts
···
-
import { DB_URL, DB_TOKEN } from "astro:env/server";
-
-
import { createDatabase } from "db0";
-
import { createStorage } from "unstorage";
-
import dbDriver from "unstorage/drivers/db0";
-
import libSqlConnector from "db0/connectors/libsql/web";
-
import { drizzle } from "db0/integrations/drizzle";
-
import { sqliteTable, int, text } from "drizzle-orm/sqlite-core";
-
-
export const database = createDatabase(
-
libSqlConnector({
-
url: DB_URL,
-
...import.meta.env.PROD && { authToken: DB_TOKEN },
-
})
-
);
-
-
export const driver = drizzle(database);
-
-
export const storage = createStorage({
-
driver: dbDriver({
-
database,
-
tableName: "fanfic_archive",
-
}),
-
});
-
-
export const usersTable = sqliteTable("users_table", {
-
id: int().primaryKey({ autoIncrement: true }),
-
handle: text().notNull(),
-
userDid: text().notNull(),
-
});
-
-
export const worksTable = sqliteTable("works_table", {
-
id: int().primaryKey({ autoIncrement: true }),
-
author: text(),
-
// recordkey
-
title: text(),
-
body: text(),
-
});
-
-
export const tagsTable = sqliteTable("tags_table", {
-
id: int().primaryKey({ autoIncrement: true }),
-
label: text(),
-
// rkey
-
class: text(),
-
// classrkey?
-
});
+12
src/lib/db/drizzle.config.ts
···
+
import { DB_URL, DB_TOKEN } from "astro:env/server";
+
import { defineConfig } from "drizzle-kit";
+
+
export default defineConfig({
+
dialect: "turso",
+
schema: "./schema.ts",
+
out: "./migrations",
+
dbCredentials: {
+
url: DB_URL,
+
authToken: DB_TOKEN,
+
},
+
});
+24
src/lib/db/index.ts
···
+
import { DB_URL, DB_TOKEN } from "astro:env/server";
+
+
import { createDatabase } from "db0";
+
import { createStorage } from "unstorage";
+
import dbDriver from "unstorage/drivers/db0";
+
import libSqlConnector from "db0/connectors/libsql/node";
+
import { drizzle } from "db0/integrations/drizzle";
+
+
export const database = createDatabase(
+
libSqlConnector({
+
url: DB_URL,
+
...import.meta.env.PROD && { authToken: DB_TOKEN },
+
+
})
+
);
+
+
export const driver = drizzle(database);
+
+
export const storage = createStorage({
+
driver: dbDriver({
+
database,
+
tableName: "fanfic_archive",
+
}),
+
});
+23
src/lib/db/schema.ts
···
+
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
+
+
export const usersTable = sqliteTable("users_table", {
+
id: int().primaryKey({ autoIncrement: true }),
+
handle: text().notNull(),
+
userDid: text().notNull(),
+
});
+
+
export const worksTable = sqliteTable("works_table", {
+
id: int().primaryKey({ autoIncrement: true }),
+
author: text(),
+
// recordkey
+
title: text(),
+
body: text(),
+
});
+
+
export const tagsTable = sqliteTable("tags_table", {
+
id: int().primaryKey({ autoIncrement: true }),
+
label: text(),
+
// rkey
+
class: text(),
+
// classrkey?
+
});