···97979898### Application Variables
9999100100-Most of the application can be modified either through the `wrangler.toml` vars section or via `src/limits.d.ts`. These are usually heavily commented to explain what the options control.
100100+Most of the application can be modified either through the `wrangler.toml` vars section or via `src/limits.ts`. These are usually heavily commented to explain what the options control.
101101102102### Minimization
103103104104-The application by default is configured to use the minified versions of the scripts in `assets/js`. You can either turn off this behavior in `src/limits.d.ts` or run `npm run minify` whenever those files change.
104104+The application by default is configured to use the minified versions of the scripts in `assets/js`. You can either turn off this behavior in `src/limits.ts` or run `npm run minify` whenever those files change.
105105106106## Project Structure
107107
+1-1
src/auth/index.ts
···44import { username } from "better-auth/plugins";
55import { drizzle } from "drizzle-orm/d1";
66import { schema } from "../db";
77-import { BSKY_MAX_USERNAME_LENGTH, BSKY_MIN_USERNAME_LENGTH } from "../limits.d";
77+import { BSKY_MAX_USERNAME_LENGTH, BSKY_MIN_USERNAME_LENGTH } from "../limits";
88import { Bindings } from "../types";
99import { lookupBskyHandle } from "../utils/bskyApi";
1010import { createDMWithUser } from "../utils/bskyMsg";
+1-1
src/endpoints/preview.tsx
···22import { secureHeaders } from "hono/secure-headers";
33import isEmpty from "just-is-empty";
44import { ContextVariables } from "../auth";
55-import { BSKY_IMG_MIME_TYPES } from "../limits.d";
55+import { BSKY_IMG_MIME_TYPES } from "../limits";
66import { authMiddleware } from "../middleware/auth";
77import { corsHelperMiddleware } from "../middleware/corsHelper";
88import { Bindings } from "../types.d";
+1-1
src/layout/altTextModal.tsx
···11-import { MAX_ALT_TEXT } from "../limits.d";
11+import { MAX_ALT_TEXT } from "../limits";
2233export function AltTextDialog() {
44 return (
+1-1
src/layout/editPost.tsx
···11-import { MAX_LENGTH } from "../limits.d";
11+import { MAX_LENGTH } from "../limits";
22import { EmbedDataType, Post } from "../types.d";
33import { PostContentObject } from "./postList";
44
+1-1
src/layout/makePost.tsx
···88 MAX_LENGTH,
99 MAX_THUMBNAIL_SIZE,
1010 R2_FILE_SIZE_LIMIT_IN_MB
1111-} from "../limits.d";
1111+} from "../limits";
1212import { PreloadRules } from "../types.d";
1313import { ConstScriptPreload } from "../utils/constScriptGen";
1414import { DependencyTags } from "./depTags";
+1-1
src/layout/passwordFields.tsx
···11import { html } from "hono/html";
22-import { BSKY_MAX_APP_PASSWORD_LENGTH, MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
22+import { BSKY_MAX_APP_PASSWORD_LENGTH, MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
33import { PWAutoCompleteSettings } from "../types.d";
44import { appPasswordRegex } from "../validation/regexCases";
55
+1-1
src/layout/retweetOptions.tsx
···11import isEmpty from "just-is-empty";
22-import { MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL_LIMIT } from "../limits.d";
22+import { MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL_LIMIT } from "../limits";
3344type RetweetOptionsProps = {
55 id: string;
+1-1
src/layout/settings.tsx
···11-import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
11+import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
22import { PWAutoCompleteSettings } from "../types.d";
33import { settingsScriptStr } from "../utils/appScripts";
44import { BSkyAppPasswordField, DashboardPasswordField } from "./passwordFields";
+1-1
src/layout/usernameField.tsx
···11import { raw } from "hono/html";
22-import { BSKY_MIN_USERNAME_LENGTH } from "../limits.d";
22+import { BSKY_MIN_USERNAME_LENGTH } from "../limits";
3344type UsernameFieldProps = {
55 title?: string;
+1-1
src/limits.d.ts
src/limits.ts
···1212// max length of an animated gif in minutes
1313export const MAX_GIF_LENGTH: number = 1;
1414// if gifs should be allowed to upload
1515-export const GIF_UPLOAD_ALLOWED: boolean = false;
1515+export const GIF_UPLOAD_ALLOWED: boolean = true;
16161717// This is the length of how much we keep in the DB after a post has been made
1818export const MAX_POSTED_LENGTH: number = 50;
+1-1
src/pages/homepage.tsx
···11import FooterCopyright from "../layout/footer";
22import { BaseLayout } from "../layout/main";
33import NavTags from "../layout/navTags";
44-import { MAX_REPOST_DAYS, MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL, R2_FILE_SIZE_LIMIT_IN_MB } from "../limits.d";
44+import { MAX_REPOST_DAYS, MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL, R2_FILE_SIZE_LIMIT_IN_MB } from "../limits";
5566export default function Home() {
77 return (
+1-1
src/pages/reset.tsx
···11import AccountHandler from "../layout/account";
22import { BaseLayout } from "../layout/main";
33import NavTags from "../layout/navTags";
44-import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
44+import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
5566export default function ResetPassword() {
77 const links = [{title: "Forgot Password", url: "/forgot"}];
+1-1
src/pages/signup.tsx
···66import { BSkyAppPasswordField, DashboardPasswordField } from "../layout/passwordFields";
77import { TurnstileCaptcha, TurnstileCaptchaPreloads } from "../layout/turnstile";
88import { UsernameField } from "../layout/usernameField";
99-import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
99+import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
1010import { PWAutoCompleteSettings } from "../types.d";
1111import { getInviteThread, isUsingInviteKeys } from "../utils/inviteKeys";
1212
+1-1
src/utils/bskyApi.ts
···44import has from 'just-has';
55import isEmpty from "just-is-empty";
66import truncate from "just-truncate";
77-import { BSKY_IMG_SIZE_LIMIT, MAX_ALT_TEXT, MAX_EMBEDS_PER_POST, MAX_POSTED_LENGTH } from '../limits.d';
77+import { BSKY_IMG_SIZE_LIMIT, MAX_ALT_TEXT, MAX_EMBEDS_PER_POST, MAX_POSTED_LENGTH } from '../limits';
88import {
99 Bindings, BskyEmbedWrapper, BskyRecordWrapper, EmbedData, EmbedDataType,
1010 LooseObj, PlatformLoginResponse, Post, PostLabel,
+1-1
src/utils/constScriptGen.ts
···1111 MAX_THUMBNAIL_SIZE,
1212 R2_FILE_SIZE_LIMIT,
1313 GIF_UPLOAD_ALLOWED
1414-} from "../limits.d";
1414+} from "../limits";
1515import { PreloadRules } from "../types.d";
1616import { postRecordURI } from "../validation/regexCases";
1717
+1-1
src/utils/dbQuery.ts
···1313import { v4 as uuidv4, validate as uuidValid } from 'uuid';
1414import { mediaFiles, posts, repostCounts, reposts, violations } from "../db/app.schema";
1515import { accounts, users } from "../db/auth.schema";
1616-import { MAX_HOLD_DAYS_BEFORE_PURGE, MAX_POSTED_LENGTH, MAX_REPOST_POSTS } from "../limits.d";
1616+import { MAX_HOLD_DAYS_BEFORE_PURGE, MAX_POSTED_LENGTH, MAX_REPOST_POSTS } from "../limits";
1717import {
1818 BatchQuery,
1919 Bindings, BskyAPILoginCreds, CreateObjectResponse, CreatePostQueryResponse,
+1-1
src/utils/r2Query.ts
···1313 MB_TO_BYTES,
1414 R2_FILE_SIZE_LIMIT,
1515 R2_FILE_SIZE_LIMIT_IN_MB
1616-} from "../limits.d";
1616+} from "../limits";
1717import { Bindings, EmbedData, EmbedDataType, R2BucketObject, ScheduledContext } from '../types.d';
1818import { addFileListing, deleteFileListings } from './dbQueryFile';
1919
+1-1
src/validation/accountResetSchema.ts
···11import * as z from "zod/v4";
22-import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
22+import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits";
3344export const AccountResetSchema = z.object({
55 resetToken: z.string().nonempty("reset token is missing!"),
+1-1
src/validation/accountUpdateSchema.ts
···22import {
33 BSKY_MAX_APP_PASSWORD_LENGTH, BSKY_MIN_USERNAME_LENGTH,
44 MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS
55-} from "../limits.d";
55+} from "../limits";
66import { appPasswordRegex } from "./regexCases";
7788export const AccountUpdateSchema = z.object({
+1-1
src/validation/embedSchema.ts
···11import isEmpty from "just-is-empty";
22import * as z from "zod/v4";
33-import { BSKY_VIDEO_LENGTH_LIMIT } from "../limits.d";
33+import { BSKY_VIDEO_LENGTH_LIMIT } from "../limits";
44import { EmbedDataType } from "../types.d";
55import { FileContentSchema } from "./mediaSchema";
66import { atpRecordURI } from "./regexCases";
+1-1
src/validation/postSchema.ts
···11import * as z from "zod/v4";
22-import { MAX_LENGTH, MAX_REPOST_INTERVAL_LIMIT, MAX_REPOST_IN_HOURS, MIN_LENGTH } from "../limits.d";
22+import { MAX_LENGTH, MAX_REPOST_INTERVAL_LIMIT, MAX_REPOST_IN_HOURS, MIN_LENGTH } from "../limits";
33import { EmbedDataType, PostLabel } from "../types.d";
44import { ImageEmbedSchema, LinkEmbedSchema, PostRecordSchema, VideoEmbedSchema } from "./embedSchema";
55import { FileContentSchema } from "./mediaSchema";
+1-1
src/validation/repostSchema.ts
···11import * as z from "zod/v4";
22-import { MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL_LIMIT } from "../limits.d";
22+import { MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL_LIMIT } from "../limits";
33import { atProtoPostURI, postRecordURI } from "./regexCases";
4455export const RepostSchema = z.object({
+1-1
src/validation/sharedValidations.ts
···55 BSKY_MIN_USERNAME_LENGTH,
66 MAX_ALT_TEXT,
77 MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS
88-} from "../limits.d";
88+} from "../limits";
99import { appPasswordRegex } from "./regexCases";
10101111export const UsernameSchema = z.object({