Buat Aplikasi Bookmarking Dengan FaunaDB, Netlify, dan 11ty

Diterbitkan: 2022-03-10
Ringkasan cepat Pada artikel ini, kita akan membuat situs bookmark pribadi menggunakan FaunaDB, Netlify Functions dan 11ty file data.

Revolusi JAMstack (JavaScript, API, dan Markup) sedang berjalan lancar. Situs statis aman, cepat, andal, dan menyenangkan untuk dikerjakan. Di jantung JAMstack adalah generator situs statis (SSG) yang menyimpan data Anda sebagai file datar: Penurunan harga, YAML, JSON, HTML, dan sebagainya. Terkadang, mengelola data dengan cara ini bisa sangat rumit. Terkadang, kita masih membutuhkan database.

Dengan mengingat hal itu, Netlify — host situs statis dan FaunaDB — database cloud tanpa server — berkolaborasi untuk mempermudah penggabungan kedua sistem.

Mengapa Sebuah Situs Bookmarking?

JAMstack sangat bagus untuk banyak penggunaan profesional, tetapi salah satu aspek favorit saya dari rangkaian teknologi ini adalah hambatan masuknya yang rendah untuk alat dan proyek pribadi.

Ada banyak produk bagus di pasaran untuk sebagian besar aplikasi yang dapat saya buat, tetapi tidak ada yang benar-benar disiapkan untuk saya. Tidak ada yang akan memberi saya kendali penuh atas konten saya. Tidak ada yang akan datang tanpa biaya (uang atau informasi).

Dengan mengingat hal itu, kita dapat membuat layanan mini kita sendiri menggunakan metode JAMstack. Dalam hal ini, kami akan membuat situs untuk menyimpan dan mempublikasikan artikel menarik yang saya temukan dalam bacaan teknologi harian saya.

Saya menghabiskan banyak waktu membaca artikel yang telah dibagikan di Twitter. Ketika saya menyukainya, saya menekan ikon "hati". Kemudian, dalam beberapa hari, hampir tidak mungkin untuk menemukan dengan masuknya favorit baru. Saya ingin membangun sesuatu yang sedekat mungkin dengan “hati”, tetapi yang saya miliki dan kendalikan.

Bagaimana kita akan melakukannya? Saya senang Anda bertanya.

Tertarik untuk mendapatkan kodenya? Anda dapat mengambilnya di Github atau langsung menyebarkannya ke Netlify dari repositori itu! Lihatlah produk jadi di sini.

Teknologi kami

Fungsi Hosting Dan Tanpa Server: Netlify

Untuk fungsi hosting dan tanpa server, kami akan menggunakan Netlify. Sebagai bonus tambahan, dengan kolaborasi baru yang disebutkan di atas, CLI Netlify — “Netlify Dev” — akan secara otomatis terhubung ke FaunaDB dan menyimpan kunci API kami sebagai variabel lingkungan.

Basis data: FaunaDB

FaunaDB adalah database NoSQL "tanpa server". Kami akan menggunakannya untuk menyimpan data bookmark kami.

Generator Situs Statis: 11ty

Saya sangat percaya pada HTML. Karena itu, tutorial tidak akan menggunakan JavaScript front-end untuk merender bookmark kita. Sebagai gantinya, kami akan menggunakan 11ty sebagai generator situs statis. 11ty memiliki fungsionalitas data bawaan yang membuat pengambilan data dari API semudah menulis beberapa fungsi JavaScript singkat.

Pintasan iOS

Kami akan membutuhkan cara mudah untuk mengirim data ke database kami. Dalam hal ini, kami akan menggunakan aplikasi Pintasan iOS. Ini juga dapat dikonversi ke bookmarklet JavaScript Android atau desktop.

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Menyiapkan FaunaDB Melalui Netlify Dev

Apakah Anda sudah mendaftar ke FaunaDB atau Anda perlu membuat akun baru, cara termudah untuk membuat tautan antara FaunaDB dan Netlify adalah melalui CLI Netlify: Netlify Dev. Anda dapat menemukan instruksi lengkap dari FaunaDB di sini atau ikuti di bawah ini.

Netlify Dev berjalan di proyek akhir dengan nama variabel lingkungan kami menunjukkan
Netlify Dev berjalan di proyek akhir dengan menampilkan nama variabel lingkungan kami (Pratinjau besar)

