diff --git a/README.md b/README.md
index 661222a..247aabc 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# at
-https://github.com/bluesky-social/atproto
+- https://github.com/bluesky-social/atproto
+- https://github.com/bluesky-social/atproto/discussions/2026
|word|name|example|
|---|---|---|
@@ -23,7 +24,6 @@ https://github.com/bluesky-social/atproto
```sh
$ curl -sL syu.is/xrpc/_health
-{"version":"0.4.65"}
# latest
# https://github.com/bluesky-social/atproto/blob/main/packages/pds/package.json
@@ -46,12 +46,6 @@ $ curl -sL "syu.is/xrpc/com.atproto.repo.listRecords?repo=ai.syu.is&collection=a
- https://feed.syu.is/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:4hqjfn7m6n5hno3doamuhgef/app.bsky.feed.generator/cmd
- https://desc.syu.is/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/cmd
-## link
-
-- https://github.com/bluesky-social/atproto
-- https://github.com/itaru2622/bluesky-selfhost-env
-- https://github.com/bluesky-social/atproto/discussions/2026
-
## self-host
currently, bsky and bsync require patches to function properly. additionally, social-app is not displaying avatars. for components that are not working, it's recommended to use [itaru2622/bluesky-selfhost-env](https://github.com/itaru2622/bluesky-selfhost-env). this repository provides an environment for self-hosting bluesky.
diff --git a/bin/build-aiat.sh b/bin/build-aiat.sh
new file mode 100755
index 0000000..5f27209
--- /dev/null
+++ b/bin/build-aiat.sh
@@ -0,0 +1,41 @@
+#!/bin/zsh
+set -e
+
+cd ~/ai/at/repos/social-app
+
+# 初回のみ実行: ネイティブプロジェクト生成
+# npx expo prebuild --clean
+# cd ios && pod install && cd ..
+
+## アーカイブ
+xcodebuild -workspace ios/aiat.xcworkspace \
+ -scheme aiat \
+ -configuration Release \
+ -archivePath build/Aiat.xcarchive \
+ -allowProvisioningUpdates \
+ archive
+
+cd build
+
+# IPA作成
+rm -rf Payload Aiat.ipa
+mkdir -p Payload
+cp -R Aiat.xcarchive/Products/Applications/aiat.app Payload/
+cp ../store.mobileprovision Payload/aiat.app/embedded.mobileprovision
+
+# entitlements抽出
+security cms -D -i Payload/aiat.app/embedded.mobileprovision > /tmp/profile.plist
+/usr/libexec/PlistBuddy -x -c "Print :Entitlements" /tmp/profile.plist > /tmp/entitlements.plist
+
+# 署名
+CERT="Apple Distribution: syutaro inagaki (WN6KD5ZT49)"
+codesign -f -s "$CERT" Payload/aiat.app/Frameworks/*.framework 2>/dev/null || true
+codesign -f -s "$CERT" --entitlements /tmp/entitlements.plist Payload/aiat.app
+
+# IPA作成
+zip -r Aiat.ipa Payload
+
+# アップロード
+xcrun altool --upload-app -f Aiat.ipa -t ios -u "syui@syui.ai" -p "@keychain:AC_PASSWORD"
+
+echo "Upload complete"
diff --git a/install.zsh b/install.zsh
index 61e56a3..f737f48 100755
--- a/install.zsh
+++ b/install.zsh
@@ -108,7 +108,8 @@ function at-repos-social-app-avatar-write() {
grep -R syu.is .|cut -d : -f 1|sort -u|xargs sed -i "s/syu.is/${host}/g"
grep -R web.syu.is .|cut -d : -f 1|sort -u|xargs sed -i "s/web.syu.is/web.${host}/g"
f=$dt/lib/constants.ts
- sed -i "s/public.api.web/bsky/g" $f
+ sed -i "s/public.api.bsky.app/bsky.syu.is/g" $f
+ sed -i "s/bsky.social/syu.is/g" $f
f=$dt/view/icons/Logotype.tsx
o=$d/icons/Logotype.tsx
cp -rf $o $f
@@ -156,6 +157,16 @@ function at-repos-social-app-agent-patch() {
popd
}
+function at-repos-social-app-disable-external-services-patch() {
+ f=$d/repos/social-app/src/state/geolocation/const.ts
+ p_=$d/patching/8980-social-app-disable-external-services.diff
+ d_=$d/repos/social-app
+ echo "applying patch: under ${f} for ${p_}"
+ pushd ${d_}
+ patch -p1 < ${p_}
+ popd
+}
+
function at-repos-ozone-patch() {
#DOMAIN=syu.is
cd $d/repos
@@ -188,7 +199,7 @@ function at-repos-build-docker-social() {
docker compose build --no-cache social-app
}
-function at-repos-build-docker-tag() {
+function at-repos-push-docker() {
docker restart registry
docker stop registry
docker rm registry
@@ -230,9 +241,11 @@ function at-repos-pull-docker() {
docker compose up -d --pull always
}
+function at-origin-social-app() {
+ cp -rf $d/social-app-custom $d/repos/social-app
+}
at-repos-env
-
case "`cat /etc/hostname`" in
at)
at-repos-pull-docker
@@ -243,11 +256,103 @@ case "`cat /etc/hostname`" in
at-repos-social-app-icon
at-repos-social-app-icon-origin
at-repos-social-app-avatar-write
+ at-repos-social-app-agent-patch
+ at-repos-social-app-disable-external-services-patch
+ if [ -n "$1" ] && [ "$1" = "social-app-custom" ];then
+ at-social-app-custom-pages
+ at-social-app-custom-screens
+ at-social-app-aiat-config
+ at-social-app-aiat-logo
+ at-origin-social-app
+ exit
+ fi
at-repos-atproto-service-bsky-api-patch
at-repos-atproto-service-pds-index-patch
- at-repos-social-app-agent-patch
at-repos-ozone-patch
- at-repos-build-docker-atproto
at-repos-build-docker-social
+ if [ -n "$1" ] && [ "$1" = "s" ];then
+ docker run -d -p ${dport}:${dport} --name registry --restart=always registry:2
+ docker tag at-social-app:latest localhost:${dport}/social-app:latest
+ docker push localhost:${dport}/social-app:latest
+ exit
+ fi
+ at-repos-build-docker-atproto
+ at-repos-push-docker
;;
esac
+
+function at-social-app-custom-pages() {
+ d_=$d/repos/social-app
+ custom=$d/social-app-custom
+
+ echo "copying custom components to social-app"
+
+ # Create components directory if not exists
+ mkdir -p ${d_}/src/components/custom
+
+ # Copy custom components
+ cp ${custom}/PrivacyContent.tsx ${d_}/src/components/custom/
+ cp ${custom}/AppInfo.tsx ${d_}/src/components/custom/
+
+ echo "custom components copied successfully"
+}
+
+function at-social-app-aiat-config() {
+ d_=$d/repos/social-app
+ custom=$d/social-app-custom
+
+ echo "applying Aiat configuration"
+
+ # Update app.config.js
+ cd ${d_}
+
+ # Backup original
+ cp app.config.js app.config.js.orig
+
+ # Apply changes using sed
+ sed -i "s/name: 'Bluesky'/name: 'Aiat'/g" app.config.js
+ sed -i "s/slug: 'bluesky'/slug: 'aiat'/g" app.config.js
+ sed -i "s/scheme: 'bluesky'/scheme: 'aiat'/g" app.config.js
+ sed -i "s/owner: 'blueskysocial'/owner: 'syui'/g" app.config.js
+ sed -i "s/bundleIdentifier: 'xyz.blueskyweb.app'/bundleIdentifier: 'ai.syui.at'/g" app.config.js
+
+ # Update package.json name
+ sed -i 's/"name": "bsky.app"/"name": "aiat"/g' package.json
+
+ echo "Aiat configuration applied"
+}
+
+function at-social-app-aiat-logo() {
+ d_=$d/repos/social-app
+ custom=$d/social-app-custom
+
+ echo "applying Aiat logo"
+
+ # Create logo directory if not exists
+ mkdir -p ${custom}/assets
+
+ # Copy logo if exists in custom folder
+ if [ -f ${custom}/assets/icon.png ]; then
+ cp ${custom}/assets/icon.png ${d_}/assets/app-icons/ios_icon_default_next.png
+ echo "Aiat logo applied"
+ else
+ echo "Warning: Logo file not found at ${custom}/assets/icon.png"
+ echo "Please add your logo file there"
+ fi
+}
+
+function at-social-app-custom-screens() {
+ d_=$d/repos/social-app
+ custom=$d/social-app-custom
+
+ echo "applying custom screens"
+
+ # Copy custom screen files
+ cp ${custom}/PrivacyPolicy.screen.tsx ${d_}/src/view/screens/PrivacyPolicy.tsx
+ cp ${custom}/Support.screen.tsx ${d_}/src/view/screens/Support.tsx
+ cp ${custom}/LicenseNotice.tsx ${d_}/src/components/custom/
+
+ echo "custom screens applied"
+}
+
+
diff --git a/patching/8980-social-app-disable-external-services.diff b/patching/8980-social-app-disable-external-services.diff
new file mode 100644
index 0000000..74ffc22
--- /dev/null
+++ b/patching/8980-social-app-disable-external-services.diff
@@ -0,0 +1,17 @@
+--- a/src/state/geolocation/const.ts
++++ b/src/state/geolocation/const.ts
+@@ -3,9 +3,10 @@ import {BAPP_CONFIG_DEV_URL, IS_DEV} from '#/env'
+ import {type Device} from '#/storage'
+
+ export const IPCC_URL = `https://bsky.app/ipcc`
+-export const BAPP_CONFIG_URL_PROD = `https://ip.bsky.app/config`
+-export const BAPP_CONFIG_URL = IS_DEV
+- ? (BAPP_CONFIG_DEV_URL ?? BAPP_CONFIG_URL_PROD)
+- : BAPP_CONFIG_URL_PROD
++// Disabled for self-hosted environment to avoid CORS errors
++// export const BAPP_CONFIG_URL_PROD = `https://ip.bsky.app/config`
++// export const BAPP_CONFIG_URL = IS_DEV
++// ? (BAPP_CONFIG_DEV_URL ?? BAPP_CONFIG_URL_PROD)
++// : BAPP_CONFIG_URL_PROD
++export const BAPP_CONFIG_URL = null
+ export const GEOLOCATION_CONFIG_URL = BAPP_CONFIG_URL
diff --git a/social-app-custom/.keep b/social-app-custom/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/social-app-custom/AppInfo.tsx b/social-app-custom/AppInfo.tsx
new file mode 100644
index 0000000..6242b12
--- /dev/null
+++ b/social-app-custom/AppInfo.tsx
@@ -0,0 +1,134 @@
+import React from 'react'
+import {View, Text, StyleSheet, Pressable, Linking} from 'react-native'
+
+interface AppInfoProps {
+ onLinkPress?: (url: string) => void
+}
+
+export default function AppInfo({onLinkPress}: AppInfoProps) {
+ const handleLinkPress = (url: string) => {
+ if (onLinkPress) {
+ onLinkPress(url)
+ } else {
+ Linking.openURL(url)
+ }
+ }
+
+ return (
+
+
+ About This App
+
+ This is a customized AT Protocol social networking client. It allows you to
+ connect to any Personal Data Server (PDS) and participate in the decentralized
+ social network.
+
+
+
+
+ Key Features
+
+ • Connect to any AT Protocol PDS
+ • Post text, images, and videos
+ • Follow users and view timelines
+ • Customize feeds and moderation settings
+ • Direct messaging support
+
+
+
+
+ Open Source
+
+ This application is based on the Bluesky social-app, licensed under the MIT
+ License. The original source code is available at:
+
+
+ handleLinkPress('https://github.com/bluesky-social/social-app')
+ }>
+ github.com/bluesky-social/social-app
+
+
+
+
+ AT Protocol
+
+ This app uses the AT Protocol (Authenticated Transfer Protocol), an open and
+ decentralized standard for social applications.
+
+ handleLinkPress('https://atproto.com')}>
+ atproto.com
+
+
+
+
+ License
+
+ Copyright 2023–2025 Bluesky Social PBC
+
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software.
+
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
+
+
+
+
+ Contact
+ handleLinkPress('https://syu.is')}>
+ https://syu.is
+
+
+
+
+ Version 1.0.0
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ section: {
+ marginBottom: 24,
+ },
+ sectionTitle: {
+ fontSize: 20,
+ fontWeight: '600',
+ color: '#1d1d1f',
+ marginBottom: 12,
+ },
+ paragraph: {
+ fontSize: 15,
+ lineHeight: 22,
+ color: '#3a3a3c',
+ marginBottom: 8,
+ },
+ list: {
+ marginLeft: 8,
+ marginTop: 8,
+ },
+ listItem: {
+ fontSize: 15,
+ lineHeight: 24,
+ color: '#3a3a3c',
+ },
+ link: {
+ fontSize: 15,
+ color: '#007aff',
+ textDecorationLine: 'underline',
+ marginTop: 8,
+ },
+ versionText: {
+ fontSize: 13,
+ color: '#8e8e93',
+ fontStyle: 'italic',
+ },
+})
diff --git a/social-app-custom/LicenseNotice.tsx b/social-app-custom/LicenseNotice.tsx
new file mode 100644
index 0000000..496d367
--- /dev/null
+++ b/social-app-custom/LicenseNotice.tsx
@@ -0,0 +1,95 @@
+import React from 'react'
+import {View, Text, StyleSheet, Pressable, Linking} from 'react-native'
+
+export default function LicenseNotice() {
+ return (
+
+ Open Source Licenses
+
+
+ Bluesky Social App
+ MIT License
+ Copyright 2023–2025 Bluesky Social PBC
+
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+
+
+ Linking.openURL('https://github.com/bluesky-social/social-app')
+ }>
+ View Source Code
+
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 16,
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ marginBottom: 20,
+ color: '#1d1d1f',
+ },
+ section: {
+ marginBottom: 24,
+ padding: 16,
+ backgroundColor: '#f5f5f7',
+ borderRadius: 8,
+ },
+ projectName: {
+ fontSize: 18,
+ fontWeight: '600',
+ marginBottom: 8,
+ color: '#1d1d1f',
+ },
+ license: {
+ fontSize: 14,
+ fontWeight: '500',
+ color: '#007aff',
+ marginBottom: 4,
+ },
+ copyright: {
+ fontSize: 13,
+ color: '#3a3a3c',
+ marginBottom: 12,
+ },
+ licenseText: {
+ fontSize: 12,
+ lineHeight: 18,
+ color: '#3a3a3c',
+ marginBottom: 12,
+ },
+ link: {
+ fontSize: 14,
+ color: '#007aff',
+ textDecorationLine: 'underline',
+ marginTop: 8,
+ },
+})
diff --git a/social-app-custom/PrivacyContent.tsx b/social-app-custom/PrivacyContent.tsx
new file mode 100644
index 0000000..d780104
--- /dev/null
+++ b/social-app-custom/PrivacyContent.tsx
@@ -0,0 +1,163 @@
+import React from 'react'
+import {View, Text, StyleSheet, Pressable, Linking} from 'react-native'
+
+interface PrivacyContentProps {
+ onLinkPress?: (url: string) => void
+}
+
+export default function PrivacyContent({onLinkPress}: PrivacyContentProps) {
+ const handleLinkPress = (url: string) => {
+ if (onLinkPress) {
+ onLinkPress(url)
+ } else {
+ Linking.openURL(url)
+ }
+ }
+
+ return (
+
+
+ Introduction
+
+ This Privacy Policy explains how this AT Protocol client application
+ (hereinafter referred to as "the App") handles personal information.
+ Please read this policy carefully before using the App.
+
+
+
+
+ Information We Collect
+
+ The App may collect and use the following information:
+
+
+ 1. Information Collected Automatically
+
+ • Device information (model, OS version)
+ • App usage data (sessions, features used)
+ • Crash logs and performance data
+
+
+ 2. Information Provided by Users
+
+
+ • DID (Decentralized Identifier) and handle for authentication
+
+ • Posts, media, and social interactions
+ • Profile information (avatar, display name, bio)
+
+
+
+
+ Important: Your data is stored on your chosen PDS (Personal Data Server).
+ This app does not store your content on our servers.
+
+
+
+
+
+ How We Use Your Information
+
+
+ • To provide AT Protocol social networking features
+
+ • To improve app performance and user experience
+ • To diagnose and fix technical issues
+
+
+
+
+ Data Sharing
+
+ The App interacts with your chosen PDS and AppView services. Your posts and
+ profile information are shared according to the AT Protocol specification and
+ your privacy settings.
+
+
+
+
+ Your Rights
+
+ You have the right to access, modify, or delete your data through your PDS.
+ You can also switch to a different PDS at any time while maintaining your
+ identity.
+
+
+
+
+ Contact
+
+ For questions about this Privacy Policy, please contact:
+
+ handleLinkPress('https://syu.is')}>
+ https://syu.is
+
+
+
+
+ Last Updated: December 3, 2025
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ section: {
+ marginBottom: 24,
+ },
+ sectionTitle: {
+ fontSize: 20,
+ fontWeight: '600',
+ color: '#1d1d1f',
+ marginBottom: 12,
+ },
+ subTitle: {
+ fontSize: 16,
+ fontWeight: '500',
+ color: '#1d1d1f',
+ marginTop: 12,
+ marginBottom: 8,
+ },
+ paragraph: {
+ fontSize: 15,
+ lineHeight: 22,
+ color: '#3a3a3c',
+ marginBottom: 8,
+ },
+ list: {
+ marginLeft: 8,
+ marginTop: 8,
+ },
+ listItem: {
+ fontSize: 15,
+ lineHeight: 24,
+ color: '#3a3a3c',
+ },
+ highlight: {
+ backgroundColor: '#fff3cd',
+ borderLeftWidth: 4,
+ borderLeftColor: '#ffc107',
+ padding: 12,
+ marginTop: 12,
+ borderRadius: 4,
+ },
+ highlightText: {
+ fontSize: 14,
+ lineHeight: 20,
+ color: '#856404',
+ },
+ link: {
+ fontSize: 15,
+ color: '#007aff',
+ textDecorationLine: 'underline',
+ marginTop: 8,
+ },
+ lastUpdated: {
+ fontSize: 13,
+ color: '#8e8e93',
+ fontStyle: 'italic',
+ },
+})
diff --git a/social-app-custom/PrivacyPolicy.screen.tsx b/social-app-custom/PrivacyPolicy.screen.tsx
new file mode 100644
index 0000000..df5d5c8
--- /dev/null
+++ b/social-app-custom/PrivacyPolicy.screen.tsx
@@ -0,0 +1,42 @@
+import React from 'react'
+import {View} from 'react-native'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useFocusEffect} from '@react-navigation/native'
+
+import {usePalette} from '#/lib/hooks/usePalette'
+import {
+ type CommonNavigatorParams,
+ type NativeStackScreenProps,
+} from '#/lib/routes/types'
+import {s} from '#/lib/styles'
+import {useSetMinimalShellMode} from '#/state/shell'
+import {ScrollView} from '#/view/com/util/Views'
+import * as Layout from '#/components/Layout'
+import {ViewHeader} from '../com/util/ViewHeader'
+import PrivacyContent from '#/components/custom/PrivacyContent'
+
+type Props = NativeStackScreenProps
+export const PrivacyPolicyScreen = (_props: Props) => {
+ const pal = usePalette('default')
+ const {_} = useLingui()
+ const setMinimalShellMode = useSetMinimalShellMode()
+
+ useFocusEffect(
+ React.useCallback(() => {
+ setMinimalShellMode(false)
+ }, [setMinimalShellMode]),
+ )
+
+ return (
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/social-app-custom/Support.screen.tsx b/social-app-custom/Support.screen.tsx
new file mode 100644
index 0000000..3fddf92
--- /dev/null
+++ b/social-app-custom/Support.screen.tsx
@@ -0,0 +1,38 @@
+import React from 'react'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useFocusEffect} from '@react-navigation/native'
+
+import {usePalette} from '#/lib/hooks/usePalette'
+import {
+ type CommonNavigatorParams,
+ type NativeStackScreenProps,
+} from '#/lib/routes/types'
+import {s} from '#/lib/styles'
+import {useSetMinimalShellMode} from '#/state/shell'
+import {ViewHeader} from '#/view/com/util/ViewHeader'
+import {ScrollView} from '#/view/com/util/Views'
+import * as Layout from '#/components/Layout'
+import AppInfo from '#/components/custom/AppInfo'
+
+type Props = NativeStackScreenProps
+export const SupportScreen = (_props: Props) => {
+ const pal = usePalette('default')
+ const setMinimalShellMode = useSetMinimalShellMode()
+ const {_} = useLingui()
+
+ useFocusEffect(
+ React.useCallback(() => {
+ setMinimalShellMode(false)
+ }, [setMinimalShellMode]),
+ )
+
+ return (
+
+
+
+
+
+
+ )
+}
diff --git a/social-app-custom/app.config.patch.js b/social-app-custom/app.config.patch.js
new file mode 100644
index 0000000..136a4d9
--- /dev/null
+++ b/social-app-custom/app.config.patch.js
@@ -0,0 +1,9 @@
+// Aiat app configuration overrides
+module.exports = {
+ name: 'Aiat',
+ slug: 'aiat',
+ scheme: 'aiat',
+ owner: 'syui', // Your Expo account
+ bundleIdentifier: 'ai.syui.at',
+ // Icon will be set separately
+}