Jika Anda belum menginstal ini, Anda dapat menjalankan perintah berikut di Terminal:

 npm install netlify-cli -g

Dari dalam direktori proyek Anda, jalankan perintah berikut:

 netlify init // This will connect your project to a Netlify project netlify addons:create fauna // This will install the FaunaDB "addon" netlify addons:auth fauna // This command will run you through connecting your account or setting up an account

Setelah semuanya terhubung, Anda dapat menjalankan netlify dev di proyek Anda. Ini akan menjalankan skrip build apa pun yang kami siapkan, tetapi juga terhubung ke layanan Netlify dan FaunaDB dan mengambil variabel lingkungan apa pun yang diperlukan. Berguna!

Membuat Data Pertama Kami

Dari sini, kita akan masuk ke FaunaDB dan membuat kumpulan data pertama kita. Kita akan mulai dengan membuat Database baru yang disebut “bookmark”. Di dalam Database, kami memiliki Koleksi, Dokumen, dan Indeks.

Tangkapan layar konsol FaunaDB dengan data
Tangkapan layar konsol FaunaDB dengan data (Pratinjau besar)

Koleksi adalah sekelompok data yang dikategorikan. Setiap bagian data mengambil bentuk Dokumen. Dokumen adalah “catatan tunggal yang dapat diubah dalam database FaunaDB,” menurut dokumentasi Fauna. Anda dapat menganggap Koleksi sebagai tabel database tradisional dan Dokumen sebagai baris.

Untuk aplikasi kami, kami membutuhkan satu Koleksi, yang akan kami sebut "tautan". Setiap dokumen dalam Koleksi "tautan" akan menjadi objek JSON sederhana dengan tiga properti. Untuk memulai, kami akan menambahkan Dokumen baru yang akan kami gunakan untuk membangun pengambilan data pertama kami.

 { "url": "https://css-irl.info/debugging-css-grid-part-2-what-the-fraction/", "pageTitle": "CSS { In Real Life } | Debugging CSS Grid – Part 2: What the Fr(action)?", "description": "CSS In Real Life is a blog covering CSS topics and useful snippets on the web's most beautiful language. Published by Michelle Barker, front end developer at Ordoo and CSS superfan." }

Ini menciptakan dasar untuk informasi yang kita perlukan dari bookmark kita serta memberi kita kumpulan data pertama untuk menarik ke dalam template kita.

Jika Anda seperti saya, Anda ingin segera melihat hasil kerja keras Anda. Ayo dapatkan sesuatu di halaman!

Memasang 11ty Dan Menarik Data Ke Dalam Template

Karena kita ingin bookmark dirender dalam HTML dan tidak diambil oleh browser, kita memerlukan sesuatu untuk melakukan rendering. Ada banyak cara hebat untuk melakukannya, tetapi untuk kemudahan dan kekuatan, saya suka menggunakan generator situs statis 11ty.

Karena 11ty adalah generator situs statis JavaScript, kita dapat menginstalnya melalui NPM.

 npm install --save @11ty/eleventy

Dari instalasi itu, kita dapat menjalankan eleventy atau eleventy --serve dalam proyek kita untuk aktif dan berjalan.

Netlify Dev akan sering mendeteksi 11ty sebagai persyaratan dan menjalankan perintah untuk kita. Agar ini berfungsi - dan memastikan kami siap untuk menerapkan, kami juga dapat membuat perintah "serve" dan "build" di package.json kami.

 "scripts": { "build": "npx eleventy", "serve": "npx eleventy --serve" }

File Data 11ty

Sebagian besar generator situs statis memiliki gagasan tentang "file data" bawaan. Biasanya, file-file ini adalah file JSON atau YAML yang memungkinkan Anda menambahkan informasi tambahan ke situs Anda.

Di 11ty, Anda dapat menggunakan file data JSON atau file data JavaScript. Dengan memanfaatkan file JavaScript, kita sebenarnya dapat membuat panggilan API dan mengembalikan data secara langsung ke dalam template.

Secara default, 11ty ingin file data disimpan dalam direktori _data . Anda kemudian dapat mengakses data dengan menggunakan nama file sebagai variabel di template Anda. Dalam kasus kami, kami akan membuat file di _data/bookmarks.js dan mengaksesnya melalui nama variabel {{ bookmarks }} .

Jika Anda ingin menggali lebih dalam tentang konfigurasi file data, Anda dapat membaca contoh di dokumentasi 11ty atau lihat tutorial ini tentang menggunakan file data 11ty dengan Meetup API.

File akan menjadi modul JavaScript. Jadi agar apa pun berfungsi, kita perlu mengekspor data atau fungsi kita. Dalam kasus kami, kami akan mengekspor fungsi.

 module.exports = async function() { const data = mapBookmarks(await getBookmarks()); return data.reverse() }

Mari kita hancurkan itu. Kami memiliki dua fungsi yang melakukan pekerjaan utama kami di sini: mapBookmarks() dan getBookmarks() .

Fungsi getBookmarks() akan mengambil data kita dari database FaunaDB dan mapBookmarks() akan mengambil array bookmark dan merestrukturisasinya agar berfungsi lebih baik untuk template kita.

Mari gali lebih dalam getBookmarks() .

getBookmarks()

Pertama, kita perlu menginstal dan menginisialisasi instance driver JavaScript FaunaDB.

 npm install --save faunadb

Sekarang setelah kita menginstalnya, mari tambahkan ke bagian atas file data kita. Kode ini langsung dari dokumen Fauna.

 // Requires the Fauna module and sets up the query module, which we can use to create custom queries. const faunadb = require('faunadb'), q = faunadb.query; // Once required, we need a new instance with our secret var adminClient = new faunadb.Client({ secret: process.env.FAUNADB_SERVER_SECRET });

Setelah itu, kita dapat membuat fungsi kita. Kami akan mulai dengan membuat kueri pertama kami menggunakan metode bawaan pada driver. Bit kode pertama ini akan mengembalikan referensi database yang dapat kita gunakan untuk mendapatkan data lengkap untuk semua tautan yang kita bookmark. Kami menggunakan metode Paginate , sebagai pembantu untuk mengelola status kursor jika kami memutuskan untuk membuat paginasi data sebelum menyerahkannya ke 11ty. Dalam kasus kami, kami hanya akan mengembalikan semua referensi.

Dalam contoh ini, saya berasumsi Anda menginstal dan menghubungkan FaunaDB melalui Netlify Dev CLI. Dengan menggunakan proses ini, Anda mendapatkan variabel lingkungan lokal dari rahasia FaunaDB. Jika Anda tidak menginstalnya dengan cara ini atau tidak menjalankan netlify dev di proyek Anda, Anda memerlukan paket seperti dotenv untuk membuat variabel lingkungan. Anda juga harus menambahkan variabel lingkungan Anda ke konfigurasi situs Netlify Anda untuk membuat penerapan berfungsi nanti.

 adminClient.query(q.Paginate( q.Match( // Match the reference below q.Ref("indexes/all_links") // Reference to match, in this case, our all_links index ) )) .then( response => { ... })

Kode ini akan mengembalikan larik dari semua tautan kami dalam bentuk referensi. Kami sekarang dapat membuat daftar kueri untuk dikirim ke database kami.

 adminClient.query(...) .then((response) => { const linkRefs = response.data; // Get just the references for the links from the response const getAllLinksDataQuery = linkRefs.map((ref) => { return q.Get(ref) // Return a Get query based on the reference passed in }) return adminClient.query(getAllLinksDataQuery).then(ret => { return ret // Return an array of all the links with full data }) }).catch(...)

Dari sini, kita hanya perlu membersihkan data yang dikembalikan. Di situlah mapBookmarks() masuk!

mapBookmarks()

Dalam fungsi ini, kita berurusan dengan dua aspek data.

Pertama, kita mendapatkan dateTime gratis di FaunaDB. Untuk setiap data yang dibuat, ada properti timestamp ( ts ). Itu tidak diformat dengan cara yang membuat filter tanggal default Liquid senang, jadi mari kita perbaiki itu.

 function mapBookmarks(data) { return data.map(bookmark => { const dateTime = new Date(bookmark.ts / 1000); ... }) }

Dengan itu, kita bisa membangun objek baru untuk data kita. Dalam hal ini, itu akan memiliki properti time , dan kami akan menggunakan operator Spread untuk merusak objek data kami untuk membuat semuanya hidup di satu tingkat.

 function mapBookmarks(data) { return data.map(bookmark => { const dateTime = new Date(bookmark.ts / 1000); return { time: dateTime, ...bookmark.data } }) }

Inilah data kami sebelum fungsi kami:

 { ref: Ref(Collection("links"), "244778237839802888"), ts: 1569697568650000, data: { url: 'https://sample.com', pageTitle: 'Sample title', description: 'An escaped description goes here' } }

Berikut data kami setelah fungsi kami:

 { time: 1569697568650, url: 'https://sample.com', pageTitle: 'Sample title' description: 'An escaped description goes here' }

Sekarang, kami memiliki data yang diformat dengan baik yang siap untuk template kami!

Mari kita menulis template sederhana. Kami akan mengulangi bookmark kami dan memvalidasi bahwa masing-masing memiliki pageTitle dan url sehingga kami tidak terlihat konyol.

 <div class="bookmarks"> {% for link in bookmarks %} {% if link.url and link.pageTitle %} // confirms there's both title AND url for safety <div class="bookmark"> <h2><a href="{{ link.url }}">{{ link.pageTitle }}</a></h2> <p>Saved on {{ link.time | date: "%b %d, %Y" }}</p> {% if link.description != "" %} <p>{{ link.description }}</p> {% endif %} </div> {% endif %} {% endfor %} </div>

Kami sekarang mencerna dan menampilkan data dari FaunaDB. Mari luangkan waktu sejenak dan pikirkan betapa menyenangkannya ini menghasilkan HTML murni dan tidak perlu mengambil data di sisi klien!

Tapi itu tidak cukup untuk membuat aplikasi ini berguna bagi kami. Mari kita cari cara yang lebih baik daripada menambahkan bookmark di konsol FaunaDB.

Masuk ke Fungsi Netlify

Add-on Fungsi Netlify adalah salah satu cara yang lebih mudah untuk menerapkan fungsi lambda AWS. Karena tidak ada langkah konfigurasi, ini sempurna untuk proyek DIY di mana Anda hanya ingin menulis kode.

Fungsi ini akan hidup di URL di proyek Anda yang terlihat seperti ini: https://myproject.com/.netlify/functions/bookmarks dengan asumsi file yang kami buat di folder fungsi kami adalah bookmarks.js .

Aliran Dasar

  1. Berikan URL sebagai parameter kueri ke URL fungsi kami.
  2. Gunakan fungsi untuk memuat URL dan mengikis judul dan deskripsi halaman jika tersedia.
  3. Format detail untuk FaunaDB.
  4. Dorong detailnya ke Koleksi FaunaDB kami.
  5. Membangun kembali situs.

Persyaratan

Kami memiliki beberapa paket yang kami perlukan saat kami membangun ini. Kami akan menggunakan CLI netlify-lambda untuk membangun fungsi kami secara lokal. request-promise adalah paket yang akan kita gunakan untuk membuat permintaan. Cheerio.js adalah paket yang akan kita gunakan untuk mengikis item tertentu dari halaman yang kita minta (pikirkan jQuery untuk Node). Dan terakhir, kita membutuhkan FaunaDb (yang seharusnya sudah diinstal.

 npm install --save netlify-lambda request-promise cheerio

Setelah itu terinstal, mari konfigurasikan proyek kita untuk membangun dan melayani fungsi secara lokal.

Kami akan memodifikasi skrip "build" dan "serve" kami di package.json kami agar terlihat seperti ini:

 "scripts": { "build": "npx netlify-lambda build lambda --config ./webpack.functions.js && npx eleventy", "serve": "npx netlify-lambda build lambda --config ./webpack.functions.js && npx eleventy --serve" }

Peringatan: Ada kesalahan dengan driver NodeJS Fauna saat mengkompilasi dengan Webpack, yang digunakan Fungsi Netlify untuk membangun. Untuk menyiasatinya, kita perlu mendefinisikan file konfigurasi untuk Webpack. Anda dapat menyimpan kode berikut ke baruatau yang sudah adawebpack.config.js .

 const webpack = require('webpack'); module.exports = { plugins: [ new webpack.DefinePlugin({ "global.GENTLY": false }) ] };

Setelah file ini ada, ketika kita menggunakan perintah netlify-lambda , kita harus memberitahunya untuk menjalankan dari konfigurasi ini. Inilah sebabnya mengapa skrip "serve" dan "build kami menggunakan nilai --config untuk perintah itu.

Fungsi Rumah Tangga

Untuk menjaga file Fungsi utama kami sebersih mungkin, kami akan membuat fungsi kami di direktori bookmarks terpisah dan mengimpornya ke file Fungsi utama kami.

 import { getDetails, saveBookmark } from "./bookmarks/create";

getDetails(url)

Fungsi getDetails() akan mengambil URL, diteruskan dari handler yang diekspor. Dari sana, kami akan menjangkau situs di URL itu dan mengambil bagian halaman yang relevan untuk disimpan sebagai data untuk bookmark kami.

Kita mulai dengan membutuhkan paket NPM yang kita butuhkan:

 const rp = require('request-promise'); const cheerio = require('cheerio');

Kemudian, kita akan menggunakan modul request-promise untuk mengembalikan string HTML untuk halaman yang diminta dan meneruskannya ke cheerio untuk memberi kita antarmuka yang sangat mirip dengan jQuery.

 const getDetails = async function(url) { const data = rp(url).then(function(htmlString) { const $ = cheerio.load(htmlString); ... }

Dari sini, kita perlu mendapatkan judul halaman dan deskripsi meta. Untuk melakukannya, kami akan menggunakan penyeleksi seperti yang Anda lakukan di jQuery.

Catatan: Dalam kode ini, kami menggunakan 'head > title' sebagai pemilih untuk mendapatkan judul halaman. Jika Anda tidak menentukan ini, Anda mungkin mendapatkan <title> di dalam semua SVG pada halaman, yang kurang ideal.

 const getDetails = async function(url) { const data = rp(url).then(function(htmlString) { const $ = cheerio.load(htmlString); const title = $('head > title').text(); // Get the text inside the tag const description = $('meta[name="description"]').attr('content'); // Get the text of the content attribute // Return out the data in the structure we expect return { pageTitle: title, description: description }; }); return data //return to our main function }

Dengan data di tangan, saatnya untuk mengirim bookmark kami ke Koleksi kami di FaunaDB!

saveBookmark(details)

Untuk fungsi simpan kami, kami ingin meneruskan detail yang kami peroleh dari getDetails serta URL sebagai objek tunggal. Operator Spread menyerang lagi!

 const savedResponse = await saveBookmark({url, ...details});

Dalam file create.js kami, kami juga perlu meminta dan mengatur driver FaunaDB kami. Ini akan terlihat sangat familier dari file data 11ty kami.

 const faunadb = require('faunadb'), q = faunadb.query; const adminClient = new faunadb.Client({ secret: process.env.FAUNADB_SERVER_SECRET });

Setelah kami menyelesaikannya, kami dapat membuat kode.

Pertama, kita perlu memformat detail kita menjadi struktur data yang diharapkan Fauna untuk kueri kita. Fauna mengharapkan objek dengan properti data yang berisi data yang ingin kita simpan.

 const saveBookmark = async function(details) { const data = { data: details }; ... }

Kemudian kami akan membuka kueri baru untuk ditambahkan ke Koleksi kami. Dalam hal ini, kami akan menggunakan pembantu kueri kami dan menggunakan metode Buat. Create() membutuhkan dua argumen. Pertama adalah Koleksi di mana kita ingin menyimpan data kita dan yang kedua adalah data itu sendiri.

Setelah kami menyimpan, kami mengembalikan kesuksesan atau kegagalan ke pawang kami.

 const saveBookmark = async function(details) { const data = { data: details }; return adminClient.query(q.Create(q.Collection("links"), data)) .then((response) => { /* Success! return the response with statusCode 200 */ return { statusCode: 200, body: JSON.stringify(response) } }).catch((error) => { /* Error! return the error with statusCode 400 */ return { statusCode: 400, body: JSON.stringify(error) } }) }

Mari kita lihat file Function selengkapnya.

 import { getDetails, saveBookmark } from "./bookmarks/create"; import { rebuildSite } from "./utilities/rebuild"; // For rebuilding the site (more on that in a minute) exports.handler = async function(event, context) { try { const url = event.queryStringParameters.url; // Grab the URL const details = await getDetails(url); // Get the details of the page const savedResponse = await saveBookmark({url, ...details}); //Save the URL and the details to Fauna if (savedResponse.statusCode === 200) { // If successful, return success and trigger a Netlify build await rebuildSite(); return { statusCode: 200, body: savedResponse.body } } else { return savedResponse //or else return the error } } catch (err) { return { statusCode: 500, body: `Error: ${err}` }; } };

rebuildSite()

Mata yang jeli akan melihat bahwa kita memiliki satu fungsi lagi yang diimpor ke handler kita: rebuildSite() . Fungsi ini akan menggunakan fungsionalitas Deploy Hook Netlify untuk membangun kembali situs kami dari data baru setiap kali kami mengirimkan penyimpanan bookmark baru — berhasil —.

Dalam pengaturan situs Anda di Netlify, Anda dapat mengakses pengaturan Build & Deploy dan membuat "Build Hook" baru. Hooks memiliki nama yang muncul di bagian Deploy dan opsi untuk cabang non-master untuk diterapkan jika Anda menginginkannya. Dalam kasus kami, kami akan menamakannya "new_link" dan menyebarkan cabang master kami.

Referensi visual untuk pengaturan build hook Admin Netlify
Referensi visual untuk pengaturan build hook Admin Netlify (Pratinjau besar)

Dari sana, kita hanya perlu mengirim permintaan POST ke URL yang disediakan.

Kami membutuhkan cara untuk membuat permintaan dan karena kami telah menginstal request-promise , kami akan terus menggunakan paket itu dengan memintanya di bagian atas file kami.

 const rp = require('request-promise'); const rebuildSite = async function() { var options = { method: 'POST', uri: 'https://api.netlify.com/build_hooks/5d7fa6175504dfd43377688c', body: {}, json: true }; const returned = await rp(options).then(function(res) { console.log('Successfully hit webhook', res); }).catch(function(err) { console.log('Error:', err); }); return returned } 
Demo penyiapan Fungsi Netlify dan penyiapan Pintasan iOS digabungkan

Menyiapkan Pintasan iOS

Jadi, kami memiliki database, cara untuk menampilkan data, dan fungsi untuk menambahkan data, tetapi kami masih belum terlalu ramah pengguna.

Netlify menyediakan URL untuk fungsi Lambda kami, tetapi URL tersebut tidak menyenangkan untuk diketik ke perangkat seluler. Kami juga harus memberikan URL sebagai parameter kueri ke dalamnya. Itu BANYAK usaha. Bagaimana kita bisa melakukan ini sesedikit mungkin?

Referensi visual untuk pengaturan fungsi Pintasan kami
Referensi visual untuk penyiapan fungsi Pintasan kami (Pratinjau besar)

Aplikasi Pintasan Apple memungkinkan pembuatan item khusus masuk ke lembar berbagi Anda. Di dalam pintasan ini, kami dapat mengirim berbagai jenis permintaan data yang dikumpulkan dalam proses berbagi.

Berikut adalah Pintasan langkah demi langkah:

  1. Terima item apa pun dan simpan item itu di blok "teks".
  2. Lewati teks itu ke dalam blok "Scripting" ke penyandian URL (untuk berjaga-jaga).
  3. Teruskan string itu ke dalam blok URL dengan URL Fungsi Netlify kami dan parameter kueri url .
  4. Dari "Jaringan" gunakan blok "Dapatkan konten" ke POST ke JSON ke URL kami.
  5. Opsional: Dari "Scripting" "Tampilkan" isi langkah terakhir (untuk mengonfirmasi data yang kami kirim).

Untuk mengakses ini dari menu berbagi, kami membuka pengaturan untuk Pintasan ini dan mengaktifkan opsi "Tampilkan di Lembar Bagikan".

Pada iOS13, "Tindakan" yang dibagikan ini dapat difavoritkan dan dipindahkan ke posisi tinggi dalam dialog.

Kami sekarang memiliki "aplikasi" yang berfungsi untuk berbagi bookmark di berbagai platform!

Berusaha lebih jauh!

Jika Anda terinspirasi untuk mencobanya sendiri, ada banyak kemungkinan lain untuk menambahkan fungsionalitas. Kegembiraan web DIY adalah Anda dapat membuat aplikasi semacam ini bekerja untuk Anda. Berikut adalah beberapa ide:

  1. Gunakan "kunci API" palsu untuk autentikasi cepat, sehingga pengguna lain tidak memposting ke situs Anda (milik saya menggunakan kunci API, jadi jangan coba-coba memposting ke sana!).
  2. Tambahkan fungsionalitas tag untuk mengatur bookmark.
  3. Tambahkan umpan RSS untuk situs Anda sehingga orang lain dapat berlangganan.
  4. Kirim email pengumpulan mingguan secara terprogram untuk tautan yang telah Anda tambahkan.

Sungguh, langit adalah batasnya, jadi mulailah bereksperimen!